• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static android.content.res.Resources.ID_NULL;
20 import static android.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.Configuration;
67 import android.content.res.Resources;
68 import android.content.res.TypedArray;
69 import android.graphics.Bitmap;
70 import android.graphics.BlendMode;
71 import android.graphics.Canvas;
72 import android.graphics.Color;
73 import android.graphics.Insets;
74 import android.graphics.Interpolator;
75 import android.graphics.LinearGradient;
76 import android.graphics.Matrix;
77 import android.graphics.Outline;
78 import android.graphics.Paint;
79 import android.graphics.PixelFormat;
80 import android.graphics.Point;
81 import android.graphics.PorterDuff;
82 import android.graphics.PorterDuffXfermode;
83 import android.graphics.RecordingCanvas;
84 import android.graphics.Rect;
85 import android.graphics.RectF;
86 import android.graphics.Region;
87 import android.graphics.RenderEffect;
88 import android.graphics.RenderNode;
89 import android.graphics.Shader;
90 import android.graphics.drawable.ColorDrawable;
91 import android.graphics.drawable.Drawable;
92 import android.graphics.drawable.GradientDrawable;
93 import android.hardware.display.DisplayManagerGlobal;
94 import android.net.Uri;
95 import android.os.Build;
96 import android.os.Bundle;
97 import android.os.Handler;
98 import android.os.IBinder;
99 import android.os.Message;
100 import android.os.Parcel;
101 import android.os.Parcelable;
102 import android.os.RemoteCallback;
103 import android.os.RemoteException;
104 import android.os.SystemClock;
105 import android.os.Trace;
106 import android.sysprop.DisplayProperties;
107 import android.text.InputType;
108 import android.text.TextUtils;
109 import android.util.AttributeSet;
110 import android.util.FloatProperty;
111 import android.util.LayoutDirection;
112 import android.util.Log;
113 import android.util.LongSparseArray;
114 import android.util.LongSparseLongArray;
115 import android.util.Pair;
116 import android.util.Pools.SynchronizedPool;
117 import android.util.Property;
118 import android.util.SparseArray;
119 import android.util.SparseIntArray;
120 import android.util.StateSet;
121 import android.util.SuperNotCalledException;
122 import android.util.TypedValue;
123 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
124 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
125 import android.view.AccessibilityIterators.TextSegmentIterator;
126 import android.view.AccessibilityIterators.WordTextSegmentIterator;
127 import android.view.ContextMenu.ContextMenuInfo;
128 import android.view.InputDevice.InputSourceClass;
129 import android.view.Window.OnContentApplyWindowInsetsListener;
130 import android.view.WindowInsets.Type;
131 import android.view.WindowInsetsAnimation.Bounds;
132 import android.view.WindowManager.LayoutParams;
133 import android.view.accessibility.AccessibilityEvent;
134 import android.view.accessibility.AccessibilityEventSource;
135 import android.view.accessibility.AccessibilityManager;
136 import android.view.accessibility.AccessibilityNodeIdManager;
137 import android.view.accessibility.AccessibilityNodeInfo;
138 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
139 import android.view.accessibility.AccessibilityNodeProvider;
140 import android.view.accessibility.AccessibilityWindowInfo;
141 import android.view.animation.Animation;
142 import android.view.animation.AnimationUtils;
143 import android.view.animation.Transformation;
144 import android.view.autofill.AutofillId;
145 import android.view.autofill.AutofillManager;
146 import android.view.autofill.AutofillValue;
147 import android.view.contentcapture.ContentCaptureContext;
148 import android.view.contentcapture.ContentCaptureManager;
149 import android.view.contentcapture.ContentCaptureSession;
150 import android.view.displayhash.DisplayHash;
151 import android.view.displayhash.DisplayHashManager;
152 import android.view.displayhash.DisplayHashResultCallback;
153 import android.view.inputmethod.EditorInfo;
154 import android.view.inputmethod.InputConnection;
155 import android.view.inspector.InspectableProperty;
156 import android.view.inspector.InspectableProperty.EnumEntry;
157 import android.view.inspector.InspectableProperty.FlagEntry;
158 import android.view.translation.TranslationCapability;
159 import android.view.translation.TranslationSpec.DataFormat;
160 import android.view.translation.ViewTranslationCallback;
161 import android.view.translation.ViewTranslationRequest;
162 import android.view.translation.ViewTranslationResponse;
163 import android.widget.Checkable;
164 import android.widget.FrameLayout;
165 import android.widget.ScrollBarDrawable;
166 import android.window.OnBackInvokedDispatcher;
167 
168 import com.android.internal.R;
169 import com.android.internal.util.ArrayUtils;
170 import com.android.internal.util.FrameworkStatsLog;
171 import com.android.internal.util.Preconditions;
172 import com.android.internal.view.ScrollCaptureInternal;
173 import com.android.internal.view.TooltipPopup;
174 import com.android.internal.view.menu.MenuBuilder;
175 import com.android.internal.widget.ScrollBarUtils;
176 
177 import com.google.android.collect.Lists;
178 import com.google.android.collect.Maps;
179 
180 import java.io.PrintWriter;
181 import java.lang.annotation.Retention;
182 import java.lang.annotation.RetentionPolicy;
183 import java.lang.ref.WeakReference;
184 import java.lang.reflect.Field;
185 import java.lang.reflect.InvocationTargetException;
186 import java.lang.reflect.Method;
187 import java.lang.reflect.Modifier;
188 import java.util.ArrayList;
189 import java.util.Arrays;
190 import java.util.Calendar;
191 import java.util.Collection;
192 import java.util.Collections;
193 import java.util.HashMap;
194 import java.util.List;
195 import java.util.Locale;
196 import java.util.Map;
197 import java.util.concurrent.CopyOnWriteArrayList;
198 import java.util.concurrent.Executor;
199 import java.util.concurrent.atomic.AtomicInteger;
200 import java.util.function.Consumer;
201 import java.util.function.Predicate;
202 
203 /**
204  * <p>
205  * This class represents the basic building block for user interface components. A View
206  * occupies a rectangular area on the screen and is responsible for drawing and
207  * event handling. View is the base class for <em>widgets</em>, which are
208  * used to create interactive UI components (buttons, text fields, etc.). The
209  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
210  * are invisible containers that hold other Views (or other ViewGroups) and define
211  * their layout properties.
212  * </p>
213  *
214  * <div class="special reference">
215  * <h3>Developer Guides</h3>
216  * <p>For information about using this class to develop your application's user interface,
217  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
218  * </div>
219  *
220  * <a name="Using"></a>
221  * <h3>Using Views</h3>
222  * <p>
223  * All of the views in a window are arranged in a single tree. You can add views
224  * either from code or by specifying a tree of views in one or more XML layout
225  * files. There are many specialized subclasses of views that act as controls or
226  * are capable of displaying text, images, or other content.
227  * </p>
228  * <p>
229  * Once you have created a tree of views, there are typically a few types of
230  * common operations you may wish to perform:
231  * <ul>
232  * <li><strong>Set properties:</strong> for example setting the text of a
233  * {@link android.widget.TextView}. The available properties and the methods
234  * that set them will vary among the different subclasses of views. Note that
235  * properties that are known at build time can be set in the XML layout
236  * files.</li>
237  * <li><strong>Set focus:</strong> The framework will handle moving focus in
238  * response to user input. To force focus to a specific view, call
239  * {@link #requestFocus}.</li>
240  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
241  * that will be notified when something interesting happens to the view. For
242  * example, all views will let you set a listener to be notified when the view
243  * gains or loses focus. You can register such a listener using
244  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
245  * Other view subclasses offer more specialized listeners. For example, a Button
246  * exposes a listener to notify clients when the button is clicked.</li>
247  * <li><strong>Set visibility:</strong> You can hide or show views using
248  * {@link #setVisibility(int)}.</li>
249  * </ul>
250  * </p>
251  * <p><em>
252  * Note: The Android framework is responsible for measuring, laying out and
253  * drawing views. You should not call methods that perform these actions on
254  * views yourself unless you are actually implementing a
255  * {@link android.view.ViewGroup}.
256  * </em></p>
257  *
258  * <a name="Lifecycle"></a>
259  * <h3>Implementing a Custom View</h3>
260  *
261  * <p>
262  * To implement a custom view, you will usually begin by providing overrides for
263  * some of the standard methods that the framework calls on all views. You do
264  * not need to override all of these methods. In fact, you can start by just
265  * overriding {@link #onDraw(android.graphics.Canvas)}.
266  * <table border="2" width="85%" align="center" cellpadding="5">
267  *     <thead>
268  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
269  *     </thead>
270  *
271  *     <tbody>
272  *     <tr>
273  *         <td rowspan="2">Creation</td>
274  *         <td>Constructors</td>
275  *         <td>There is a form of the constructor that are called when the view
276  *         is created from code and a form that is called when the view is
277  *         inflated from a layout file. The second form should parse and apply
278  *         any attributes defined in the layout file.
279  *         </td>
280  *     </tr>
281  *     <tr>
282  *         <td><code>{@link #onFinishInflate()}</code></td>
283  *         <td>Called after a view and all of its children has been inflated
284  *         from XML.</td>
285  *     </tr>
286  *
287  *     <tr>
288  *         <td rowspan="3">Layout</td>
289  *         <td><code>{@link #onMeasure(int, int)}</code></td>
290  *         <td>Called to determine the size requirements for this view and all
291  *         of its children.
292  *         </td>
293  *     </tr>
294  *     <tr>
295  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
296  *         <td>Called when this view should assign a size and position to all
297  *         of its children.
298  *         </td>
299  *     </tr>
300  *     <tr>
301  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
302  *         <td>Called when the size of this view has changed.
303  *         </td>
304  *     </tr>
305  *
306  *     <tr>
307  *         <td>Drawing</td>
308  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
309  *         <td>Called when the view should render its content.
310  *         </td>
311  *     </tr>
312  *
313  *     <tr>
314  *         <td rowspan="4">Event processing</td>
315  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
316  *         <td>Called when a new hardware key event occurs.
317  *         </td>
318  *     </tr>
319  *     <tr>
320  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
321  *         <td>Called when a hardware key up event occurs.
322  *         </td>
323  *     </tr>
324  *     <tr>
325  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
326  *         <td>Called when a trackball motion event occurs.
327  *         </td>
328  *     </tr>
329  *     <tr>
330  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
331  *         <td>Called when a touch screen motion event occurs.
332  *         </td>
333  *     </tr>
334  *
335  *     <tr>
336  *         <td rowspan="2">Focus</td>
337  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
338  *         <td>Called when the view gains or loses focus.
339  *         </td>
340  *     </tr>
341  *
342  *     <tr>
343  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
344  *         <td>Called when the window containing the view gains or loses focus.
345  *         </td>
346  *     </tr>
347  *
348  *     <tr>
349  *         <td rowspan="3">Attaching</td>
350  *         <td><code>{@link #onAttachedToWindow()}</code></td>
351  *         <td>Called when the view is attached to a window.
352  *         </td>
353  *     </tr>
354  *
355  *     <tr>
356  *         <td><code>{@link #onDetachedFromWindow}</code></td>
357  *         <td>Called when the view is detached from its window.
358  *         </td>
359  *     </tr>
360  *
361  *     <tr>
362  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
363  *         <td>Called when the visibility of the window containing the view
364  *         has changed.
365  *         </td>
366  *     </tr>
367  *     </tbody>
368  *
369  * </table>
370  * </p>
371  *
372  * <a name="IDs"></a>
373  * <h3>IDs</h3>
374  * Views may have an integer id associated with them. These ids are typically
375  * assigned in the layout XML files, and are used to find specific views within
376  * the view tree. A common pattern is to:
377  * <ul>
378  * <li>Define a Button in the layout file and assign it a unique ID.
379  * <pre>
380  * &lt;Button
381  *     android:id="@+id/my_button"
382  *     android:layout_width="wrap_content"
383  *     android:layout_height="wrap_content"
384  *     android:text="@string/my_button_text"/&gt;
385  * </pre></li>
386  * <li>From the onCreate method of an Activity, find the Button
387  * <pre class="prettyprint">
388  *      Button myButton = findViewById(R.id.my_button);
389  * </pre></li>
390  * </ul>
391  * <p>
392  * View IDs need not be unique throughout the tree, but it is good practice to
393  * ensure that they are at least unique within the part of the tree you are
394  * searching.
395  * </p>
396  *
397  * <a name="Position"></a>
398  * <h3>Position</h3>
399  * <p>
400  * The geometry of a view is that of a rectangle. A view has a location,
401  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
402  * two dimensions, expressed as a width and a height. The unit for location
403  * and dimensions is the pixel.
404  * </p>
405  *
406  * <p>
407  * It is possible to retrieve the location of a view by invoking the methods
408  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
409  * coordinate of the rectangle representing the view. The latter returns the
410  * top, or Y, coordinate of the rectangle representing the view. These methods
411  * both return the location of the view relative to its parent. For instance,
412  * when getLeft() returns 20, that means the view is located 20 pixels to the
413  * right of the left edge of its direct parent.
414  * </p>
415  *
416  * <p>
417  * In addition, several convenience methods are offered to avoid unnecessary
418  * computations, namely {@link #getRight()} and {@link #getBottom()}.
419  * These methods return the coordinates of the right and bottom edges of the
420  * rectangle representing the view. For instance, calling {@link #getRight()}
421  * is similar to the following computation: <code>getLeft() + getWidth()</code>
422  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
423  * </p>
424  *
425  * <a name="SizePaddingMargins"></a>
426  * <h3>Size, padding and margins</h3>
427  * <p>
428  * The size of a view is expressed with a width and a height. A view actually
429  * possess two pairs of width and height values.
430  * </p>
431  *
432  * <p>
433  * The first pair is known as <em>measured width</em> and
434  * <em>measured height</em>. These dimensions define how big a view wants to be
435  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
436  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
437  * and {@link #getMeasuredHeight()}.
438  * </p>
439  *
440  * <p>
441  * The second pair is simply known as <em>width</em> and <em>height</em>, or
442  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
443  * dimensions define the actual size of the view on screen, at drawing time and
444  * after layout. These values may, but do not have to, be different from the
445  * measured width and height. The width and height can be obtained by calling
446  * {@link #getWidth()} and {@link #getHeight()}.
447  * </p>
448  *
449  * <p>
450  * To measure its dimensions, a view takes into account its padding. The padding
451  * is expressed in pixels for the left, top, right and bottom parts of the view.
452  * Padding can be used to offset the content of the view by a specific amount of
453  * pixels. For instance, a left padding of 2 will push the view's content by
454  * 2 pixels to the right of the left edge. Padding can be set using the
455  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
456  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
457  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
458  * {@link #getPaddingEnd()}.
459  * </p>
460  *
461  * <p>
462  * Even though a view can define a padding, it does not provide any support for
463  * margins. However, view groups provide such a support. Refer to
464  * {@link android.view.ViewGroup} and
465  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
466  * </p>
467  *
468  * <a name="Layout"></a>
469  * <h3>Layout</h3>
470  * <p>
471  * Layout is a two pass process: a measure pass and a layout pass. The measuring
472  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
473  * of the view tree. Each view pushes dimension specifications down the tree
474  * during the recursion. At the end of the measure pass, every view has stored
475  * its measurements. The second pass happens in
476  * {@link #layout(int,int,int,int)} and is also top-down. During
477  * this pass each parent is responsible for positioning all of its children
478  * using the sizes computed in the measure pass.
479  * </p>
480  *
481  * <p>
482  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
483  * {@link #getMeasuredHeight()} values must be set, along with those for all of
484  * that view's descendants. A view's measured width and measured height values
485  * must respect the constraints imposed by the view's parents. This guarantees
486  * that at the end of the measure pass, all parents accept all of their
487  * children's measurements. A parent view may call measure() more than once on
488  * its children. For example, the parent may measure each child once with
489  * unspecified dimensions to find out how big they want to be, then call
490  * measure() on them again with actual numbers if the sum of all the children's
491  * unconstrained sizes is too big or too small.
492  * </p>
493  *
494  * <p>
495  * The measure pass uses two classes to communicate dimensions. The
496  * {@link MeasureSpec} class is used by views to tell their parents how they
497  * want to be measured and positioned. The base LayoutParams class just
498  * describes how big the view wants to be for both width and height. For each
499  * dimension, it can specify one of:
500  * <ul>
501  * <li> an exact number
502  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
503  * (minus padding)
504  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
505  * enclose its content (plus padding).
506  * </ul>
507  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
508  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
509  * an X and Y value.
510  * </p>
511  *
512  * <p>
513  * MeasureSpecs are used to push requirements down the tree from parent to
514  * child. A MeasureSpec can be in one of three modes:
515  * <ul>
516  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
517  * of a child view. For example, a LinearLayout may call measure() on its child
518  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
519  * tall the child view wants to be given a width of 240 pixels.
520  * <li>EXACTLY: This is used by the parent to impose an exact size on the
521  * child. The child must use this size, and guarantee that all of its
522  * descendants will fit within this size.
523  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
524  * child. The child must guarantee that it and all of its descendants will fit
525  * within this size.
526  * </ul>
527  * </p>
528  *
529  * <p>
530  * To initiate a layout, call {@link #requestLayout}. This method is typically
531  * called by a view on itself when it believes that it can no longer fit within
532  * its current bounds.
533  * </p>
534  *
535  * <a name="Drawing"></a>
536  * <h3>Drawing</h3>
537  * <p>
538  * Drawing is handled by walking the tree and recording the drawing commands of
539  * any View that needs to update. After this, the drawing commands of the
540  * entire tree are issued to screen, clipped to the newly damaged area.
541  * </p>
542  *
543  * <p>
544  * The tree is largely recorded and drawn in order, with parents drawn before
545  * (i.e., behind) their children, with siblings drawn in the order they appear
546  * in the tree. If you set a background drawable for a View, then the View will
547  * draw it before calling back to its <code>onDraw()</code> method. The child
548  * drawing order can be overridden with
549  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
550  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
551  * </p>
552  *
553  * <p>
554  * To force a view to draw, call {@link #invalidate()}.
555  * </p>
556  *
557  * <a name="EventHandlingThreading"></a>
558  * <h3>Event Handling and Threading</h3>
559  * <p>
560  * The basic cycle of a view is as follows:
561  * <ol>
562  * <li>An event comes in and is dispatched to the appropriate view. The view
563  * handles the event and notifies any listeners.</li>
564  * <li>If in the course of processing the event, the view's bounds may need
565  * to be changed, the view will call {@link #requestLayout()}.</li>
566  * <li>Similarly, if in the course of processing the event the view's appearance
567  * may need to be changed, the view will call {@link #invalidate()}.</li>
568  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
569  * the framework will take care of measuring, laying out, and drawing the tree
570  * as appropriate.</li>
571  * </ol>
572  * </p>
573  *
574  * <p><em>Note: The entire view tree is single threaded. You must always be on
575  * the UI thread when calling any method on any view.</em>
576  * If you are doing work on other threads and want to update the state of a view
577  * from that thread, you should use a {@link Handler}.
578  * </p>
579  *
580  * <a name="FocusHandling"></a>
581  * <h3>Focus Handling</h3>
582  * <p>
583  * The framework will handle routine focus movement in response to user input.
584  * This includes changing the focus as views are removed or hidden, or as new
585  * views become available. Views indicate their willingness to take focus
586  * through the {@link #isFocusable} method. To change whether a view can take
587  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
588  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
589  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
590  * </p>
591  * <p>
592  * Focus movement is based on an algorithm which finds the nearest neighbor in a
593  * given direction. In rare cases, the default algorithm may not match the
594  * intended behavior of the developer. In these situations, you can provide
595  * explicit overrides by using these XML attributes in the layout file:
596  * <pre>
597  * nextFocusDown
598  * nextFocusLeft
599  * nextFocusRight
600  * nextFocusUp
601  * </pre>
602  * </p>
603  *
604  *
605  * <p>
606  * To get a particular view to take focus, call {@link #requestFocus()}.
607  * </p>
608  *
609  * <a name="TouchMode"></a>
610  * <h3>Touch Mode</h3>
611  * <p>
612  * When a user is navigating a user interface via directional keys such as a D-pad, it is
613  * necessary to give focus to actionable items such as buttons so the user can see
614  * what will take input.  If the device has touch capabilities, however, and the user
615  * begins interacting with the interface by touching it, it is no longer necessary to
616  * always highlight, or give focus to, a particular view.  This motivates a mode
617  * for interaction named 'touch mode'.
618  * </p>
619  * <p>
620  * For a touch capable device, once the user touches the screen, the device
621  * will enter touch mode.  From this point onward, only views for which
622  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
623  * Other views that are touchable, like buttons, will not take focus when touched; they will
624  * only fire the on click listeners.
625  * </p>
626  * <p>
627  * Any time a user hits a directional key, such as a D-pad direction, the view device will
628  * exit touch mode, and find a view to take focus, so that the user may resume interacting
629  * with the user interface without touching the screen again.
630  * </p>
631  * <p>
632  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
633  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
634  * </p>
635  *
636  * <a name="Scrolling"></a>
637  * <h3>Scrolling</h3>
638  * <p>
639  * The framework provides basic support for views that wish to internally
640  * scroll their content. This includes keeping track of the X and Y scroll
641  * offset as well as mechanisms for drawing scrollbars. See
642  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
643  * {@link #awakenScrollBars()} for more details.
644  * </p>
645  *
646  * <a name="Tags"></a>
647  * <h3>Tags</h3>
648  * <p>
649  * Unlike IDs, tags are not used to identify views. Tags are essentially an
650  * extra piece of information that can be associated with a view. They are most
651  * often used as a convenience to store data related to views in the views
652  * themselves rather than by putting them in a separate structure.
653  * </p>
654  * <p>
655  * Tags may be specified with character sequence values in layout XML as either
656  * a single tag using the {@link android.R.styleable#View_tag android:tag}
657  * attribute or multiple tags using the {@code <tag>} child element:
658  * <pre>
659  *     &lt;View ...
660  *           android:tag="@string/mytag_value" /&gt;
661  *     &lt;View ...&gt;
662  *         &lt;tag android:id="@+id/mytag"
663  *              android:value="@string/mytag_value" /&gt;
664  *     &lt;/View>
665  * </pre>
666  * </p>
667  * <p>
668  * Tags may also be specified with arbitrary objects from code using
669  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
670  * </p>
671  *
672  * <a name="Themes"></a>
673  * <h3>Themes</h3>
674  * <p>
675  * By default, Views are created using the theme of the Context object supplied
676  * to their constructor; however, a different theme may be specified by using
677  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
678  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
679  * code.
680  * </p>
681  * <p>
682  * When the {@link android.R.styleable#View_theme android:theme} attribute is
683  * used in XML, the specified theme is applied on top of the inflation
684  * context's theme (see {@link LayoutInflater}) and used for the view itself as
685  * well as any child elements.
686  * </p>
687  * <p>
688  * In the following example, both views will be created using the Material dark
689  * color scheme; however, because an overlay theme is used which only defines a
690  * subset of attributes, the value of
691  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
692  * the inflation context's theme (e.g. the Activity theme) will be preserved.
693  * <pre>
694  *     &lt;LinearLayout
695  *             ...
696  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
697  *         &lt;View ...&gt;
698  *     &lt;/LinearLayout&gt;
699  * </pre>
700  * </p>
701  *
702  * <a name="Properties"></a>
703  * <h3>Properties</h3>
704  * <p>
705  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
706  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
707  * available both in the {@link Property} form as well as in similarly-named setter/getter
708  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
709  * be used to set persistent state associated with these rendering-related properties on the view.
710  * The properties and methods can also be used in conjunction with
711  * {@link android.animation.Animator Animator}-based animations, described more in the
712  * <a href="#Animation">Animation</a> section.
713  * </p>
714  *
715  * <a name="Animation"></a>
716  * <h3>Animation</h3>
717  * <p>
718  * Starting with Android 3.0, the preferred way of animating views is to use the
719  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
720  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
721  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
722  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
723  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
724  * makes animating these View properties particularly easy and efficient.
725  * </p>
726  * <p>
727  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
728  * You can attach an {@link Animation} object to a view using
729  * {@link #setAnimation(Animation)} or
730  * {@link #startAnimation(Animation)}. The animation can alter the scale,
731  * rotation, translation and alpha of a view over time. If the animation is
732  * attached to a view that has children, the animation will affect the entire
733  * subtree rooted by that node. When an animation is started, the framework will
734  * take care of redrawing the appropriate views until the animation completes.
735  * </p>
736  *
737  * <a name="Security"></a>
738  * <h3>Security</h3>
739  * <p>
740  * Sometimes it is essential that an application be able to verify that an action
741  * is being performed with the full knowledge and consent of the user, such as
742  * granting a permission request, making a purchase or clicking on an advertisement.
743  * Unfortunately, a malicious application could try to spoof the user into
744  * performing these actions, unaware, by concealing the intended purpose of the view.
745  * As a remedy, the framework offers a touch filtering mechanism that can be used to
746  * improve the security of views that provide access to sensitive functionality.
747  * </p><p>
748  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
749  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
750  * will discard touches that are received whenever the view's window is obscured by
751  * another visible window at the touched location.  As a result, the view will not receive touches
752  * whenever the touch passed through a toast, dialog or other window that appears above the view's
753  * window.
754  * </p><p>
755  * For more fine-grained control over security, consider overriding the
756  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
757  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
758  * </p>
759  *
760  * @attr ref android.R.styleable#View_accessibilityHeading
761  * @attr ref android.R.styleable#View_allowClickWhenDisabled
762  * @attr ref android.R.styleable#View_alpha
763  * @attr ref android.R.styleable#View_background
764  * @attr ref android.R.styleable#View_clickable
765  * @attr ref android.R.styleable#View_clipToOutline
766  * @attr ref android.R.styleable#View_contentDescription
767  * @attr ref android.R.styleable#View_drawingCacheQuality
768  * @attr ref android.R.styleable#View_duplicateParentState
769  * @attr ref android.R.styleable#View_id
770  * @attr ref android.R.styleable#View_requiresFadingEdge
771  * @attr ref android.R.styleable#View_fadeScrollbars
772  * @attr ref android.R.styleable#View_fadingEdgeLength
773  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
774  * @attr ref android.R.styleable#View_fitsSystemWindows
775  * @attr ref android.R.styleable#View_isScrollContainer
776  * @attr ref android.R.styleable#View_focusable
777  * @attr ref android.R.styleable#View_focusableInTouchMode
778  * @attr ref android.R.styleable#View_focusedByDefault
779  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
780  * @attr ref android.R.styleable#View_keepScreenOn
781  * @attr ref android.R.styleable#View_keyboardNavigationCluster
782  * @attr ref android.R.styleable#View_layerType
783  * @attr ref android.R.styleable#View_layoutDirection
784  * @attr ref android.R.styleable#View_longClickable
785  * @attr ref android.R.styleable#View_minHeight
786  * @attr ref android.R.styleable#View_minWidth
787  * @attr ref android.R.styleable#View_nextClusterForward
788  * @attr ref android.R.styleable#View_nextFocusDown
789  * @attr ref android.R.styleable#View_nextFocusLeft
790  * @attr ref android.R.styleable#View_nextFocusRight
791  * @attr ref android.R.styleable#View_nextFocusUp
792  * @attr ref android.R.styleable#View_onClick
793  * @attr ref android.R.styleable#View_outlineSpotShadowColor
794  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
795  * @attr ref android.R.styleable#View_padding
796  * @attr ref android.R.styleable#View_paddingHorizontal
797  * @attr ref android.R.styleable#View_paddingVertical
798  * @attr ref android.R.styleable#View_paddingBottom
799  * @attr ref android.R.styleable#View_paddingLeft
800  * @attr ref android.R.styleable#View_paddingRight
801  * @attr ref android.R.styleable#View_paddingTop
802  * @attr ref android.R.styleable#View_paddingStart
803  * @attr ref android.R.styleable#View_paddingEnd
804  * @attr ref android.R.styleable#View_saveEnabled
805  * @attr ref android.R.styleable#View_rotation
806  * @attr ref android.R.styleable#View_rotationX
807  * @attr ref android.R.styleable#View_rotationY
808  * @attr ref android.R.styleable#View_scaleX
809  * @attr ref android.R.styleable#View_scaleY
810  * @attr ref android.R.styleable#View_scrollX
811  * @attr ref android.R.styleable#View_scrollY
812  * @attr ref android.R.styleable#View_scrollbarSize
813  * @attr ref android.R.styleable#View_scrollbarStyle
814  * @attr ref android.R.styleable#View_scrollbars
815  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
816  * @attr ref android.R.styleable#View_scrollbarFadeDuration
817  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
818  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
819  * @attr ref android.R.styleable#View_scrollbarThumbVertical
820  * @attr ref android.R.styleable#View_scrollbarTrackVertical
821  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
822  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
823  * @attr ref android.R.styleable#View_stateListAnimator
824  * @attr ref android.R.styleable#View_transitionName
825  * @attr ref android.R.styleable#View_soundEffectsEnabled
826  * @attr ref android.R.styleable#View_tag
827  * @attr ref android.R.styleable#View_textAlignment
828  * @attr ref android.R.styleable#View_textDirection
829  * @attr ref android.R.styleable#View_transformPivotX
830  * @attr ref android.R.styleable#View_transformPivotY
831  * @attr ref android.R.styleable#View_translationX
832  * @attr ref android.R.styleable#View_translationY
833  * @attr ref android.R.styleable#View_translationZ
834  * @attr ref android.R.styleable#View_visibility
835  * @attr ref android.R.styleable#View_theme
836  *
837  * @see android.view.ViewGroup
838  */
839 @UiThread
840 public class View implements Drawable.Callback, KeyEvent.Callback,
841         AccessibilityEventSource {
842     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
843     private static final boolean DBG = false;
844 
845     /** @hide */
846     public static boolean DEBUG_DRAW = false;
847 
848     /**
849      * The logging tag used by this class with android.util.Log.
850      */
851     protected static final String VIEW_LOG_TAG = "View";
852 
853     /**
854      * The logging tag used by this class when logging verbose, autofill-related messages.
855      */
856     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
857     // set if a session is not started.
858     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
859 
860     /**
861      * The logging tag used by this class when logging content capture-related messages.
862      */
863     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
864 
865     private static final boolean DEBUG_CONTENT_CAPTURE = false;
866 
867     /**
868      * When set to true, this view will save its attribute data.
869      *
870      * @hide
871      */
872     public static boolean sDebugViewAttributes = false;
873 
874     /**
875      * When set to this application package view will save its attribute data.
876      *
877      * @hide
878      */
879     public static String sDebugViewAttributesApplicationPackage;
880 
881     /**
882      * Used to mark a View that has no ID.
883      */
884     public static final int NO_ID = -1;
885 
886     /**
887      * Last ID that is given to Views that are no part of activities.
888      *
889      * {@hide}
890      */
891     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
892 
893     /**
894      * Attribute to find the autofilled highlight
895      *
896      * @see #getAutofilledDrawable()
897      */
898     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
899             new int[]{android.R.attr.autofilledHighlight};
900 
901     /**
902      * Signals that compatibility booleans have been initialized according to
903      * target SDK versions.
904      */
905     private static boolean sCompatibilityDone = false;
906 
907     /**
908      * Use the old (broken) way of building MeasureSpecs.
909      */
910     private static boolean sUseBrokenMakeMeasureSpec = false;
911 
912     /**
913      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
914      */
915     static boolean sUseZeroUnspecifiedMeasureSpec = false;
916 
917     /**
918      * Ignore any optimizations using the measure cache.
919      */
920     private static boolean sIgnoreMeasureCache = false;
921 
922     /**
923      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
924      */
925     private static boolean sAlwaysRemeasureExactly = false;
926 
927     /**
928      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
929      * without throwing
930      */
931     static boolean sTextureViewIgnoresDrawableSetters = false;
932 
933     /**
934      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
935      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
936      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
937      * check is implemented for backwards compatibility.
938      *
939      * {@hide}
940      */
941     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
942 
943     /**
944      * Prior to N, when drag enters into child of a view that has already received an
945      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
946      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
947      * false from its event handler for these events.
948      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
949      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
950      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
951      */
952     static boolean sCascadedDragDrop;
953 
954     /**
955      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
956      * to determine things like whether or not to permit item click events. We can't break
957      * apps that do this just because more things (clickable things) are now auto-focusable
958      * and they would get different results, so give old behavior to old apps.
959      */
960     static boolean sHasFocusableExcludeAutoFocusable;
961 
962     /**
963      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
964      * made focusable by default. As a result, apps could (incorrectly) change the clickable
965      * setting of views off the UI thread. Now that clickable can effect the focusable state,
966      * changing the clickable attribute off the UI thread will cause an exception (since changing
967      * the focusable state checks). In order to prevent apps from crashing, we will handle this
968      * specific case and just not notify parents on new focusables resulting from marking views
969      * clickable from outside the UI thread.
970      */
971     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
972 
973     /**
974      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
975      * Float.NaN. If the app is targetting P or later then passing these values will result in an
976      * exception being thrown. If the app is targetting an earlier SDK version, then we will
977      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
978      * these bogus values.
979      */
980     private static boolean sThrowOnInvalidFloatProperties;
981 
982     /**
983      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
984      * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead.
985      */
986     private static boolean sAcceptZeroSizeDragShadow;
987 
988     /**
989      * When true, measure and layout passes of all the newly attached views will be logged with
990      * {@link Trace}, so we can better debug jank due to complex view hierarchies.
991      */
992     private static boolean sTraceLayoutSteps;
993 
994     /**
995      * When not null, emits a {@link Trace} instant event and the stacktrace every time a relayout
996      * of a class having this name happens.
997      */
998     private static String sTraceRequestLayoutClass;
999 
1000     /** Used to avoid computing the full strings each time when layout tracing is enabled. */
1001     @Nullable
1002     private ViewTraversalTracingStrings mTracingStrings;
1003 
1004     /**
1005      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
1006      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
1007      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
1008      * further down the hierarchy. This violates the basic concepts of the view hierarchy, and
1009      * thus, the hierarchical dispatching mechanism was hard to use for apps.
1010      * <p>
1011      * In order to make window inset dispatching work properly, we dispatch window insets
1012      * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}.
1013      */
1014     static boolean sBrokenInsetsDispatch;
1015 
1016     /**
1017      * Prior to Q, calling
1018      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
1019      * did not call update the window format so the opacity of the background was not correctly
1020      * applied to the window. Some applications rely on this misbehavior to work properly.
1021      * <p>
1022      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
1023      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
1024      * which updates the window format.
1025      * @hide
1026      */
1027     protected static boolean sBrokenWindowBackground;
1028 
1029     /**
1030      * Prior to R, we were always forcing a layout of the entire hierarchy when insets changed from
1031      * the server. This is inefficient and not all apps use it. Instead, we want to rely on apps
1032      * calling {@link #requestLayout} when they need to relayout based on an insets change.
1033      */
1034     static boolean sForceLayoutWhenInsetsChanged;
1035 
1036     /** @hide */
1037     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
1038     @Retention(RetentionPolicy.SOURCE)
1039     public @interface Focusable {}
1040 
1041     /**
1042      * This view does not want keystrokes.
1043      * <p>
1044      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1045      * android:focusable}.
1046      */
1047     public static final int NOT_FOCUSABLE = 0x00000000;
1048 
1049     /**
1050      * This view wants keystrokes.
1051      * <p>
1052      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1053      * android:focusable}.
1054      */
1055     public static final int FOCUSABLE = 0x00000001;
1056 
1057     /**
1058      * This view determines focusability automatically. This is the default.
1059      * <p>
1060      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1061      * android:focusable}.
1062      */
1063     public static final int FOCUSABLE_AUTO = 0x00000010;
1064 
1065     /**
1066      * Mask for use with setFlags indicating bits used for focus.
1067      */
1068     private static final int FOCUSABLE_MASK = 0x00000011;
1069 
1070     /**
1071      * This view will adjust its padding to fit sytem windows (e.g. status bar)
1072      */
1073     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1074 
1075     /** @hide */
1076     @IntDef({VISIBLE, INVISIBLE, GONE})
1077     @Retention(RetentionPolicy.SOURCE)
1078     public @interface Visibility {}
1079 
1080     /**
1081      * This view is visible.
1082      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1083      * android:visibility}.
1084      */
1085     public static final int VISIBLE = 0x00000000;
1086 
1087     /**
1088      * This view is invisible, but it still takes up space for layout purposes.
1089      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1090      * android:visibility}.
1091      */
1092     public static final int INVISIBLE = 0x00000004;
1093 
1094     /**
1095      * This view is invisible, and it doesn't take any space for layout
1096      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1097      * android:visibility}.
1098      */
1099     public static final int GONE = 0x00000008;
1100 
1101     /**
1102      * Mask for use with setFlags indicating bits used for visibility.
1103      * {@hide}
1104      */
1105     static final int VISIBILITY_MASK = 0x0000000C;
1106 
1107     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1108 
1109     /**
1110      * Hint indicating that this view can be autofilled with an email address.
1111      *
1112      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1113      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1114      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1115      *
1116      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1117      */
1118     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1119 
1120     /**
1121      * Hint indicating that this view can be autofilled with a user's real name.
1122      *
1123      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1124      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1125      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1126      *
1127      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1128      */
1129     public static final String AUTOFILL_HINT_NAME = "name";
1130 
1131     /**
1132      * Hint indicating that this view can be autofilled with a username.
1133      *
1134      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1135      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1136      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1137      *
1138      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1139      */
1140     public static final String AUTOFILL_HINT_USERNAME = "username";
1141 
1142     /**
1143      * Hint indicating that this view can be autofilled with a password.
1144      *
1145      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1146      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1147      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1148      *
1149      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1150      */
1151     public static final String AUTOFILL_HINT_PASSWORD = "password";
1152 
1153     /**
1154      * Hint indicating that this view can be autofilled with a phone number.
1155      *
1156      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1157      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1158      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1159      *
1160      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1161      */
1162     public static final String AUTOFILL_HINT_PHONE = "phone";
1163 
1164     /**
1165      * Hint indicating that this view can be autofilled with a postal address.
1166      *
1167      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1168      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1169      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1170      *
1171      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1172      */
1173     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1174 
1175     /**
1176      * Hint indicating that this view can be autofilled with a postal code.
1177      *
1178      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1179      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1180      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1181      *
1182      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1183      */
1184     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1185 
1186     /**
1187      * Hint indicating that this view can be autofilled with a credit card number.
1188      *
1189      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1190      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1191      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1192      *
1193      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1194      */
1195     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1196 
1197     /**
1198      * Hint indicating that this view can be autofilled with a credit card security code.
1199      *
1200      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1201      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1202      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1203      *
1204      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1205      */
1206     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1207 
1208     /**
1209      * Hint indicating that this view can be autofilled with a credit card expiration date.
1210      *
1211      * <p>It should be used when the credit card expiration date is represented by just one view;
1212      * if it is represented by more than one (for example, one view for the month and another view
1213      * for the year), then each of these views should use the hint specific for the unit
1214      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1215      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1216      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1217      *
1218      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1219      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1220      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1221      *
1222      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1223      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1224      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1225      * the following options:
1226      *
1227      * <ul>
1228      *   <li>{@code "04/2020"}
1229      *   <li>{@code "4/2020"}
1230      *   <li>{@code "2020/04"}
1231      *   <li>{@code "2020/4"}
1232      *   <li>{@code "April/2020"}
1233      *   <li>{@code "Apr/2020"}
1234      * </ul>
1235      *
1236      * <p>You define a date autofill value for the view by overriding the following methods:
1237      *
1238      * <ol>
1239      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1240      *   <li>{@link #getAutofillValue()} to return a
1241      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1242      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1243      * </ol>
1244      *
1245      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1246      */
1247     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1248             "creditCardExpirationDate";
1249 
1250     /**
1251      * Hint indicating that this view can be autofilled with a credit card expiration month.
1252      *
1253      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1254      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1255      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1256      *
1257      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1258      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1259      * ambiguity when the autofill service provides a value for it. To understand why a
1260      * value can be ambiguous, consider "January", which could be represented as either of
1261      *
1262      * <ul>
1263      *   <li>{@code "1"}: recommended way.
1264      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1265      *   <li>{@code "January"}: full name, in English.
1266      *   <li>{@code "jan"}: abbreviated name, in English.
1267      *   <li>{@code "Janeiro"}: full name, in another language.
1268      * </ul>
1269      *
1270      * <p>Another recommended approach is to use a date autofill value - see
1271      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1272      *
1273      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1274      */
1275     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1276             "creditCardExpirationMonth";
1277 
1278     /**
1279      * Hint indicating that this view can be autofilled with a credit card expiration year.
1280      *
1281      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1282      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1283      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1284      *
1285      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1286      */
1287     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1288             "creditCardExpirationYear";
1289 
1290     /**
1291      * Hint indicating that this view can be autofilled with a credit card expiration day.
1292      *
1293      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1294      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1295      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1296      *
1297      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1298      */
1299     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1300 
1301     /**
1302      * A hint indicating that this view can be autofilled with a password.
1303      *
1304      * This is a heuristic-based hint that is meant to be used by UI Toolkit developers when a
1305      * view is a password field but doesn't specify a
1306      * <code>{@value View#AUTOFILL_HINT_PASSWORD}</code>.
1307      * @hide
1308      */
1309     // TODO(229765029): unhide this for UI toolkit
1310     public static final String AUTOFILL_HINT_PASSWORD_AUTO = "passwordAuto";
1311 
1312     /**
1313      * Hints for the autofill services that describes the content of the view.
1314      */
1315     private @Nullable String[] mAutofillHints;
1316 
1317     /**
1318      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1319      */
1320     private AutofillId mAutofillId;
1321 
1322     /** @hide */
1323     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1324             AUTOFILL_TYPE_NONE,
1325             AUTOFILL_TYPE_TEXT,
1326             AUTOFILL_TYPE_TOGGLE,
1327             AUTOFILL_TYPE_LIST,
1328             AUTOFILL_TYPE_DATE,
1329     })
1330     @Retention(RetentionPolicy.SOURCE)
1331     public @interface AutofillType {}
1332 
1333     /**
1334      * Autofill type for views that cannot be autofilled.
1335      *
1336      * <p>Typically used when the view is read-only; for example, a text label.
1337      *
1338      * @see #getAutofillType()
1339      */
1340     public static final int AUTOFILL_TYPE_NONE = 0;
1341 
1342     /**
1343      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1344      *
1345      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1346      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1347      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1348      *
1349      * @see #getAutofillType()
1350      */
1351     public static final int AUTOFILL_TYPE_TEXT = 1;
1352 
1353     /**
1354      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1355      *
1356      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1357      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1358      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1359      *
1360      * @see #getAutofillType()
1361      */
1362     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1363 
1364     /**
1365      * Autofill type for a selection list field, which is filled by an {@code int}
1366      * representing the element index inside the list (starting at {@code 0}).
1367      *
1368      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1369      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1370      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1371      *
1372      * <p>The available options in the selection list are typically provided by
1373      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1374      *
1375      * @see #getAutofillType()
1376      */
1377     public static final int AUTOFILL_TYPE_LIST = 3;
1378 
1379     /**
1380      * Autofill type for a field that contains a date, which is represented by a long representing
1381      * the number of milliseconds since the standard base time known as "the epoch", namely
1382      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1383      *
1384      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1385      * {@link AutofillValue#forDate(long)}, and the values passed to
1386      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1387      *
1388      * @see #getAutofillType()
1389      */
1390     public static final int AUTOFILL_TYPE_DATE = 4;
1391 
1392 
1393     /** @hide */
1394     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1395             IMPORTANT_FOR_AUTOFILL_AUTO,
1396             IMPORTANT_FOR_AUTOFILL_YES,
1397             IMPORTANT_FOR_AUTOFILL_NO,
1398             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1399             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1400     })
1401     @Retention(RetentionPolicy.SOURCE)
1402     public @interface AutofillImportance {}
1403 
1404     /**
1405      * Automatically determine whether a view is important for autofill.
1406      *
1407      * @see #isImportantForAutofill()
1408      * @see #setImportantForAutofill(int)
1409      */
1410     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1411 
1412     /**
1413      * The view is important for autofill, and its children (if any) will be traversed.
1414      *
1415      * @see #isImportantForAutofill()
1416      * @see #setImportantForAutofill(int)
1417      */
1418     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1419 
1420     /**
1421      * The view is not important for autofill, but its children (if any) will be traversed.
1422      *
1423      * @see #isImportantForAutofill()
1424      * @see #setImportantForAutofill(int)
1425      */
1426     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1427 
1428     /**
1429      * The view is important for autofill, but its children (if any) will not be traversed.
1430      *
1431      * @see #isImportantForAutofill()
1432      * @see #setImportantForAutofill(int)
1433      */
1434     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1435 
1436     /**
1437      * The view is not important for autofill, and its children (if any) will not be traversed.
1438      *
1439      * @see #isImportantForAutofill()
1440      * @see #setImportantForAutofill(int)
1441      */
1442     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1443 
1444     /** @hide */
1445     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1446             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1447     })
1448     @Retention(RetentionPolicy.SOURCE)
1449     public @interface AutofillFlags {}
1450 
1451     /**
1452      * Flag requesting you to add views that are marked as not important for autofill
1453      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1454      */
1455     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1456 
1457     /** @hide */
1458     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1459             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1460             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1461             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1462             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1463             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1464     })
1465     @Retention(RetentionPolicy.SOURCE)
1466     public @interface ContentCaptureImportance {}
1467 
1468     /**
1469      * Automatically determine whether a view is important for content capture.
1470      *
1471      * @see #isImportantForContentCapture()
1472      * @see #setImportantForContentCapture(int)
1473      */
1474     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1475 
1476     /**
1477      * The view is important for content capture, and its children (if any) will be traversed.
1478      *
1479      * @see #isImportantForContentCapture()
1480      * @see #setImportantForContentCapture(int)
1481      */
1482     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1483 
1484     /**
1485      * The view is not important for content capture, but its children (if any) will be traversed.
1486      *
1487      * @see #isImportantForContentCapture()
1488      * @see #setImportantForContentCapture(int)
1489      */
1490     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1491 
1492     /**
1493      * The view is important for content capture, but its children (if any) will not be traversed.
1494      *
1495      * @see #isImportantForContentCapture()
1496      * @see #setImportantForContentCapture(int)
1497      */
1498     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1499 
1500     /**
1501      * The view is not important for content capture, and its children (if any) will not be
1502      * traversed.
1503      *
1504      * @see #isImportantForContentCapture()
1505      * @see #setImportantForContentCapture(int)
1506      */
1507     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1508 
1509     /** {@hide} */
1510     @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
1511             value = {
1512                     SCROLL_CAPTURE_HINT_AUTO,
1513                     SCROLL_CAPTURE_HINT_EXCLUDE,
1514                     SCROLL_CAPTURE_HINT_INCLUDE,
1515                     SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
1516     })
1517     @Retention(RetentionPolicy.SOURCE)
1518     public @interface ScrollCaptureHint {}
1519 
1520     /**
1521      * The content of this view will be considered for scroll capture if scrolling is possible.
1522      *
1523      * @see #getScrollCaptureHint()
1524      * @see #setScrollCaptureHint(int)
1525      */
1526     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
1527 
1528     /**
1529      * Explicitly exclude this view as a potential scroll capture target. The system will not
1530      * consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
1531      * takes precedence over.
1532      *
1533      * @see #getScrollCaptureHint()
1534      * @see #setScrollCaptureHint(int)
1535      */
1536     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
1537 
1538     /**
1539      * Explicitly include this view as a potential scroll capture target. When locating a scroll
1540      * capture target, this view will be prioritized before others without this flag. Mutually
1541      * exclusive with {@link #SCROLL_CAPTURE_HINT_EXCLUDE}, which takes precedence.
1542      *
1543      * @see #getScrollCaptureHint()
1544      * @see #setScrollCaptureHint(int)
1545      */
1546     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
1547 
1548     /**
1549      * Explicitly exclude all children of this view as potential scroll capture targets. This view
1550      * is unaffected. Note: Excluded children are not considered, regardless of {@link
1551      * #SCROLL_CAPTURE_HINT_INCLUDE}.
1552      *
1553      * @see #getScrollCaptureHint()
1554      * @see #setScrollCaptureHint(int)
1555      */
1556     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
1557 
1558     /**
1559      * This view is enabled. Interpretation varies by subclass.
1560      * Use with ENABLED_MASK when calling setFlags.
1561      * {@hide}
1562      */
1563     static final int ENABLED = 0x00000000;
1564 
1565     /**
1566      * This view is disabled. Interpretation varies by subclass.
1567      * Use with ENABLED_MASK when calling setFlags.
1568      * {@hide}
1569      */
1570     static final int DISABLED = 0x00000020;
1571 
1572    /**
1573     * Mask for use with setFlags indicating bits used for indicating whether
1574     * this view is enabled
1575     * {@hide}
1576     */
1577     static final int ENABLED_MASK = 0x00000020;
1578 
1579     /**
1580      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1581      * called and further optimizations will be performed. It is okay to have
1582      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1583      * {@hide}
1584      */
1585     static final int WILL_NOT_DRAW = 0x00000080;
1586 
1587     /**
1588      * Mask for use with setFlags indicating bits used for indicating whether
1589      * this view is will draw
1590      * {@hide}
1591      */
1592     static final int DRAW_MASK = 0x00000080;
1593 
1594     /**
1595      * <p>This view doesn't show scrollbars.</p>
1596      * {@hide}
1597      */
1598     static final int SCROLLBARS_NONE = 0x00000000;
1599 
1600     /**
1601      * <p>This view shows horizontal scrollbars.</p>
1602      * {@hide}
1603      */
1604     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1605 
1606     /**
1607      * <p>This view shows vertical scrollbars.</p>
1608      * {@hide}
1609      */
1610     static final int SCROLLBARS_VERTICAL = 0x00000200;
1611 
1612     /**
1613      * <p>Mask for use with setFlags indicating bits used for indicating which
1614      * scrollbars are enabled.</p>
1615      * {@hide}
1616      */
1617     static final int SCROLLBARS_MASK = 0x00000300;
1618 
1619     /**
1620      * Indicates that the view should filter touches when its window is obscured.
1621      * Refer to the class comments for more information about this security feature.
1622      * {@hide}
1623      */
1624     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1625 
1626     /**
1627      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1628      * that they are optional and should be skipped if the window has
1629      * requested system UI flags that ignore those insets for layout.
1630      * <p>
1631      * This is only used for support library as of Android R. The framework now uses
1632      * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
1633      * insets path that loses insets information.
1634      */
1635     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1636 
1637     /**
1638      * <p>This view doesn't show fading edges.</p>
1639      * {@hide}
1640      */
1641     static final int FADING_EDGE_NONE = 0x00000000;
1642 
1643     /**
1644      * <p>This view shows horizontal fading edges.</p>
1645      * {@hide}
1646      */
1647     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1648 
1649     /**
1650      * <p>This view shows vertical fading edges.</p>
1651      * {@hide}
1652      */
1653     static final int FADING_EDGE_VERTICAL = 0x00002000;
1654 
1655     /**
1656      * <p>Mask for use with setFlags indicating bits used for indicating which
1657      * fading edges are enabled.</p>
1658      * {@hide}
1659      */
1660     static final int FADING_EDGE_MASK = 0x00003000;
1661 
1662     /**
1663      * <p>Indicates this view can be clicked. When clickable, a View reacts
1664      * to clicks by notifying the OnClickListener.<p>
1665      * {@hide}
1666      */
1667     static final int CLICKABLE = 0x00004000;
1668 
1669     /**
1670      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1671      * {@hide}
1672      */
1673     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1674 
1675     /**
1676      * <p>Indicates that no icicle should be saved for this view.<p>
1677      * {@hide}
1678      */
1679     static final int SAVE_DISABLED = 0x000010000;
1680 
1681     /**
1682      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1683      * property.</p>
1684      * {@hide}
1685      */
1686     static final int SAVE_DISABLED_MASK = 0x000010000;
1687 
1688     /**
1689      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1690      * {@hide}
1691      */
1692     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1693 
1694     /**
1695      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1696      * {@hide}
1697      */
1698     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1699 
1700     /** @hide */
1701     @Retention(RetentionPolicy.SOURCE)
1702     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1703             DRAWING_CACHE_QUALITY_LOW,
1704             DRAWING_CACHE_QUALITY_HIGH,
1705             DRAWING_CACHE_QUALITY_AUTO
1706     })
1707     public @interface DrawingCacheQuality {}
1708 
1709     /**
1710      * <p>Enables low quality mode for the drawing cache.</p>
1711      *
1712      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1713      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1714      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1715      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1716      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1717      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1718      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1719      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1720      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1721      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1722      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1723      * reports or unit testing the {@link PixelCopy} API is recommended.
1724      */
1725     @Deprecated
1726     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1727 
1728     /**
1729      * <p>Enables high quality mode for the drawing cache.</p>
1730      *
1731      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1732      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1733      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1734      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1735      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1736      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1737      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1738      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1739      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1740      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1741      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1742      * reports or unit testing the {@link PixelCopy} API is recommended.
1743      */
1744     @Deprecated
1745     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1746 
1747     /**
1748      * <p>Enables automatic quality mode for the drawing cache.</p>
1749      *
1750      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1751      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1752      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1753      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1754      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1755      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1756      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1757      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1758      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1759      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1760      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1761      * reports or unit testing the {@link PixelCopy} API is recommended.
1762      */
1763     @Deprecated
1764     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1765 
1766     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1767             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1768     };
1769 
1770     /**
1771      * <p>Mask for use with setFlags indicating bits used for the cache
1772      * quality property.</p>
1773      * {@hide}
1774      */
1775     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1776 
1777     /**
1778      * <p>
1779      * Indicates this view can be long clicked. When long clickable, a View
1780      * reacts to long clicks by notifying the OnLongClickListener or showing a
1781      * context menu.
1782      * </p>
1783      * {@hide}
1784      */
1785     static final int LONG_CLICKABLE = 0x00200000;
1786 
1787     /**
1788      * <p>Indicates that this view gets its drawable states from its direct parent
1789      * and ignores its original internal states.</p>
1790      *
1791      * @hide
1792      */
1793     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1794 
1795     /**
1796      * <p>
1797      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1798      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1799      * OnContextClickListener.
1800      * </p>
1801      * {@hide}
1802      */
1803     static final int CONTEXT_CLICKABLE = 0x00800000;
1804 
1805     /** @hide */
1806     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1807             SCROLLBARS_INSIDE_OVERLAY,
1808             SCROLLBARS_INSIDE_INSET,
1809             SCROLLBARS_OUTSIDE_OVERLAY,
1810             SCROLLBARS_OUTSIDE_INSET
1811     })
1812     @Retention(RetentionPolicy.SOURCE)
1813     public @interface ScrollBarStyle {}
1814 
1815     /**
1816      * The scrollbar style to display the scrollbars inside the content area,
1817      * without increasing the padding. The scrollbars will be overlaid with
1818      * translucency on the view's content.
1819      */
1820     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1821 
1822     /**
1823      * The scrollbar style to display the scrollbars inside the padded area,
1824      * increasing the padding of the view. The scrollbars will not overlap the
1825      * content area of the view.
1826      */
1827     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1828 
1829     /**
1830      * The scrollbar style to display the scrollbars at the edge of the view,
1831      * without increasing the padding. The scrollbars will be overlaid with
1832      * translucency.
1833      */
1834     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1835 
1836     /**
1837      * The scrollbar style to display the scrollbars at the edge of the view,
1838      * increasing the padding of the view. The scrollbars will only overlap the
1839      * background, if any.
1840      */
1841     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1842 
1843     /**
1844      * Mask to check if the scrollbar style is overlay or inset.
1845      * {@hide}
1846      */
1847     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1848 
1849     /**
1850      * Mask to check if the scrollbar style is inside or outside.
1851      * {@hide}
1852      */
1853     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1854 
1855     /**
1856      * Mask for scrollbar style.
1857      * {@hide}
1858      */
1859     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1860 
1861     /**
1862      * View flag indicating that the screen should remain on while the
1863      * window containing this view is visible to the user.  This effectively
1864      * takes care of automatically setting the WindowManager's
1865      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1866      */
1867     public static final int KEEP_SCREEN_ON = 0x04000000;
1868 
1869     /**
1870      * View flag indicating whether this view should have sound effects enabled
1871      * for events such as clicking and touching.
1872      */
1873     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1874 
1875     /**
1876      * View flag indicating whether this view should have haptic feedback
1877      * enabled for events such as long presses.
1878      */
1879     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1880 
1881     /**
1882      * <p>Indicates that the view hierarchy should stop saving state when
1883      * it reaches this view.  If state saving is initiated immediately at
1884      * the view, it will be allowed.
1885      * {@hide}
1886      */
1887     static final int PARENT_SAVE_DISABLED = 0x20000000;
1888 
1889     /**
1890      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1891      * {@hide}
1892      */
1893     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1894 
1895     private static Paint sDebugPaint;
1896 
1897     /**
1898      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1899      * {@hide}
1900      */
1901     static final int TOOLTIP = 0x40000000;
1902 
1903     /** @hide */
1904     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1905             FOCUSABLES_ALL,
1906             FOCUSABLES_TOUCH_MODE
1907     })
1908     @Retention(RetentionPolicy.SOURCE)
1909     public @interface FocusableMode {}
1910 
1911     /**
1912      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1913      * should add all focusable Views regardless if they are focusable in touch mode.
1914      */
1915     public static final int FOCUSABLES_ALL = 0x00000000;
1916 
1917     /**
1918      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1919      * should add only Views focusable in touch mode.
1920      */
1921     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1922 
1923     /** @hide */
1924     @IntDef(prefix = { "FOCUS_" }, value = {
1925             FOCUS_BACKWARD,
1926             FOCUS_FORWARD,
1927             FOCUS_LEFT,
1928             FOCUS_UP,
1929             FOCUS_RIGHT,
1930             FOCUS_DOWN
1931     })
1932     @Retention(RetentionPolicy.SOURCE)
1933     public @interface FocusDirection {}
1934 
1935     /** @hide */
1936     @IntDef(prefix = { "FOCUS_" }, value = {
1937             FOCUS_LEFT,
1938             FOCUS_UP,
1939             FOCUS_RIGHT,
1940             FOCUS_DOWN
1941     })
1942     @Retention(RetentionPolicy.SOURCE)
1943     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1944 
1945     /**
1946      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1947      * item.
1948      */
1949     public static final int FOCUS_BACKWARD = 0x00000001;
1950 
1951     /**
1952      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1953      * item.
1954      */
1955     public static final int FOCUS_FORWARD = 0x00000002;
1956 
1957     /**
1958      * Use with {@link #focusSearch(int)}. Move focus to the left.
1959      */
1960     public static final int FOCUS_LEFT = 0x00000011;
1961 
1962     /**
1963      * Use with {@link #focusSearch(int)}. Move focus up.
1964      */
1965     public static final int FOCUS_UP = 0x00000021;
1966 
1967     /**
1968      * Use with {@link #focusSearch(int)}. Move focus to the right.
1969      */
1970     public static final int FOCUS_RIGHT = 0x00000042;
1971 
1972     /**
1973      * Use with {@link #focusSearch(int)}. Move focus down.
1974      */
1975     public static final int FOCUS_DOWN = 0x00000082;
1976 
1977     /**
1978      * Bits of {@link #getMeasuredWidthAndState()} and
1979      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1980      */
1981     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1982 
1983     /**
1984      * Bits of {@link #getMeasuredWidthAndState()} and
1985      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1986      */
1987     public static final int MEASURED_STATE_MASK = 0xff000000;
1988 
1989     /**
1990      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1991      * for functions that combine both width and height into a single int,
1992      * such as {@link #getMeasuredState()} and the childState argument of
1993      * {@link #resolveSizeAndState(int, int, int)}.
1994      */
1995     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1996 
1997     /**
1998      * Bit of {@link #getMeasuredWidthAndState()} and
1999      * {@link #getMeasuredWidthAndState()} that indicates the measured size
2000      * is smaller that the space the view would like to have.
2001      */
2002     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
2003 
2004     /**
2005      * Base View state sets
2006      */
2007     // Singles
2008     /**
2009      * Indicates the view has no states set. States are used with
2010      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2011      * view depending on its state.
2012      *
2013      * @see android.graphics.drawable.Drawable
2014      * @see #getDrawableState()
2015      */
2016     protected static final int[] EMPTY_STATE_SET;
2017     /**
2018      * Indicates the view is enabled. States are used with
2019      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2020      * view depending on its state.
2021      *
2022      * @see android.graphics.drawable.Drawable
2023      * @see #getDrawableState()
2024      */
2025     protected static final int[] ENABLED_STATE_SET;
2026     /**
2027      * Indicates the view is focused. States are used with
2028      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2029      * view depending on its state.
2030      *
2031      * @see android.graphics.drawable.Drawable
2032      * @see #getDrawableState()
2033      */
2034     protected static final int[] FOCUSED_STATE_SET;
2035     /**
2036      * Indicates the view is selected. States are used with
2037      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2038      * view depending on its state.
2039      *
2040      * @see android.graphics.drawable.Drawable
2041      * @see #getDrawableState()
2042      */
2043     protected static final int[] SELECTED_STATE_SET;
2044     /**
2045      * Indicates the view is pressed. States are used with
2046      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2047      * view depending on its state.
2048      *
2049      * @see android.graphics.drawable.Drawable
2050      * @see #getDrawableState()
2051      */
2052     protected static final int[] PRESSED_STATE_SET;
2053     /**
2054      * Indicates the view's window has focus. States are used with
2055      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2056      * view depending on its state.
2057      *
2058      * @see android.graphics.drawable.Drawable
2059      * @see #getDrawableState()
2060      */
2061     protected static final int[] WINDOW_FOCUSED_STATE_SET;
2062     // Doubles
2063     /**
2064      * Indicates the view is enabled and has the focus.
2065      *
2066      * @see #ENABLED_STATE_SET
2067      * @see #FOCUSED_STATE_SET
2068      */
2069     protected static final int[] ENABLED_FOCUSED_STATE_SET;
2070     /**
2071      * Indicates the view is enabled and selected.
2072      *
2073      * @see #ENABLED_STATE_SET
2074      * @see #SELECTED_STATE_SET
2075      */
2076     protected static final int[] ENABLED_SELECTED_STATE_SET;
2077     /**
2078      * Indicates the view is enabled and that its window has focus.
2079      *
2080      * @see #ENABLED_STATE_SET
2081      * @see #WINDOW_FOCUSED_STATE_SET
2082      */
2083     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
2084     /**
2085      * Indicates the view is focused and selected.
2086      *
2087      * @see #FOCUSED_STATE_SET
2088      * @see #SELECTED_STATE_SET
2089      */
2090     protected static final int[] FOCUSED_SELECTED_STATE_SET;
2091     /**
2092      * Indicates the view has the focus and that its window has the focus.
2093      *
2094      * @see #FOCUSED_STATE_SET
2095      * @see #WINDOW_FOCUSED_STATE_SET
2096      */
2097     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
2098     /**
2099      * Indicates the view is selected and that its window has the focus.
2100      *
2101      * @see #SELECTED_STATE_SET
2102      * @see #WINDOW_FOCUSED_STATE_SET
2103      */
2104     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2105     // Triples
2106     /**
2107      * Indicates the view is enabled, focused and selected.
2108      *
2109      * @see #ENABLED_STATE_SET
2110      * @see #FOCUSED_STATE_SET
2111      * @see #SELECTED_STATE_SET
2112      */
2113     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2114     /**
2115      * Indicates the view is enabled, focused and its window has the focus.
2116      *
2117      * @see #ENABLED_STATE_SET
2118      * @see #FOCUSED_STATE_SET
2119      * @see #WINDOW_FOCUSED_STATE_SET
2120      */
2121     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2122     /**
2123      * Indicates the view is enabled, selected and its window has the focus.
2124      *
2125      * @see #ENABLED_STATE_SET
2126      * @see #SELECTED_STATE_SET
2127      * @see #WINDOW_FOCUSED_STATE_SET
2128      */
2129     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2130     /**
2131      * Indicates the view is focused, selected and its window has the focus.
2132      *
2133      * @see #FOCUSED_STATE_SET
2134      * @see #SELECTED_STATE_SET
2135      * @see #WINDOW_FOCUSED_STATE_SET
2136      */
2137     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2138     /**
2139      * Indicates the view is enabled, focused, selected and its window
2140      * has the focus.
2141      *
2142      * @see #ENABLED_STATE_SET
2143      * @see #FOCUSED_STATE_SET
2144      * @see #SELECTED_STATE_SET
2145      * @see #WINDOW_FOCUSED_STATE_SET
2146      */
2147     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2148     /**
2149      * Indicates the view is pressed and its window has the focus.
2150      *
2151      * @see #PRESSED_STATE_SET
2152      * @see #WINDOW_FOCUSED_STATE_SET
2153      */
2154     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2155     /**
2156      * Indicates the view is pressed and selected.
2157      *
2158      * @see #PRESSED_STATE_SET
2159      * @see #SELECTED_STATE_SET
2160      */
2161     protected static final int[] PRESSED_SELECTED_STATE_SET;
2162     /**
2163      * Indicates the view is pressed, selected and its window has the focus.
2164      *
2165      * @see #PRESSED_STATE_SET
2166      * @see #SELECTED_STATE_SET
2167      * @see #WINDOW_FOCUSED_STATE_SET
2168      */
2169     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2170     /**
2171      * Indicates the view is pressed and focused.
2172      *
2173      * @see #PRESSED_STATE_SET
2174      * @see #FOCUSED_STATE_SET
2175      */
2176     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2177     /**
2178      * Indicates the view is pressed, focused and its window has the focus.
2179      *
2180      * @see #PRESSED_STATE_SET
2181      * @see #FOCUSED_STATE_SET
2182      * @see #WINDOW_FOCUSED_STATE_SET
2183      */
2184     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2185     /**
2186      * Indicates the view is pressed, focused and selected.
2187      *
2188      * @see #PRESSED_STATE_SET
2189      * @see #SELECTED_STATE_SET
2190      * @see #FOCUSED_STATE_SET
2191      */
2192     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2193     /**
2194      * Indicates the view is pressed, focused, selected and its window has the focus.
2195      *
2196      * @see #PRESSED_STATE_SET
2197      * @see #FOCUSED_STATE_SET
2198      * @see #SELECTED_STATE_SET
2199      * @see #WINDOW_FOCUSED_STATE_SET
2200      */
2201     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2202     /**
2203      * Indicates the view is pressed and enabled.
2204      *
2205      * @see #PRESSED_STATE_SET
2206      * @see #ENABLED_STATE_SET
2207      */
2208     protected static final int[] PRESSED_ENABLED_STATE_SET;
2209     /**
2210      * Indicates the view is pressed, enabled and its window has the focus.
2211      *
2212      * @see #PRESSED_STATE_SET
2213      * @see #ENABLED_STATE_SET
2214      * @see #WINDOW_FOCUSED_STATE_SET
2215      */
2216     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2217     /**
2218      * Indicates the view is pressed, enabled and selected.
2219      *
2220      * @see #PRESSED_STATE_SET
2221      * @see #ENABLED_STATE_SET
2222      * @see #SELECTED_STATE_SET
2223      */
2224     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2225     /**
2226      * Indicates the view is pressed, enabled, selected and its window has the
2227      * focus.
2228      *
2229      * @see #PRESSED_STATE_SET
2230      * @see #ENABLED_STATE_SET
2231      * @see #SELECTED_STATE_SET
2232      * @see #WINDOW_FOCUSED_STATE_SET
2233      */
2234     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2235     /**
2236      * Indicates the view is pressed, enabled and focused.
2237      *
2238      * @see #PRESSED_STATE_SET
2239      * @see #ENABLED_STATE_SET
2240      * @see #FOCUSED_STATE_SET
2241      */
2242     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2243     /**
2244      * Indicates the view is pressed, enabled, focused and its window has the
2245      * focus.
2246      *
2247      * @see #PRESSED_STATE_SET
2248      * @see #ENABLED_STATE_SET
2249      * @see #FOCUSED_STATE_SET
2250      * @see #WINDOW_FOCUSED_STATE_SET
2251      */
2252     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2253     /**
2254      * Indicates the view is pressed, enabled, focused and selected.
2255      *
2256      * @see #PRESSED_STATE_SET
2257      * @see #ENABLED_STATE_SET
2258      * @see #SELECTED_STATE_SET
2259      * @see #FOCUSED_STATE_SET
2260      */
2261     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2262     /**
2263      * Indicates the view is pressed, enabled, focused, selected and its window
2264      * has the focus.
2265      *
2266      * @see #PRESSED_STATE_SET
2267      * @see #ENABLED_STATE_SET
2268      * @see #SELECTED_STATE_SET
2269      * @see #FOCUSED_STATE_SET
2270      * @see #WINDOW_FOCUSED_STATE_SET
2271      */
2272     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2273 
2274     static {
2275         EMPTY_STATE_SET = StateSet.get(0);
2276 
2277         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2278 
2279         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2280         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2281                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2282 
2283         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2284         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2285                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2286         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2287                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2288         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2289                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2290                         | StateSet.VIEW_STATE_FOCUSED);
2291 
2292         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2293         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2294                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2295         ENABLED_SELECTED_STATE_SET = StateSet.get(
2296                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2297         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2298                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2299                         | StateSet.VIEW_STATE_ENABLED);
2300         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2301                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2302         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2303                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2304                         | StateSet.VIEW_STATE_ENABLED);
2305         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2306                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2307                         | StateSet.VIEW_STATE_ENABLED);
2308         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2309                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2310                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2311 
2312         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2313         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2314                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2315         PRESSED_SELECTED_STATE_SET = StateSet.get(
2316                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2317         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2318                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2319                         | StateSet.VIEW_STATE_PRESSED);
2320         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2321                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2322         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2323                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2324                         | StateSet.VIEW_STATE_PRESSED);
2325         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2326                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2327                         | StateSet.VIEW_STATE_PRESSED);
2328         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2329                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2330                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2331         PRESSED_ENABLED_STATE_SET = StateSet.get(
2332                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2333         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2334                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2335                         | StateSet.VIEW_STATE_PRESSED);
2336         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2337                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2338                         | StateSet.VIEW_STATE_PRESSED);
2339         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2340                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2341                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2342         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2343                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2344                         | StateSet.VIEW_STATE_PRESSED);
2345         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2346                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2347                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2348         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2349                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2350                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2351         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2352                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2353                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2354                         | StateSet.VIEW_STATE_PRESSED);
2355     }
2356 
2357     /**
2358      * Accessibility event types that are dispatched for text population.
2359      */
2360     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2361             AccessibilityEvent.TYPE_VIEW_CLICKED
2362             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2363             | AccessibilityEvent.TYPE_VIEW_SELECTED
2364             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2365             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2366             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2367             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2368             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2369             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2370             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2371             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2372 
2373     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2374 
2375     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2376 
2377     /**
2378      * Temporary Rect currently for use in setBackground().  This will probably
2379      * be extended in the future to hold our own class with more than just
2380      * a Rect. :)
2381      */
2382     static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
2383 
2384     /**
2385      * Map used to store views' tags.
2386      */
2387     @UnsupportedAppUsage
2388     private SparseArray<Object> mKeyedTags;
2389 
2390     /**
2391      * The next available accessibility id.
2392      */
2393     private static int sNextAccessibilityViewId;
2394 
2395     /**
2396      * The animation currently associated with this view.
2397      * @hide
2398      */
2399     protected Animation mCurrentAnimation = null;
2400 
2401     /**
2402      * Width as measured during measure pass.
2403      * {@hide}
2404      */
2405     @ViewDebug.ExportedProperty(category = "measurement")
2406     @UnsupportedAppUsage
2407     int mMeasuredWidth;
2408 
2409     /**
2410      * Height as measured during measure pass.
2411      * {@hide}
2412      */
2413     @ViewDebug.ExportedProperty(category = "measurement")
2414     @UnsupportedAppUsage
2415     int mMeasuredHeight;
2416 
2417     /**
2418      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2419      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2420      * its display list. This flag, used only when hw accelerated, allows us to clear the
2421      * flag while retaining this information until it's needed (at getDisplayList() time and
2422      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2423      *
2424      * {@hide}
2425      */
2426     @UnsupportedAppUsage
2427     boolean mRecreateDisplayList = false;
2428 
2429     /**
2430      * The view's identifier.
2431      * {@hide}
2432      *
2433      * @see #setId(int)
2434      * @see #getId()
2435      */
2436     @IdRes
2437     @ViewDebug.ExportedProperty(resolveId = true)
2438     int mID = NO_ID;
2439 
2440     /** The ID of this view for autofill purposes.
2441      * <ul>
2442      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2443      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2444      *                                                  unique in the process. This might change
2445      *                                                  over activity lifecycle events.
2446      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2447      *                                                  unique in the activity. This stays the same
2448      *                                                  over activity lifecycle events.
2449      */
2450     private int mAutofillViewId = NO_ID;
2451 
2452     // ID for accessibility purposes. This ID must be unique for every window
2453     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2454     private int mAccessibilityViewId = NO_ID;
2455 
2456     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2457 
2458     /**
2459      * The view's tag.
2460      * {@hide}
2461      *
2462      * @see #setTag(Object)
2463      * @see #getTag()
2464      */
2465     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2466     protected Object mTag = null;
2467 
2468     /*
2469      * Masks for mPrivateFlags, as generated by dumpFlags():
2470      *
2471      * |-------|-------|-------|-------|
2472      *                                 1 PFLAG_WANTS_FOCUS
2473      *                                1  PFLAG_FOCUSED
2474      *                               1   PFLAG_SELECTED
2475      *                              1    PFLAG_IS_ROOT_NAMESPACE
2476      *                             1     PFLAG_HAS_BOUNDS
2477      *                            1      PFLAG_DRAWN
2478      *                           1       PFLAG_DRAW_ANIMATION
2479      *                          1        PFLAG_SKIP_DRAW
2480      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2481      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2482      *                      1            PFLAG_MEASURED_DIMENSION_SET
2483      *                     1             PFLAG_FORCE_LAYOUT
2484      *                    1              PFLAG_LAYOUT_REQUIRED
2485      *                   1               PFLAG_PRESSED
2486      *                  1                PFLAG_DRAWING_CACHE_VALID
2487      *                 1                 PFLAG_ANIMATION_STARTED
2488      *                1                  PFLAG_SAVE_STATE_CALLED
2489      *               1                   PFLAG_ALPHA_SET
2490      *              1                    PFLAG_SCROLL_CONTAINER
2491      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2492      *            1                      PFLAG_DIRTY
2493      *            1                      PFLAG_DIRTY_MASK
2494      *          1                        PFLAG_OPAQUE_BACKGROUND
2495      *         1                         PFLAG_OPAQUE_SCROLLBARS
2496      *         11                        PFLAG_OPAQUE_MASK
2497      *        1                          PFLAG_PREPRESSED
2498      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2499      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2500      *     1                             PFLAG_HOVERED
2501      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2502      *   1                               PFLAG_ACTIVATED
2503      *  1                                PFLAG_INVALIDATED
2504      * |-------|-------|-------|-------|
2505      */
2506     /** {@hide} */
2507     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2508     /** {@hide} */
2509     static final int PFLAG_FOCUSED                     = 0x00000002;
2510     /** {@hide} */
2511     static final int PFLAG_SELECTED                    = 0x00000004;
2512     /** {@hide} */
2513     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2514     /** {@hide} */
2515     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2516     /** {@hide} */
2517     static final int PFLAG_DRAWN                       = 0x00000020;
2518     /**
2519      * When this flag is set, this view is running an animation on behalf of its
2520      * children and should therefore not cancel invalidate requests, even if they
2521      * lie outside of this view's bounds.
2522      *
2523      * {@hide}
2524      */
2525     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2526     /** {@hide} */
2527     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2528     /** {@hide} */
2529     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2530     /** {@hide} */
2531     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2532     /** {@hide} */
2533     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2534     /** {@hide} */
2535     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2536     /** {@hide} */
2537     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2538 
2539     private static final int PFLAG_PRESSED             = 0x00004000;
2540 
2541     /** {@hide} */
2542     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2543     /**
2544      * Flag used to indicate that this view should be drawn once more (and only once
2545      * more) after its animation has completed.
2546      * {@hide}
2547      */
2548     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2549 
2550     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2551 
2552     /**
2553      * Indicates that the View returned true when onSetAlpha() was called and that
2554      * the alpha must be restored.
2555      * {@hide}
2556      */
2557     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2558 
2559     /**
2560      * Set by {@link #setScrollContainer(boolean)}.
2561      */
2562     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2563 
2564     /**
2565      * Set by {@link #setScrollContainer(boolean)}.
2566      */
2567     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2568 
2569     /**
2570      * View flag indicating whether this view was invalidated (fully or partially.)
2571      *
2572      * @hide
2573      */
2574     static final int PFLAG_DIRTY                       = 0x00200000;
2575 
2576     /**
2577      * Mask for {@link #PFLAG_DIRTY}.
2578      *
2579      * @hide
2580      */
2581     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2582 
2583     /**
2584      * Indicates whether the background is opaque.
2585      *
2586      * @hide
2587      */
2588     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2589 
2590     /**
2591      * Indicates whether the scrollbars are opaque.
2592      *
2593      * @hide
2594      */
2595     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2596 
2597     /**
2598      * Indicates whether the view is opaque.
2599      *
2600      * @hide
2601      */
2602     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2603 
2604     /**
2605      * Indicates a prepressed state;
2606      * the short time between ACTION_DOWN and recognizing
2607      * a 'real' press. Prepressed is used to recognize quick taps
2608      * even when they are shorter than ViewConfiguration.getTapTimeout().
2609      *
2610      * @hide
2611      */
2612     private static final int PFLAG_PREPRESSED          = 0x02000000;
2613 
2614     /**
2615      * Indicates whether the view is temporarily detached.
2616      *
2617      * @hide
2618      */
2619     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2620 
2621     /**
2622      * Indicates that we should awaken scroll bars once attached
2623      *
2624      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2625      * during window attachment and it is no longer needed. Feel free to repurpose it.
2626      *
2627      * @hide
2628      */
2629     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2630 
2631     /**
2632      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2633      * @hide
2634      */
2635     private static final int PFLAG_HOVERED             = 0x10000000;
2636 
2637     /**
2638      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2639      */
2640     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2641 
2642     /** {@hide} */
2643     static final int PFLAG_ACTIVATED                   = 0x40000000;
2644 
2645     /**
2646      * Indicates that this view was specifically invalidated, not just dirtied because some
2647      * child view was invalidated. The flag is used to determine when we need to recreate
2648      * a view's display list (as opposed to just returning a reference to its existing
2649      * display list).
2650      *
2651      * @hide
2652      */
2653     static final int PFLAG_INVALIDATED                 = 0x80000000;
2654 
2655     /* End of masks for mPrivateFlags */
2656 
2657     /*
2658      * Masks for mPrivateFlags2, as generated by dumpFlags():
2659      *
2660      * |-------|-------|-------|-------|
2661      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2662      *                                1  PFLAG2_DRAG_HOVERED
2663      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2664      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2665      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2666      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2667      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2668      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2669      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2670      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2671      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2672      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2673      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2674      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2675      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2676      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2677      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2678      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2679      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2680      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2681      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2682      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2683      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2684      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2685      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2686      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2687      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2688      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2689      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2690      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2691      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2692      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2693      *    1                              PFLAG2_PADDING_RESOLVED
2694      *   1                               PFLAG2_DRAWABLE_RESOLVED
2695      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2696      * |-------|-------|-------|-------|
2697      */
2698 
2699     /**
2700      * Indicates that this view has reported that it can accept the current drag's content.
2701      * Cleared when the drag operation concludes.
2702      * @hide
2703      */
2704     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2705 
2706     /**
2707      * Indicates that this view is currently directly under the drag location in a
2708      * drag-and-drop operation involving content that it can accept.  Cleared when
2709      * the drag exits the view, or when the drag operation concludes.
2710      * @hide
2711      */
2712     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2713 
2714     /** @hide */
2715     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2716             LAYOUT_DIRECTION_LTR,
2717             LAYOUT_DIRECTION_RTL,
2718             LAYOUT_DIRECTION_INHERIT,
2719             LAYOUT_DIRECTION_LOCALE
2720     })
2721     @Retention(RetentionPolicy.SOURCE)
2722     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2723     public @interface LayoutDir {}
2724 
2725     /** @hide */
2726     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2727             LAYOUT_DIRECTION_LTR,
2728             LAYOUT_DIRECTION_RTL
2729     })
2730     @Retention(RetentionPolicy.SOURCE)
2731     public @interface ResolvedLayoutDir {}
2732 
2733     /**
2734      * A flag to indicate that the layout direction of this view has not been defined yet.
2735      * @hide
2736      */
2737     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2738 
2739     /**
2740      * Horizontal layout direction of this view is from Left to Right.
2741      * Use with {@link #setLayoutDirection}.
2742      */
2743     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2744 
2745     /**
2746      * Horizontal layout direction of this view is from Right to Left.
2747      * Use with {@link #setLayoutDirection}.
2748      */
2749     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2750 
2751     /**
2752      * Horizontal layout direction of this view is inherited from its parent.
2753      * Use with {@link #setLayoutDirection}.
2754      */
2755     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2756 
2757     /**
2758      * Horizontal layout direction of this view is from deduced from the default language
2759      * script for the locale. Use with {@link #setLayoutDirection}.
2760      */
2761     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2762 
2763     /**
2764      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2765      * @hide
2766      */
2767     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2768 
2769     /**
2770      * Mask for use with private flags indicating bits used for horizontal layout direction.
2771      * @hide
2772      */
2773     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2774 
2775     /**
2776      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2777      * right-to-left direction.
2778      * @hide
2779      */
2780     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2781 
2782     /**
2783      * Indicates whether the view horizontal layout direction has been resolved.
2784      * @hide
2785      */
2786     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2787 
2788     /**
2789      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2790      * @hide
2791      */
2792     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2793             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2794 
2795     /*
2796      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2797      * flag value.
2798      * @hide
2799      */
2800     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2801             LAYOUT_DIRECTION_LTR,
2802             LAYOUT_DIRECTION_RTL,
2803             LAYOUT_DIRECTION_INHERIT,
2804             LAYOUT_DIRECTION_LOCALE
2805     };
2806 
2807     /**
2808      * Default horizontal layout direction.
2809      */
2810     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2811 
2812     /**
2813      * Default horizontal layout direction.
2814      * @hide
2815      */
2816     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2817 
2818     /**
2819      * Text direction is inherited through {@link ViewGroup}
2820      */
2821     public static final int TEXT_DIRECTION_INHERIT = 0;
2822 
2823     /**
2824      * Text direction is using "first strong algorithm". The first strong directional character
2825      * determines the paragraph direction. If there is no strong directional character, the
2826      * paragraph direction is the view's resolved layout direction.
2827      */
2828     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2829 
2830     /**
2831      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2832      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2833      * If there are neither, the paragraph direction is the view's resolved layout direction.
2834      */
2835     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2836 
2837     /**
2838      * Text direction is forced to LTR.
2839      */
2840     public static final int TEXT_DIRECTION_LTR = 3;
2841 
2842     /**
2843      * Text direction is forced to RTL.
2844      */
2845     public static final int TEXT_DIRECTION_RTL = 4;
2846 
2847     /**
2848      * Text direction is coming from the system Locale.
2849      */
2850     public static final int TEXT_DIRECTION_LOCALE = 5;
2851 
2852     /**
2853      * Text direction is using "first strong algorithm". The first strong directional character
2854      * determines the paragraph direction. If there is no strong directional character, the
2855      * paragraph direction is LTR.
2856      */
2857     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2858 
2859     /**
2860      * Text direction is using "first strong algorithm". The first strong directional character
2861      * determines the paragraph direction. If there is no strong directional character, the
2862      * paragraph direction is RTL.
2863      */
2864     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2865 
2866     /**
2867      * Default text direction is inherited
2868      */
2869     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2870 
2871     /**
2872      * Default resolved text direction
2873      * @hide
2874      */
2875     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2876 
2877     /**
2878      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2879      * @hide
2880      */
2881     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2882 
2883     /**
2884      * Mask for use with private flags indicating bits used for text direction.
2885      * @hide
2886      */
2887     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2888             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2889 
2890     /**
2891      * Array of text direction flags for mapping attribute "textDirection" to correct
2892      * flag value.
2893      * @hide
2894      */
2895     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2896             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2897             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2898             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2899             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2900             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2901             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2902             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2903             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2904     };
2905 
2906     /**
2907      * Indicates whether the view text direction has been resolved.
2908      * @hide
2909      */
2910     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2911             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2912 
2913     /**
2914      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2915      * @hide
2916      */
2917     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2918 
2919     /**
2920      * Mask for use with private flags indicating bits used for resolved text direction.
2921      * @hide
2922      */
2923     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2924             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2925 
2926     /**
2927      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2928      * @hide
2929      */
2930     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2931             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2932 
2933     /** @hide */
2934     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2935             TEXT_ALIGNMENT_INHERIT,
2936             TEXT_ALIGNMENT_GRAVITY,
2937             TEXT_ALIGNMENT_CENTER,
2938             TEXT_ALIGNMENT_TEXT_START,
2939             TEXT_ALIGNMENT_TEXT_END,
2940             TEXT_ALIGNMENT_VIEW_START,
2941             TEXT_ALIGNMENT_VIEW_END
2942     })
2943     @Retention(RetentionPolicy.SOURCE)
2944     public @interface TextAlignment {}
2945 
2946     /**
2947      * Default text alignment. The text alignment of this View is inherited from its parent.
2948      * Use with {@link #setTextAlignment(int)}
2949      */
2950     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2951 
2952     /**
2953      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2954      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
2955      *
2956      * Use with {@link #setTextAlignment(int)}
2957      */
2958     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2959 
2960     /**
2961      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2962      *
2963      * Use with {@link #setTextAlignment(int)}
2964      */
2965     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2966 
2967     /**
2968      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2969      *
2970      * Use with {@link #setTextAlignment(int)}
2971      */
2972     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2973 
2974     /**
2975      * Center the paragraph, e.g. ALIGN_CENTER.
2976      *
2977      * Use with {@link #setTextAlignment(int)}
2978      */
2979     public static final int TEXT_ALIGNMENT_CENTER = 4;
2980 
2981     /**
2982      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
2983      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2984      *
2985      * Use with {@link #setTextAlignment(int)}
2986      */
2987     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2988 
2989     /**
2990      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
2991      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2992      *
2993      * Use with {@link #setTextAlignment(int)}
2994      */
2995     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2996 
2997     /**
2998      * Default text alignment is inherited
2999      */
3000     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3001 
3002     /**
3003      * Default resolved text alignment
3004      * @hide
3005      */
3006     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3007 
3008     /**
3009       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
3010       * @hide
3011       */
3012     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
3013 
3014     /**
3015       * Mask for use with private flags indicating bits used for text alignment.
3016       * @hide
3017       */
3018     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3019 
3020     /**
3021      * Array of text direction flags for mapping attribute "textAlignment" to correct
3022      * flag value.
3023      * @hide
3024      */
3025     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
3026             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3027             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3028             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3029             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3030             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3031             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3032             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
3033     };
3034 
3035     /**
3036      * Indicates whether the view text alignment has been resolved.
3037      * @hide
3038      */
3039     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3040 
3041     /**
3042      * Bit shift to get the resolved text alignment.
3043      * @hide
3044      */
3045     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
3046 
3047     /**
3048      * Mask for use with private flags indicating bits used for text alignment.
3049      * @hide
3050      */
3051     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
3052             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3053 
3054     /**
3055      * Indicates whether if the view text alignment has been resolved to gravity
3056      */
3057     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
3058             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3059 
3060     // Accessiblity constants for mPrivateFlags2
3061 
3062     /**
3063      * Shift for the bits in {@link #mPrivateFlags2} related to the
3064      * "importantForAccessibility" attribute.
3065      */
3066     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
3067 
3068     /**
3069      * Automatically determine whether a view is important for accessibility.
3070      */
3071     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
3072 
3073     /**
3074      * The view is important for accessibility.
3075      */
3076     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
3077 
3078     /**
3079      * The view is not important for accessibility.
3080      */
3081     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
3082 
3083     /**
3084      * The view is not important for accessibility, nor are any of its
3085      * descendant views.
3086      */
3087     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
3088 
3089     /**
3090      * The default whether the view is important for accessibility.
3091      */
3092     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3093 
3094     /**
3095      * Mask for obtaining the bits which specify how to determine
3096      * whether a view is important for accessibility.
3097      */
3098     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
3099         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
3100         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
3101         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3102 
3103     /**
3104      * Shift for the bits in {@link #mPrivateFlags2} related to the
3105      * "accessibilityLiveRegion" attribute.
3106      */
3107     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3108 
3109     /**
3110      * Live region mode specifying that accessibility services should not
3111      * automatically announce changes to this view. This is the default live
3112      * region mode for most views.
3113      * <p>
3114      * Use with {@link #setAccessibilityLiveRegion(int)}.
3115      */
3116     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3117 
3118     /**
3119      * Live region mode specifying that accessibility services should announce
3120      * changes to this view.
3121      * <p>
3122      * Use with {@link #setAccessibilityLiveRegion(int)}.
3123      */
3124     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3125 
3126     /**
3127      * Live region mode specifying that accessibility services should interrupt
3128      * ongoing speech to immediately announce changes to this view.
3129      * <p>
3130      * Use with {@link #setAccessibilityLiveRegion(int)}.
3131      */
3132     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3133 
3134     /**
3135      * The default whether the view is important for accessibility.
3136      */
3137     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3138 
3139     /**
3140      * Mask for obtaining the bits which specify a view's accessibility live
3141      * region mode.
3142      */
3143     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3144             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3145             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3146 
3147     /**
3148      * Flag indicating whether a view has accessibility focus.
3149      */
3150     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3151 
3152     /**
3153      * Flag whether the accessibility state of the subtree rooted at this view changed.
3154      */
3155     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3156 
3157     /**
3158      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3159      * is used to check whether later changes to the view's transform should invalidate the
3160      * view to force the quickReject test to run again.
3161      */
3162     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3163 
3164     /**
3165      * Flag indicating that start/end padding has been resolved into left/right padding
3166      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3167      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3168      * during measurement. In some special cases this is required such as when an adapter-based
3169      * view measures prospective children without attaching them to a window.
3170      */
3171     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3172 
3173     /**
3174      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3175      */
3176     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3177 
3178     /**
3179      * Indicates that the view is tracking some sort of transient state
3180      * that the app should not need to be aware of, but that the framework
3181      * should take special care to preserve.
3182      */
3183     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3184 
3185     /**
3186      * Group of bits indicating that RTL properties resolution is done.
3187      */
3188     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3189             PFLAG2_TEXT_DIRECTION_RESOLVED |
3190             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3191             PFLAG2_PADDING_RESOLVED |
3192             PFLAG2_DRAWABLE_RESOLVED;
3193 
3194     // There are a couple of flags left in mPrivateFlags2
3195 
3196     /* End of masks for mPrivateFlags2 */
3197 
3198     /*
3199      * Masks for mPrivateFlags3, as generated by dumpFlags():
3200      *
3201      * |-------|-------|-------|-------|
3202      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3203      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3204      *                               1   PFLAG3_IS_LAID_OUT
3205      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3206      *                             1     PFLAG3_CALLED_SUPER
3207      *                            1      PFLAG3_APPLYING_INSETS
3208      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3209      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3210      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3211      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3212      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3213      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3214      *                     1             PFLAG3_SCROLL_INDICATOR_START
3215      *                    1              PFLAG3_SCROLL_INDICATOR_END
3216      *                   1               PFLAG3_ASSIST_BLOCKED
3217      *                  1                PFLAG3_CLUSTER
3218      *                 1                 PFLAG3_IS_AUTOFILLED
3219      *                1                  PFLAG3_FINGER_DOWN
3220      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3221      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3222      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3223      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3224      *        1                          PFLAG3_TEMPORARY_DETACH
3225      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3226      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3227      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3228      *    1                              PFLAG3_AGGREGATED_VISIBLE
3229      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3230      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3231      * |-------|-------|-------|-------|
3232      */
3233 
3234     /**
3235      * Flag indicating that view has a transform animation set on it. This is used to track whether
3236      * an animation is cleared between successive frames, in order to tell the associated
3237      * DisplayList to clear its animation matrix.
3238      */
3239     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3240 
3241     /**
3242      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3243      * animation is cleared between successive frames, in order to tell the associated
3244      * DisplayList to restore its alpha value.
3245      */
3246     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3247 
3248     /**
3249      * Flag indicating that the view has been through at least one layout since it
3250      * was last attached to a window.
3251      */
3252     static final int PFLAG3_IS_LAID_OUT = 0x4;
3253 
3254     /**
3255      * Flag indicating that a call to measure() was skipped and should be done
3256      * instead when layout() is invoked.
3257      */
3258     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3259 
3260     /**
3261      * Flag indicating that an overridden method correctly called down to
3262      * the superclass implementation as required by the API spec.
3263      */
3264     static final int PFLAG3_CALLED_SUPER = 0x10;
3265 
3266     /**
3267      * Flag indicating that we're in the process of applying window insets.
3268      */
3269     static final int PFLAG3_APPLYING_INSETS = 0x20;
3270 
3271     /**
3272      * Flag indicating that we're in the process of fitting system windows using the old method.
3273      */
3274     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3275 
3276     /**
3277      * Flag indicating that nested scrolling is enabled for this view.
3278      * The view will optionally cooperate with views up its parent chain to allow for
3279      * integrated nested scrolling along the same axis.
3280      */
3281     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3282 
3283     /**
3284      * Flag indicating that the bottom scroll indicator should be displayed
3285      * when this view can scroll up.
3286      */
3287     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3288 
3289     /**
3290      * Flag indicating that the bottom scroll indicator should be displayed
3291      * when this view can scroll down.
3292      */
3293     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3294 
3295     /**
3296      * Flag indicating that the left scroll indicator should be displayed
3297      * when this view can scroll left.
3298      */
3299     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3300 
3301     /**
3302      * Flag indicating that the right scroll indicator should be displayed
3303      * when this view can scroll right.
3304      */
3305     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3306 
3307     /**
3308      * Flag indicating that the start scroll indicator should be displayed
3309      * when this view can scroll in the start direction.
3310      */
3311     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3312 
3313     /**
3314      * Flag indicating that the end scroll indicator should be displayed
3315      * when this view can scroll in the end direction.
3316      */
3317     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3318 
3319     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3320 
3321     static final int SCROLL_INDICATORS_NONE = 0x0000;
3322 
3323     /**
3324      * Mask for use with setFlags indicating bits used for indicating which
3325      * scroll indicators are enabled.
3326      */
3327     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3328             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3329             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3330             | PFLAG3_SCROLL_INDICATOR_END;
3331 
3332     /**
3333      * Left-shift required to translate between public scroll indicator flags
3334      * and internal PFLAGS3 flags. When used as a right-shift, translates
3335      * PFLAGS3 flags to public flags.
3336      */
3337     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3338 
3339     /** @hide */
3340     @Retention(RetentionPolicy.SOURCE)
3341     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3342             SCROLL_INDICATOR_TOP,
3343             SCROLL_INDICATOR_BOTTOM,
3344             SCROLL_INDICATOR_LEFT,
3345             SCROLL_INDICATOR_RIGHT,
3346             SCROLL_INDICATOR_START,
3347             SCROLL_INDICATOR_END,
3348     })
3349     public @interface ScrollIndicators {}
3350 
3351     /**
3352      * Scroll indicator direction for the top edge of the view.
3353      *
3354      * @see #setScrollIndicators(int)
3355      * @see #setScrollIndicators(int, int)
3356      * @see #getScrollIndicators()
3357      */
3358     public static final int SCROLL_INDICATOR_TOP =
3359             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3360 
3361     /**
3362      * Scroll indicator direction for the bottom edge of the view.
3363      *
3364      * @see #setScrollIndicators(int)
3365      * @see #setScrollIndicators(int, int)
3366      * @see #getScrollIndicators()
3367      */
3368     public static final int SCROLL_INDICATOR_BOTTOM =
3369             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3370 
3371     /**
3372      * Scroll indicator direction for the left edge of the view.
3373      *
3374      * @see #setScrollIndicators(int)
3375      * @see #setScrollIndicators(int, int)
3376      * @see #getScrollIndicators()
3377      */
3378     public static final int SCROLL_INDICATOR_LEFT =
3379             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3380 
3381     /**
3382      * Scroll indicator direction for the right edge of the view.
3383      *
3384      * @see #setScrollIndicators(int)
3385      * @see #setScrollIndicators(int, int)
3386      * @see #getScrollIndicators()
3387      */
3388     public static final int SCROLL_INDICATOR_RIGHT =
3389             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3390 
3391     /**
3392      * Scroll indicator direction for the starting edge of the view.
3393      * <p>
3394      * Resolved according to the view's layout direction, see
3395      * {@link #getLayoutDirection()} for more information.
3396      *
3397      * @see #setScrollIndicators(int)
3398      * @see #setScrollIndicators(int, int)
3399      * @see #getScrollIndicators()
3400      */
3401     public static final int SCROLL_INDICATOR_START =
3402             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3403 
3404     /**
3405      * Scroll indicator direction for the ending edge of the view.
3406      * <p>
3407      * Resolved according to the view's layout direction, see
3408      * {@link #getLayoutDirection()} for more information.
3409      *
3410      * @see #setScrollIndicators(int)
3411      * @see #setScrollIndicators(int, int)
3412      * @see #getScrollIndicators()
3413      */
3414     public static final int SCROLL_INDICATOR_END =
3415             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3416 
3417     /**
3418      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3419      * into this view.<p>
3420      */
3421     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3422 
3423     /**
3424      * Flag indicating that the view is a root of a keyboard navigation cluster.
3425      *
3426      * @see #isKeyboardNavigationCluster()
3427      * @see #setKeyboardNavigationCluster(boolean)
3428      */
3429     private static final int PFLAG3_CLUSTER = 0x8000;
3430 
3431     /**
3432      * Flag indicating that the view is autofilled
3433      *
3434      * @see #isAutofilled()
3435      * @see #setAutofilled(boolean, boolean)
3436      */
3437     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3438 
3439     /**
3440      * Indicates that the user is currently touching the screen.
3441      * Currently used for the tooltip positioning only.
3442      */
3443     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3444 
3445     /**
3446      * Flag indicating that this view is the default-focus view.
3447      *
3448      * @see #isFocusedByDefault()
3449      * @see #setFocusedByDefault(boolean)
3450      */
3451     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3452 
3453     /**
3454      * Shift for the bits in {@link #mPrivateFlags3} related to the
3455      * "importantForAutofill" attribute.
3456      */
3457     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3458 
3459     /**
3460      * Mask for obtaining the bits which specify how to determine
3461      * whether a view is important for autofill.
3462      */
3463     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3464             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3465             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3466             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3467             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3468 
3469     /**
3470      * Whether this view has rendered elements that overlap (see {@link
3471      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3472      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3473      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3474      * determined by whatever {@link #hasOverlappingRendering()} returns.
3475      */
3476     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3477 
3478     /**
3479      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3480      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3481      */
3482     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3483 
3484     /**
3485      * Flag indicating that the view is temporarily detached from the parent view.
3486      *
3487      * @see #onStartTemporaryDetach()
3488      * @see #onFinishTemporaryDetach()
3489      */
3490     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3491 
3492     /**
3493      * Flag indicating that the view does not wish to be revealed within its parent
3494      * hierarchy when it gains focus. Expressed in the negative since the historical
3495      * default behavior is to reveal on focus; this flag suppresses that behavior.
3496      *
3497      * @see #setRevealOnFocusHint(boolean)
3498      * @see #getRevealOnFocusHint()
3499      */
3500     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3501 
3502     /**
3503      * Flag indicating that when layout is completed we should notify
3504      * that the view was entered for autofill purposes. To minimize
3505      * showing autofill for views not visible to the user we evaluate
3506      * user visibility which cannot be done until the view is laid out.
3507      */
3508     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3509 
3510     /**
3511      * Works like focusable for screen readers, but without the side effects on input focus.
3512      * @see #setScreenReaderFocusable(boolean)
3513      */
3514     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3515 
3516     /**
3517      * The last aggregated visibility. Used to detect when it truly changes.
3518      */
3519     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3520 
3521     /**
3522      * Used to indicate that {@link #mAutofillId} was explicitly set through
3523      * {@link #setAutofillId(AutofillId)}.
3524      */
3525     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3526 
3527     /**
3528      * Indicates if the View is a heading for accessibility purposes
3529      */
3530     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3531 
3532     /* End of masks for mPrivateFlags3 */
3533 
3534     /*
3535      * Masks for mPrivateFlags4, as generated by dumpFlags():
3536      *
3537      * |-------|-------|-------|-------|
3538      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3539      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3540      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3541      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3542      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3543      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3544      *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
3545      *                       1          PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
3546      *                     11           PFLAG4_SCROLL_CAPTURE_HINT_MASK
3547      *                    1             PFLAG4_ALLOW_CLICK_WHEN_DISABLED
3548      *                   1              PFLAG4_DETACHED
3549      *                  1               PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
3550      *                 1                PFLAG4_DRAG_A11Y_STARTED
3551      *                1                 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
3552      *             1                    PFLAG4_TRAVERSAL_TRACING_ENABLED
3553      *            1                     PFLAG4_RELAYOUT_TRACING_ENABLED
3554      * |-------|-------|-------|-------|
3555      */
3556 
3557     /**
3558      * Mask for obtaining the bits which specify how to determine
3559      * whether a view is important for autofill.
3560      *
3561      * <p>NOTE: the important for content capture values were the first flags added and are set in
3562      * the rightmost position, so we don't need to shift them
3563      */
3564     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3565             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3566             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3567             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3568             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3569 
3570     /*
3571      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3572      * should be called.
3573      *
3574      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3575      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3576      */
3577     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3578     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3579 
3580     /*
3581      * Flags used to cache the value returned by isImportantForContentCapture while the view
3582      * hierarchy is being traversed.
3583      */
3584     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3585     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3586 
3587     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3588             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3589             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3590 
3591     /**
3592      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3593      */
3594     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3595 
3596     /**
3597      * Flag indicating the field should not have yellow highlight when autofilled.
3598      */
3599     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3600 
3601     /**
3602      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3603      */
3604     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3605 
3606     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3607             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3608             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3609 
3610     /**
3611      * Indicates if the view can receive click events when disabled.
3612      */
3613     private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
3614 
3615     /**
3616      * Indicates if the view is just detached.
3617      */
3618     private static final int PFLAG4_DETACHED = 0x000002000;
3619 
3620     /**
3621      * Indicates that the view has transient state because the system is translating it.
3622      */
3623     private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
3624 
3625     /**
3626      * Indicates that the view has started a drag with {@link AccessibilityAction#ACTION_DRAG_START}
3627      */
3628     private static final int PFLAG4_DRAG_A11Y_STARTED = 0x000008000;
3629 
3630     /**
3631      * Indicates that the view enables auto handwriting initiation.
3632      */
3633     private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
3634 
3635     /**
3636      * When set, measure and layout passes of this view will be logged with {@link Trace}, so we
3637      * can better debug jank due to complex view hierarchies.
3638      */
3639     private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
3640 
3641     /**
3642      * When set, emits a {@link Trace} instant event and stacktrace every time a requestLayout of
3643      * this class happens.
3644      */
3645     private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
3646 
3647     /* End of masks for mPrivateFlags4 */
3648 
3649     /** @hide */
3650     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3651     /** @hide */
3652     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3653     /** @hide */
3654     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3655 
3656     /** @hide */
3657     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3658             VIEW_STRUCTURE_FOR_ASSIST,
3659             VIEW_STRUCTURE_FOR_AUTOFILL,
3660             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3661     })
3662     @Retention(RetentionPolicy.SOURCE)
3663     public @interface ViewStructureType {}
3664 
3665     /**
3666      * Always allow a user to over-scroll this view, provided it is a
3667      * view that can scroll.
3668      *
3669      * @see #getOverScrollMode()
3670      * @see #setOverScrollMode(int)
3671      */
3672     public static final int OVER_SCROLL_ALWAYS = 0;
3673 
3674     /**
3675      * Allow a user to over-scroll this view only if the content is large
3676      * enough to meaningfully scroll, provided it is a view that can scroll.
3677      *
3678      * @see #getOverScrollMode()
3679      * @see #setOverScrollMode(int)
3680      */
3681     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3682 
3683     /**
3684      * Never allow a user to over-scroll this view.
3685      *
3686      * @see #getOverScrollMode()
3687      * @see #setOverScrollMode(int)
3688      */
3689     public static final int OVER_SCROLL_NEVER = 2;
3690 
3691     /**
3692      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3693      * requested the system UI (status bar) to be visible (the default).
3694      *
3695      * @see #setSystemUiVisibility(int)
3696      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
3697      * instead.
3698      */
3699     @Deprecated
3700     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3701 
3702     /**
3703      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3704      * system UI to enter an unobtrusive "low profile" mode.
3705      *
3706      * <p>This is for use in games, book readers, video players, or any other
3707      * "immersive" application where the usual system chrome is deemed too distracting.
3708      *
3709      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3710      *
3711      * @see #setSystemUiVisibility(int)
3712      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
3713      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
3714      * {@link Type#systemBars()}.
3715      */
3716     @Deprecated
3717     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3718 
3719     /**
3720      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3721      * system navigation be temporarily hidden.
3722      *
3723      * <p>This is an even less obtrusive state than that called for by
3724      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3725      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3726      * those to disappear. This is useful (in conjunction with the
3727      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3728      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3729      * window flags) for displaying content using every last pixel on the display.
3730      *
3731      * <p>There is a limitation: because navigation controls are so important, the least user
3732      * interaction will cause them to reappear immediately.  When this happens, both
3733      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3734      * so that both elements reappear at the same time.
3735      *
3736      * @see #setSystemUiVisibility(int)
3737      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
3738      * instead.
3739      */
3740     @Deprecated
3741     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3742 
3743     /**
3744      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3745      * into the normal fullscreen mode so that its content can take over the screen
3746      * while still allowing the user to interact with the application.
3747      *
3748      * <p>This has the same visual effect as
3749      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3750      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3751      * meaning that non-critical screen decorations (such as the status bar) will be
3752      * hidden while the user is in the View's window, focusing the experience on
3753      * that content.  Unlike the window flag, if you are using ActionBar in
3754      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3755      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3756      * hide the action bar.
3757      *
3758      * <p>This approach to going fullscreen is best used over the window flag when
3759      * it is a transient state -- that is, the application does this at certain
3760      * points in its user interaction where it wants to allow the user to focus
3761      * on content, but not as a continuous state.  For situations where the application
3762      * would like to simply stay full screen the entire time (such as a game that
3763      * wants to take over the screen), the
3764      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3765      * is usually a better approach.  The state set here will be removed by the system
3766      * in various situations (such as the user moving to another application) like
3767      * the other system UI states.
3768      *
3769      * <p>When using this flag, the application should provide some easy facility
3770      * for the user to go out of it.  A common example would be in an e-book
3771      * reader, where tapping on the screen brings back whatever screen and UI
3772      * decorations that had been hidden while the user was immersed in reading
3773      * the book.
3774      *
3775      * @see #setSystemUiVisibility(int)
3776      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
3777      * instead.
3778      */
3779     @Deprecated
3780     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3781 
3782     /**
3783      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3784      * flags, we would like a stable view of the content insets given to
3785      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3786      * will always represent the worst case that the application can expect
3787      * as a continuous state.  In the stock Android UI this is the space for
3788      * the system bar, nav bar, and status bar, but not more transient elements
3789      * such as an input method.
3790      *
3791      * The stable layout your UI sees is based on the system UI modes you can
3792      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3793      * then you will get a stable layout for changes of the
3794      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3795      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3796      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3797      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3798      * with a stable layout.  (Note that you should avoid using
3799      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3800      *
3801      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3802      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3803      * then a hidden status bar will be considered a "stable" state for purposes
3804      * here.  This allows your UI to continually hide the status bar, while still
3805      * using the system UI flags to hide the action bar while still retaining
3806      * a stable layout.  Note that changing the window fullscreen flag will never
3807      * provide a stable layout for a clean transition.
3808      *
3809      * <p>If you are using ActionBar in
3810      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3811      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3812      * insets it adds to those given to the application.
3813      *
3814      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
3815      * insets that don't change when system bars change visibility state.
3816      */
3817     @Deprecated
3818     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3819 
3820     /**
3821      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3822      * to be laid out as if it has requested
3823      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3824      * allows it to avoid artifacts when switching in and out of that mode, at
3825      * the expense that some of its user interface may be covered by screen
3826      * decorations when they are shown.  You can perform layout of your inner
3827      * UI elements to account for the navigation system UI through the
3828      * {@link #fitSystemWindows(Rect)} method.
3829      *
3830      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3831      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
3832      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3833      */
3834     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3835 
3836     /**
3837      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3838      * to be laid out as if it has requested
3839      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3840      * allows it to avoid artifacts when switching in and out of that mode, at
3841      * the expense that some of its user interface may be covered by screen
3842      * decorations when they are shown.  You can perform layout of your inner
3843      * UI elements to account for non-fullscreen system UI through the
3844      * {@link #fitSystemWindows(Rect)} method.
3845      *
3846      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3847      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3848      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3849      *  layoutInDisplayCutoutMode} is
3850      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3851      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3852      *
3853      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3854      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3855      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3856      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3857      *
3858      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3859      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
3860      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3861      */
3862     @Deprecated
3863     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3864 
3865     /**
3866      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3867      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3868      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3869      * user interaction.
3870      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3871      * has an effect when used in combination with that flag.</p>
3872      *
3873      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_DEFAULT} instead.
3874      */
3875     @Deprecated
3876     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3877 
3878     /**
3879      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3880      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3881      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3882      * experience while also hiding the system bars.  If this flag is not set,
3883      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3884      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3885      * if the user swipes from the top of the screen.
3886      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3887      * system gestures, such as swiping from the top of the screen.  These transient system bars
3888      * will overlay app's content, may have some degree of transparency, and will automatically
3889      * hide after a short timeout.
3890      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3891      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3892      * with one or both of those flags.</p>
3893      *
3894      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
3895      */
3896     @Deprecated
3897     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3898 
3899     /**
3900      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3901      * is compatible with light status bar backgrounds.
3902      *
3903      * <p>For this to take effect, the window must request
3904      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3905      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3906      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3907      *         FLAG_TRANSLUCENT_STATUS}.
3908      *
3909      * @see android.R.attr#windowLightStatusBar
3910      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
3911      */
3912     @Deprecated
3913     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3914 
3915     /**
3916      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3917      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3918      */
3919     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3920 
3921     /**
3922      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3923      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3924      */
3925     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3926 
3927     /**
3928      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3929      * that is compatible with light navigation bar backgrounds.
3930      *
3931      * <p>For this to take effect, the window must request
3932      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3933      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3934      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3935      *         FLAG_TRANSLUCENT_NAVIGATION}.
3936      *
3937      * @see android.R.attr#windowLightNavigationBar
3938      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
3939      */
3940     @Deprecated
3941     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3942 
3943     /**
3944      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3945      */
3946     @Deprecated
3947     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3948 
3949     /**
3950      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3951      */
3952     @Deprecated
3953     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3954 
3955     /**
3956      * @hide
3957      *
3958      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3959      * out of the public fields to keep the undefined bits out of the developer's way.
3960      *
3961      * Flag to make the status bar not expandable.  Unless you also
3962      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3963      */
3964     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3965     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3966 
3967     /**
3968      * @hide
3969      *
3970      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3971      * out of the public fields to keep the undefined bits out of the developer's way.
3972      *
3973      * Flag to hide notification icons and scrolling ticker text.
3974      */
3975     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3976 
3977     /**
3978      * @hide
3979      *
3980      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3981      * out of the public fields to keep the undefined bits out of the developer's way.
3982      *
3983      * Flag to disable incoming notification alerts.  This will not block
3984      * icons, but it will block sound, vibrating and other visual or aural notifications.
3985      */
3986     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3987 
3988     /**
3989      * @hide
3990      *
3991      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3992      * out of the public fields to keep the undefined bits out of the developer's way.
3993      *
3994      * Flag to hide only the scrolling ticker.  Note that
3995      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3996      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3997      */
3998     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3999 
4000     /**
4001      * @hide
4002      *
4003      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4004      * out of the public fields to keep the undefined bits out of the developer's way.
4005      *
4006      * Flag to hide the center system info area.
4007      */
4008     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
4009 
4010     /**
4011      * @hide
4012      *
4013      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4014      * out of the public fields to keep the undefined bits out of the developer's way.
4015      *
4016      * Flag to hide only the home button.  Don't use this
4017      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4018      */
4019     @UnsupportedAppUsage
4020     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
4021 
4022     /**
4023      * @hide
4024      *
4025      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4026      * out of the public fields to keep the undefined bits out of the developer's way.
4027      *
4028      * Flag to hide only the back button. Don't use this
4029      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4030      */
4031     @UnsupportedAppUsage
4032     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
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 hide only the clock.  You might use this if your activity has
4041      * its own clock making the status bar's clock redundant.
4042      */
4043     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
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 recent apps button. Don't use this
4052      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4053      */
4054     @UnsupportedAppUsage
4055     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
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 disable the global search gesture. Don't use this
4064      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4065      */
4066     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
4067 
4068     /**
4069      * @hide
4070      *
4071      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4072      * out of the public fields to keep the undefined bits out of the developer's way.
4073      *
4074      * Flag to disable the ongoing call chip.
4075      */
4076     public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
4077 
4078     /**
4079      * @hide
4080      */
4081     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4082 
4083     /**
4084      * These are the system UI flags that can be cleared by events outside
4085      * of an application.  Currently this is just the ability to tap on the
4086      * screen while hiding the navigation bar to have it return.
4087      * @hide
4088      */
4089     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4090             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4091             | SYSTEM_UI_FLAG_FULLSCREEN;
4092 
4093     /**
4094      * Flags that can impact the layout in relation to system UI.
4095      *
4096      * @deprecated System UI layout flags are deprecated.
4097      */
4098     @Deprecated
4099     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4100             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4101             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4102 
4103     /** @hide */
4104     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4105             FIND_VIEWS_WITH_TEXT,
4106             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4107     })
4108     @Retention(RetentionPolicy.SOURCE)
4109     public @interface FindViewFlags {}
4110 
4111     /**
4112      * Find views that render the specified text.
4113      *
4114      * @see #findViewsWithText(ArrayList, CharSequence, int)
4115      */
4116     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4117 
4118     /**
4119      * Find find views that contain the specified content description.
4120      *
4121      * @see #findViewsWithText(ArrayList, CharSequence, int)
4122      */
4123     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4124 
4125     /**
4126      * Find views that contain {@link AccessibilityNodeProvider}. Such
4127      * a View is a root of virtual view hierarchy and may contain the searched
4128      * text. If this flag is set Views with providers are automatically
4129      * added and it is a responsibility of the client to call the APIs of
4130      * the provider to determine whether the virtual tree rooted at this View
4131      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4132      * representing the virtual views with this text.
4133      *
4134      * @see #findViewsWithText(ArrayList, CharSequence, int)
4135      *
4136      * @hide
4137      */
4138     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4139 
4140     /**
4141      * The undefined cursor position.
4142      *
4143      * @hide
4144      */
4145     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4146 
4147     /**
4148      * Indicates that the screen has changed state and is now off.
4149      *
4150      * @see #onScreenStateChanged(int)
4151      */
4152     public static final int SCREEN_STATE_OFF = 0x0;
4153 
4154     /**
4155      * Indicates that the screen has changed state and is now on.
4156      *
4157      * @see #onScreenStateChanged(int)
4158      */
4159     public static final int SCREEN_STATE_ON = 0x1;
4160 
4161     /**
4162      * Indicates no axis of view scrolling.
4163      */
4164     public static final int SCROLL_AXIS_NONE = 0;
4165 
4166     /**
4167      * Indicates scrolling along the horizontal axis.
4168      */
4169     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4170 
4171     /**
4172      * Indicates scrolling along the vertical axis.
4173      */
4174     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4175 
4176     /**
4177      * Controls the over-scroll mode for this view.
4178      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4179      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4180      * and {@link #OVER_SCROLL_NEVER}.
4181      */
4182     private int mOverScrollMode;
4183 
4184     /**
4185      * The parent this view is attached to.
4186      * {@hide}
4187      *
4188      * @see #getParent()
4189      */
4190     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4191     protected ViewParent mParent;
4192 
4193     /**
4194      * {@hide}
4195      *
4196      * Not available for general use. If you need help, hang up and then dial one of the following
4197      * public APIs:
4198      *
4199      * @see #isAttachedToWindow() for current attach state
4200      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4201      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4202      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4203      * @see #getHandler() for posting messages to this view's UI thread/looper
4204      * @see #getParent() for interacting with the parent chain
4205      * @see #getWindowToken() for the current window token
4206      * @see #getRootView() for the view at the root of the attached hierarchy
4207      * @see #getDisplay() for the Display this view is presented on
4208      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4209      * @see #hasWindowFocus() for whether the attached window is currently focused
4210      * @see #getWindowVisibility() for checking the visibility of the attached window
4211      */
4212     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4213     AttachInfo mAttachInfo;
4214 
4215     /**
4216      * {@hide}
4217      */
4218     @ViewDebug.ExportedProperty(flagMapping = {
4219         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4220                 name = "FORCE_LAYOUT"),
4221         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4222                 name = "LAYOUT_REQUIRED"),
4223         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4224             name = "DRAWING_CACHE_INVALID", outputIf = false),
4225         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4226         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4227         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4228     }, formatToHexString = true)
4229 
4230     /* @hide */
4231     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4232     public int mPrivateFlags;
4233     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4234     int mPrivateFlags2;
4235     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4236     int mPrivateFlags3;
4237 
4238     private int mPrivateFlags4;
4239 
4240     /**
4241      * This view's request for the visibility of the status bar.
4242      * @hide
4243      */
4244     @ViewDebug.ExportedProperty(flagMapping = {
4245             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4246                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4247                     name = "LOW_PROFILE"),
4248             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4249                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4250                     name = "HIDE_NAVIGATION"),
4251             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4252                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4253                     name = "FULLSCREEN"),
4254             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4255                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4256                     name = "LAYOUT_STABLE"),
4257             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4258                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4259                     name = "LAYOUT_HIDE_NAVIGATION"),
4260             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4261                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4262                     name = "LAYOUT_FULLSCREEN"),
4263             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4264                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4265                     name = "IMMERSIVE"),
4266             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4267                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4268                     name = "IMMERSIVE_STICKY"),
4269             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4270                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4271                     name = "LIGHT_STATUS_BAR"),
4272             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4273                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4274                     name = "LIGHT_NAVIGATION_BAR"),
4275             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4276                     equals = STATUS_BAR_DISABLE_EXPAND,
4277                     name = "STATUS_BAR_DISABLE_EXPAND"),
4278             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4279                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4280                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4281             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4282                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4283                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4284             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4285                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4286                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4287             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4288                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4289                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4290             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4291                     equals = STATUS_BAR_DISABLE_HOME,
4292                     name = "STATUS_BAR_DISABLE_HOME"),
4293             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4294                     equals = STATUS_BAR_DISABLE_BACK,
4295                     name = "STATUS_BAR_DISABLE_BACK"),
4296             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4297                     equals = STATUS_BAR_DISABLE_CLOCK,
4298                     name = "STATUS_BAR_DISABLE_CLOCK"),
4299             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4300                     equals = STATUS_BAR_DISABLE_RECENT,
4301                     name = "STATUS_BAR_DISABLE_RECENT"),
4302             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4303                     equals = STATUS_BAR_DISABLE_SEARCH,
4304                     name = "STATUS_BAR_DISABLE_SEARCH"),
4305             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4306                     equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4307                     name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
4308     }, formatToHexString = true)
4309     @SystemUiVisibility
4310     int mSystemUiVisibility;
4311 
4312     /**
4313      * @hide
4314      */
4315     @IntDef(flag = true, prefix = "", value = {
4316             SYSTEM_UI_FLAG_LOW_PROFILE,
4317             SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4318             SYSTEM_UI_FLAG_FULLSCREEN,
4319             SYSTEM_UI_FLAG_LAYOUT_STABLE,
4320             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4321             SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4322             SYSTEM_UI_FLAG_IMMERSIVE,
4323             SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4324             SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4325             SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4326             STATUS_BAR_DISABLE_EXPAND,
4327             STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4328             STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4329             STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4330             STATUS_BAR_DISABLE_SYSTEM_INFO,
4331             STATUS_BAR_DISABLE_HOME,
4332             STATUS_BAR_DISABLE_BACK,
4333             STATUS_BAR_DISABLE_CLOCK,
4334             STATUS_BAR_DISABLE_RECENT,
4335             STATUS_BAR_DISABLE_SEARCH,
4336             STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4337     })
4338     @Retention(RetentionPolicy.SOURCE)
4339     public @interface SystemUiVisibility {}
4340 
4341     /**
4342      * Reference count for transient state.
4343      * @see #setHasTransientState(boolean)
4344      */
4345     int mTransientStateCount = 0;
4346 
4347     /**
4348      * Count of how many windows this view has been attached to.
4349      */
4350     int mWindowAttachCount;
4351 
4352     /**
4353      * The layout parameters associated with this view and used by the parent
4354      * {@link android.view.ViewGroup} to determine how this view should be
4355      * laid out.
4356      *
4357      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4358      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4359      * state correctness of the class.
4360      * {@hide}
4361      */
4362     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4363     protected ViewGroup.LayoutParams mLayoutParams;
4364 
4365     /**
4366      * The view flags hold various views states.
4367      *
4368      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4369      * triggering updates.
4370      * {@hide}
4371      */
4372     @ViewDebug.ExportedProperty(formatToHexString = true)
4373     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4374     int mViewFlags;
4375 
4376     static class TransformationInfo {
4377         /**
4378          * The transform matrix for the View. This transform is calculated internally
4379          * based on the translation, rotation, and scale properties.
4380          *
4381          * Do *not* use this variable directly; instead call getMatrix(), which will
4382          * load the value from the View's RenderNode.
4383          */
4384         private final Matrix mMatrix = new Matrix();
4385 
4386         /**
4387          * The inverse transform matrix for the View. This transform is calculated
4388          * internally based on the translation, rotation, and scale properties.
4389          *
4390          * Do *not* use this variable directly; instead call getInverseMatrix(),
4391          * which will load the value from the View's RenderNode.
4392          */
4393         private Matrix mInverseMatrix;
4394 
4395         /**
4396          * The opacity of the View. This is a value from 0 to 1, where 0 means
4397          * completely transparent and 1 means completely opaque.
4398          */
4399         @ViewDebug.ExportedProperty
4400         private float mAlpha = 1f;
4401 
4402         /**
4403          * The opacity of the view as manipulated by the Fade transition. This is a
4404          * property only used by transitions, which is composited with the other alpha
4405          * values to calculate the final visual alpha value.
4406          */
4407         float mTransitionAlpha = 1f;
4408     }
4409 
4410     /** @hide */
4411     @UnsupportedAppUsage
4412     public TransformationInfo mTransformationInfo;
4413 
4414     /**
4415      * Current clip bounds. to which all drawing of this view are constrained.
4416      */
4417     @ViewDebug.ExportedProperty(category = "drawing")
4418     Rect mClipBounds = null;
4419 
4420     private boolean mLastIsOpaque;
4421 
4422     /**
4423      * The distance in pixels from the left edge of this view's parent
4424      * to the left edge of this view.
4425      * {@hide}
4426      */
4427     @ViewDebug.ExportedProperty(category = "layout")
4428     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4429     protected int mLeft;
4430     /**
4431      * The distance in pixels from the left edge of this view's parent
4432      * to the right edge of this view.
4433      * {@hide}
4434      */
4435     @ViewDebug.ExportedProperty(category = "layout")
4436     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4437     protected int mRight;
4438     /**
4439      * The distance in pixels from the top edge of this view's parent
4440      * to the top edge of this view.
4441      * {@hide}
4442      */
4443     @ViewDebug.ExportedProperty(category = "layout")
4444     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4445     protected int mTop;
4446     /**
4447      * The distance in pixels from the top edge of this view's parent
4448      * to the bottom edge of this view.
4449      * {@hide}
4450      */
4451     @ViewDebug.ExportedProperty(category = "layout")
4452     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4453     protected int mBottom;
4454 
4455     /**
4456      * The offset, in pixels, by which the content of this view is scrolled
4457      * horizontally.
4458      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4459      * accessing these directly.
4460      * {@hide}
4461      */
4462     @ViewDebug.ExportedProperty(category = "scrolling")
4463     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4464     protected int mScrollX;
4465     /**
4466      * The offset, in pixels, by which the content of this view is scrolled
4467      * vertically.
4468      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4469      * accessing these directly.
4470      * {@hide}
4471      */
4472     @ViewDebug.ExportedProperty(category = "scrolling")
4473     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4474     protected int mScrollY;
4475 
4476     /**
4477      * The final computed left padding in pixels that is used for drawing. This is the distance in
4478      * pixels between the left edge of this view and the left edge of its content.
4479      * {@hide}
4480      */
4481     @ViewDebug.ExportedProperty(category = "padding")
4482     @UnsupportedAppUsage
4483     protected int mPaddingLeft = 0;
4484     /**
4485      * The final computed right padding in pixels that is used for drawing. This is the distance in
4486      * pixels between the right edge of this view and the right edge of its content.
4487      * {@hide}
4488      */
4489     @ViewDebug.ExportedProperty(category = "padding")
4490     @UnsupportedAppUsage
4491     protected int mPaddingRight = 0;
4492     /**
4493      * The final computed top padding in pixels that is used for drawing. This is the distance in
4494      * pixels between the top edge of this view and the top edge of its content.
4495      * {@hide}
4496      */
4497     @ViewDebug.ExportedProperty(category = "padding")
4498     @UnsupportedAppUsage
4499     protected int mPaddingTop;
4500     /**
4501      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4502      * pixels between the bottom edge of this view and the bottom edge of its content.
4503      * {@hide}
4504      */
4505     @ViewDebug.ExportedProperty(category = "padding")
4506     @UnsupportedAppUsage
4507     protected int mPaddingBottom;
4508 
4509     /**
4510      * The layout insets in pixels, that is the distance in pixels between the
4511      * visible edges of this view its bounds.
4512      */
4513     private Insets mLayoutInsets;
4514 
4515     /**
4516      * Briefly describes the state of the view and is primarily used for accessibility support.
4517      */
4518     private CharSequence mStateDescription;
4519 
4520     /**
4521      * Briefly describes the view and is primarily used for accessibility support.
4522      */
4523     private CharSequence mContentDescription;
4524 
4525     /**
4526      * If this view represents a distinct part of the window, it can have a title that labels the
4527      * area.
4528      */
4529     private CharSequence mAccessibilityPaneTitle;
4530 
4531     /**
4532      * Specifies the id of a view for which this view serves as a label for
4533      * accessibility purposes.
4534      */
4535     private int mLabelForId = View.NO_ID;
4536 
4537     /**
4538      * Predicate for matching labeled view id with its label for
4539      * accessibility purposes.
4540      */
4541     private MatchLabelForPredicate mMatchLabelForPredicate;
4542 
4543     /**
4544      * Specifies a view before which this one is visited in accessibility traversal.
4545      */
4546     private int mAccessibilityTraversalBeforeId = NO_ID;
4547 
4548     /**
4549      * Specifies a view after which this one is visited in accessibility traversal.
4550      */
4551     private int mAccessibilityTraversalAfterId = NO_ID;
4552 
4553     /**
4554      * Predicate for matching a view by its id.
4555      */
4556     private MatchIdPredicate mMatchIdPredicate;
4557 
4558     /**
4559      * The right padding after RTL resolution, but before taking account of scroll bars.
4560      *
4561      * @hide
4562      */
4563     @ViewDebug.ExportedProperty(category = "padding")
4564     protected int mUserPaddingRight;
4565 
4566     /**
4567      * The resolved bottom padding before taking account of scroll bars.
4568      *
4569      * @hide
4570      */
4571     @ViewDebug.ExportedProperty(category = "padding")
4572     protected int mUserPaddingBottom;
4573 
4574     /**
4575      * The left padding after RTL resolution, but before taking account of scroll bars.
4576      *
4577      * @hide
4578      */
4579     @ViewDebug.ExportedProperty(category = "padding")
4580     protected int mUserPaddingLeft;
4581 
4582     /**
4583      * Cache the paddingStart set by the user to append to the scrollbar's size.
4584      *
4585      */
4586     @ViewDebug.ExportedProperty(category = "padding")
4587     int mUserPaddingStart;
4588 
4589     /**
4590      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4591      *
4592      */
4593     @ViewDebug.ExportedProperty(category = "padding")
4594     int mUserPaddingEnd;
4595 
4596     /**
4597      * The left padding as set by a setter method, a background's padding, or via XML property
4598      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4599      *
4600      * @hide
4601      */
4602     int mUserPaddingLeftInitial;
4603 
4604     /**
4605      * The right padding as set by a setter method, a background's padding, or via XML property
4606      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4607      *
4608      * @hide
4609      */
4610     int mUserPaddingRightInitial;
4611 
4612     /**
4613      * Default undefined padding
4614      */
4615     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4616 
4617     /**
4618      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4619      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4620      */
4621     private boolean mLeftPaddingDefined = false;
4622 
4623     /**
4624      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4625      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4626      */
4627     private boolean mRightPaddingDefined = false;
4628 
4629     /**
4630      * @hide
4631      */
4632     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4633     /**
4634      * @hide
4635      */
4636     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4637 
4638     private LongSparseLongArray mMeasureCache;
4639 
4640     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4641     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4642     private Drawable mBackground;
4643     private TintInfo mBackgroundTint;
4644 
4645     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4646     private ForegroundInfo mForegroundInfo;
4647 
4648     private Drawable mScrollIndicatorDrawable;
4649 
4650     /**
4651      * RenderNode used for backgrounds.
4652      * <p>
4653      * When non-null and valid, this is expected to contain an up-to-date copy
4654      * of the background drawable. It is cleared on temporary detach, and reset
4655      * on cleanup.
4656      * @hide
4657      */
4658     RenderNode mBackgroundRenderNode;
4659 
4660     @UnsupportedAppUsage
4661     private int mBackgroundResource;
4662     private boolean mBackgroundSizeChanged;
4663 
4664     /** The default focus highlight.
4665      * @see #mDefaultFocusHighlightEnabled
4666      * @see Drawable#hasFocusStateSpecified()
4667      */
4668     private Drawable mDefaultFocusHighlight;
4669     private Drawable mDefaultFocusHighlightCache;
4670     private boolean mDefaultFocusHighlightSizeChanged;
4671     /**
4672      * True if the default focus highlight is needed on the target device.
4673      */
4674     private static boolean sUseDefaultFocusHighlight;
4675 
4676     /**
4677      * True if zero-sized views can be focused.
4678      */
4679     private static boolean sCanFocusZeroSized;
4680 
4681     /**
4682      * Always assign focus if a focusable View is available.
4683      */
4684     private static boolean sAlwaysAssignFocus;
4685 
4686     private String mTransitionName;
4687 
4688     static class TintInfo {
4689         ColorStateList mTintList;
4690         BlendMode mBlendMode;
4691         boolean mHasTintMode;
4692         boolean mHasTintList;
4693     }
4694 
4695     private static class ForegroundInfo {
4696         private Drawable mDrawable;
4697         private TintInfo mTintInfo;
4698         private int mGravity = Gravity.FILL;
4699         private boolean mInsidePadding = true;
4700         private boolean mBoundsChanged = true;
4701         private final Rect mSelfBounds = new Rect();
4702         private final Rect mOverlayBounds = new Rect();
4703     }
4704 
4705     static class ListenerInfo {
4706 
4707         @UnsupportedAppUsage
ListenerInfo()4708         ListenerInfo() {
4709         }
4710 
4711         /**
4712          * Listener used to dispatch focus change events.
4713          * This field should be made private, so it is hidden from the SDK.
4714          * {@hide}
4715          */
4716         @UnsupportedAppUsage
4717         protected OnFocusChangeListener mOnFocusChangeListener;
4718 
4719         /**
4720          * Listeners for layout change events.
4721          */
4722         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4723 
4724         protected OnScrollChangeListener mOnScrollChangeListener;
4725 
4726         /**
4727          * Listeners for attach events.
4728          */
4729         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4730 
4731         /**
4732          * Listener used to dispatch click events.
4733          * This field should be made private, so it is hidden from the SDK.
4734          * {@hide}
4735          */
4736         @UnsupportedAppUsage
4737         public OnClickListener mOnClickListener;
4738 
4739         /**
4740          * Listener used to dispatch long click events.
4741          * This field should be made private, so it is hidden from the SDK.
4742          * {@hide}
4743          */
4744         @UnsupportedAppUsage
4745         protected OnLongClickListener mOnLongClickListener;
4746 
4747         /**
4748          * Listener used to dispatch context click events. This field should be made private, so it
4749          * is hidden from the SDK.
4750          * {@hide}
4751          */
4752         protected OnContextClickListener mOnContextClickListener;
4753 
4754         /**
4755          * Listener used to build the context menu.
4756          * This field should be made private, so it is hidden from the SDK.
4757          * {@hide}
4758          */
4759         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4760         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4761 
4762         @UnsupportedAppUsage
4763         private OnKeyListener mOnKeyListener;
4764 
4765         @UnsupportedAppUsage
4766         private OnTouchListener mOnTouchListener;
4767 
4768         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4769         private OnHoverListener mOnHoverListener;
4770 
4771         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4772         private OnGenericMotionListener mOnGenericMotionListener;
4773 
4774         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4775         private OnDragListener mOnDragListener;
4776 
4777         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4778 
4779         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4780 
4781         OnCapturedPointerListener mOnCapturedPointerListener;
4782 
4783         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4784 
4785         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
4786 
4787         /**
4788          * This lives here since it's only valid for interactive views. This list is null
4789          * until its first use.
4790          */
4791         private List<Rect> mSystemGestureExclusionRects = null;
4792         private List<Rect> mKeepClearRects = null;
4793         private List<Rect> mUnrestrictedKeepClearRects = null;
4794         private boolean mPreferKeepClear = false;
4795         private Rect mHandwritingArea = null;
4796 
4797         /**
4798          * Used to track {@link #mSystemGestureExclusionRects}, {@link #mKeepClearRects} and
4799          * {@link #mHandwritingArea}.
4800          */
4801         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4802         private Runnable mPositionChangedUpdate;
4803 
4804         /**
4805          * Allows the application to implement custom scroll capture support.
4806          */
4807         ScrollCaptureCallback mScrollCaptureCallback;
4808 
4809         @Nullable
4810         private OnReceiveContentListener mOnReceiveContentListener;
4811     }
4812 
4813     @UnsupportedAppUsage
4814     ListenerInfo mListenerInfo;
4815 
4816     private static class TooltipInfo {
4817         /**
4818          * Text to be displayed in a tooltip popup.
4819          */
4820         @Nullable
4821         CharSequence mTooltipText;
4822 
4823         /**
4824          * View-relative position of the tooltip anchor point.
4825          */
4826         int mAnchorX;
4827         int mAnchorY;
4828 
4829         /**
4830          * The tooltip popup.
4831          */
4832         @Nullable
4833         TooltipPopup mTooltipPopup;
4834 
4835         /**
4836          * Set to true if the tooltip was shown as a result of a long click.
4837          */
4838         boolean mTooltipFromLongClick;
4839 
4840         /**
4841          * Keep these Runnables so that they can be used to reschedule.
4842          */
4843         Runnable mShowTooltipRunnable;
4844         Runnable mHideTooltipRunnable;
4845 
4846         /**
4847          * Hover move is ignored if it is within this distance in pixels from the previous one.
4848          */
4849         int mHoverSlop;
4850 
4851         /**
4852          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4853          * different from the previously stored position. Ignoring insignificant changes
4854          * filters out the jitter which is typical for such input sources as stylus.
4855          *
4856          * @return True if the position has been updated.
4857          */
updateAnchorPos(MotionEvent event)4858         private boolean updateAnchorPos(MotionEvent event) {
4859             final int newAnchorX = (int) event.getX();
4860             final int newAnchorY = (int) event.getY();
4861             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4862                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4863                 return false;
4864             }
4865             mAnchorX = newAnchorX;
4866             mAnchorY = newAnchorY;
4867             return true;
4868         }
4869 
4870         /**
4871          *  Clear the anchor position to ensure that the next change is considered significant.
4872          */
clearAnchorPos()4873         private void clearAnchorPos() {
4874             mAnchorX = Integer.MAX_VALUE;
4875             mAnchorY = Integer.MAX_VALUE;
4876         }
4877     }
4878 
4879     TooltipInfo mTooltipInfo;
4880 
4881     // Temporary values used to hold (x,y) coordinates when delegating from the
4882     // two-arg performLongClick() method to the legacy no-arg version.
4883     private float mLongClickX = Float.NaN;
4884     private float mLongClickY = Float.NaN;
4885 
4886     /**
4887      * The application environment this view lives in.
4888      * This field should be made private, so it is hidden from the SDK.
4889      * {@hide}
4890      */
4891     @ViewDebug.ExportedProperty(deepExport = true)
4892     @UnsupportedAppUsage
4893     @UiContext
4894     protected Context mContext;
4895 
4896     @UnsupportedAppUsage
4897     private final Resources mResources;
4898 
4899     @UnsupportedAppUsage
4900     private ScrollabilityCache mScrollCache;
4901 
4902     private int[] mDrawableState = null;
4903 
4904     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4905 
4906     /**
4907      * Animator that automatically runs based on state changes.
4908      */
4909     private StateListAnimator mStateListAnimator;
4910 
4911     /**
4912      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4913      * the user may specify which view to go to next.
4914      */
4915     private int mNextFocusLeftId = View.NO_ID;
4916 
4917     /**
4918      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4919      * the user may specify which view to go to next.
4920      */
4921     private int mNextFocusRightId = View.NO_ID;
4922 
4923     /**
4924      * When this view has focus and the next focus is {@link #FOCUS_UP},
4925      * the user may specify which view to go to next.
4926      */
4927     private int mNextFocusUpId = View.NO_ID;
4928 
4929     /**
4930      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4931      * the user may specify which view to go to next.
4932      */
4933     private int mNextFocusDownId = View.NO_ID;
4934 
4935     /**
4936      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4937      * the user may specify which view to go to next.
4938      */
4939     int mNextFocusForwardId = View.NO_ID;
4940 
4941     /**
4942      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4943      *
4944      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4945      */
4946     int mNextClusterForwardId = View.NO_ID;
4947 
4948     /**
4949      * Whether this View should use a default focus highlight when it gets focused but doesn't
4950      * have {@link android.R.attr#state_focused} defined in its background.
4951      */
4952     boolean mDefaultFocusHighlightEnabled = true;
4953 
4954     private CheckForLongPress mPendingCheckForLongPress;
4955     @UnsupportedAppUsage
4956     private CheckForTap mPendingCheckForTap = null;
4957     private PerformClick mPerformClick;
4958     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4959     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
4960     private UnsetPressedState mUnsetPressedState;
4961 
4962     /**
4963      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4964      * up event while a long press is invoked as soon as the long press duration is reached, so
4965      * a long press could be performed before the tap is checked, in which case the tap's action
4966      * should not be invoked.
4967      */
4968     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4969     private boolean mHasPerformedLongPress;
4970 
4971     /**
4972      * Whether a context click button is currently pressed down. This is true when the stylus is
4973      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4974      * pressed. This is false once the button is released or if the stylus has been lifted.
4975      */
4976     private boolean mInContextButtonPress;
4977 
4978     /**
4979      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4980      * true after a stylus button press has occured, when the next up event should not be recognized
4981      * as a tap.
4982      */
4983     private boolean mIgnoreNextUpEvent;
4984 
4985     /**
4986      * The minimum height of the view. We'll try our best to have the height
4987      * of this view to at least this amount.
4988      */
4989     @ViewDebug.ExportedProperty(category = "measurement")
4990     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4991     private int mMinHeight;
4992 
4993     /**
4994      * The minimum width of the view. We'll try our best to have the width
4995      * of this view to at least this amount.
4996      */
4997     @ViewDebug.ExportedProperty(category = "measurement")
4998     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4999     private int mMinWidth;
5000 
5001     /**
5002      * The delegate to handle touch events that are physically in this view
5003      * but should be handled by another view.
5004      */
5005     private TouchDelegate mTouchDelegate = null;
5006 
5007     /**
5008      * While touch exploration is in use, set to true when hovering across boundaries and
5009      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
5010      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
5011      * {@link MotionEvent#ACTION_HOVER_EXIT}.
5012      * Note that children of view group are excluded in the touch area.
5013      * @see #dispatchTouchExplorationHoverEvent
5014      */
5015     private boolean mHoveringTouchDelegate = false;
5016 
5017     /**
5018      * Solid color to use as a background when creating the drawing cache. Enables
5019      * the cache to use 16 bit bitmaps instead of 32 bit.
5020      */
5021     private int mDrawingCacheBackgroundColor = 0;
5022 
5023     /**
5024      * Special tree observer used when mAttachInfo is null.
5025      */
5026     private ViewTreeObserver mFloatingTreeObserver;
5027 
5028     /**
5029      * Cache the touch slop from the context that created the view.
5030      */
5031     private int mTouchSlop;
5032 
5033     /**
5034      * Cache the ambiguous gesture multiplier from the context that created the view.
5035      */
5036     private float mAmbiguousGestureMultiplier;
5037 
5038     /**
5039      * Object that handles automatic animation of view properties.
5040      */
5041     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5042     private ViewPropertyAnimator mAnimator = null;
5043 
5044     /**
5045      * List of registered FrameMetricsObservers.
5046      */
5047     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
5048 
5049     /**
5050      * Flag indicating that a drag can cross window boundaries.  When
5051      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5052      * with this flag set, all visible applications with targetSdkVersion >=
5053      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
5054      * in the drag operation and receive the dragged content.
5055      *
5056      * <p>If this is the only flag set, then the drag recipient will only have access to text data
5057      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
5058      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
5059      */
5060     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
5061 
5062     /**
5063      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5064      * request read access to the content URI(s) contained in the {@link ClipData} object.
5065      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5066      */
5067     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5068 
5069     /**
5070      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5071      * request write access to the content URI(s) contained in the {@link ClipData} object.
5072      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5073      */
5074     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5075 
5076     /**
5077      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5078      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5079      * reboots until explicitly revoked with
5080      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5081      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5082      */
5083     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5084             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5085 
5086     /**
5087      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5088      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5089      * match against the original granted URI.
5090      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5091      */
5092     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5093             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5094 
5095     /**
5096      * Flag indicating that the drag shadow will be opaque.  When
5097      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5098      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5099      */
5100     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5101 
5102     /**
5103      * Flag indicating that the drag was initiated with
5104      * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START}. When
5105      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called, this
5106      * is used by the system to perform a drag without animations.
5107      */
5108     public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
5109 
5110     /**
5111      * Flag indicating that the caller desires to take ownership of the drag surface for handling
5112      * the animation associated with an unhandled drag.  It is mainly useful if the view starting
5113      * a global drag changes visibility during the gesture and the default animation of animating
5114      * the surface back to the origin is not sufficient.
5115      *
5116      * The calling app must hold the {@link android.Manifest.permission#START_TASKS_FROM_RECENTS}
5117      * permission and will receive the drag surface as a part of
5118      * {@link action.view.DragEvent#ACTION_DRAG_ENDED} only if the drag event's
5119      * {@link action.view.DragEvent#getDragResult()} is {@code false}.  The caller is responsible
5120      * for removing the surface after its animation.
5121      *
5122      * This flag has no effect if the system decides that a cancel-drag animation does not need to
5123      * occur.
5124      * @hide
5125      */
5126     public static final int DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION = 1 << 11;
5127 
5128     /**
5129      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5130      */
5131     private float mVerticalScrollFactor;
5132 
5133     /**
5134      * Position of the vertical scroll bar.
5135      */
5136     @UnsupportedAppUsage
5137     private int mVerticalScrollbarPosition;
5138 
5139     /**
5140      * Position the scroll bar at the default position as determined by the system.
5141      */
5142     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5143 
5144     /**
5145      * Position the scroll bar along the left edge.
5146      */
5147     public static final int SCROLLBAR_POSITION_LEFT = 1;
5148 
5149     /**
5150      * Position the scroll bar along the right edge.
5151      */
5152     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5153 
5154     /**
5155      * Indicates that the view does not have a layer.
5156      *
5157      * @see #getLayerType()
5158      * @see #setLayerType(int, android.graphics.Paint)
5159      * @see #LAYER_TYPE_SOFTWARE
5160      * @see #LAYER_TYPE_HARDWARE
5161      */
5162     public static final int LAYER_TYPE_NONE = 0;
5163 
5164     /**
5165      * <p>Indicates that the view has a software layer. A software layer is backed
5166      * by a bitmap and causes the view to be rendered using Android's software
5167      * rendering pipeline, even if hardware acceleration is enabled.</p>
5168      *
5169      * <p>Software layers have various usages:</p>
5170      * <p>When the application is not using hardware acceleration, a software layer
5171      * is useful to apply a specific color filter and/or blending mode and/or
5172      * translucency to a view and all its children.</p>
5173      * <p>When the application is using hardware acceleration, a software layer
5174      * is useful to render drawing primitives not supported by the hardware
5175      * accelerated pipeline. It can also be used to cache a complex view tree
5176      * into a texture and reduce the complexity of drawing operations. For instance,
5177      * when animating a complex view tree with a translation, a software layer can
5178      * be used to render the view tree only once.</p>
5179      * <p>Software layers should be avoided when the affected view tree updates
5180      * often. Every update will require to re-render the software layer, which can
5181      * potentially be slow (particularly when hardware acceleration is turned on
5182      * since the layer will have to be uploaded into a hardware texture after every
5183      * update.)</p>
5184      *
5185      * @see #getLayerType()
5186      * @see #setLayerType(int, android.graphics.Paint)
5187      * @see #LAYER_TYPE_NONE
5188      * @see #LAYER_TYPE_HARDWARE
5189      */
5190     public static final int LAYER_TYPE_SOFTWARE = 1;
5191 
5192     /**
5193      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5194      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5195      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5196      * rendering pipeline, but only if hardware acceleration is turned on for the
5197      * view hierarchy. When hardware acceleration is turned off, hardware layers
5198      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5199      *
5200      * <p>A hardware layer is useful to apply a specific color filter and/or
5201      * blending mode and/or translucency to a view and all its children.</p>
5202      * <p>A hardware layer can be used to cache a complex view tree into a
5203      * texture and reduce the complexity of drawing operations. For instance,
5204      * when animating a complex view tree with a translation, a hardware layer can
5205      * be used to render the view tree only once.</p>
5206      * <p>A hardware layer can also be used to increase the rendering quality when
5207      * rotation transformations are applied on a view. It can also be used to
5208      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5209      *
5210      * @see #getLayerType()
5211      * @see #setLayerType(int, android.graphics.Paint)
5212      * @see #LAYER_TYPE_NONE
5213      * @see #LAYER_TYPE_SOFTWARE
5214      */
5215     public static final int LAYER_TYPE_HARDWARE = 2;
5216 
5217     /** @hide */
5218     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5219             LAYER_TYPE_NONE,
5220             LAYER_TYPE_SOFTWARE,
5221             LAYER_TYPE_HARDWARE
5222     })
5223     @Retention(RetentionPolicy.SOURCE)
5224     public @interface LayerType {}
5225 
5226     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
5227             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
5228             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
5229             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
5230     })
5231     int mLayerType = LAYER_TYPE_NONE;
5232     Paint mLayerPaint;
5233 
5234     /**
5235      * Set to true when drawing cache is enabled and cannot be created.
5236      *
5237      * @hide
5238      */
5239     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5240     public boolean mCachingFailed;
5241     @UnsupportedAppUsage
5242     private Bitmap mDrawingCache;
5243     @UnsupportedAppUsage
5244     private Bitmap mUnscaledDrawingCache;
5245 
5246     /**
5247      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5248      * <p>
5249      * When non-null and valid, this is expected to contain an up-to-date copy
5250      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5251      * cleanup.
5252      */
5253     @UnsupportedAppUsage
5254     final RenderNode mRenderNode;
5255 
5256     /**
5257      * Set to true when the view is sending hover accessibility events because it
5258      * is the innermost hovered view.
5259      */
5260     private boolean mSendingHoverAccessibilityEvents;
5261 
5262     /**
5263      * Delegate for injecting accessibility functionality.
5264      */
5265     @UnsupportedAppUsage
5266     AccessibilityDelegate mAccessibilityDelegate;
5267 
5268     /**
5269      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5270      * and add/remove objects to/from the overlay directly through the Overlay methods.
5271      */
5272     ViewOverlay mOverlay;
5273 
5274     /**
5275      * The currently active parent view for receiving delegated nested scrolling events.
5276      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5277      * by {@link #stopNestedScroll()} at the same point where we clear
5278      * requestDisallowInterceptTouchEvent.
5279      */
5280     private ViewParent mNestedScrollingParent;
5281 
5282     /**
5283      * Consistency verifier for debugging purposes.
5284      * @hide
5285      */
5286     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5287             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5288                     new InputEventConsistencyVerifier(this, 0) : null;
5289 
5290     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5291 
5292     private int[] mTempNestedScrollConsumed;
5293 
5294     /**
5295      * An overlay is going to draw this View instead of being drawn as part of this
5296      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5297      * when this view is invalidated.
5298      */
5299     GhostView mGhostView;
5300 
5301     /**
5302      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5303      * @hide
5304      */
5305     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5306     public String[] mAttributes;
5307 
5308     /**
5309      * Maps a Resource id to its name.
5310      */
5311     private static SparseArray<String> mAttributeMap;
5312 
5313     /**
5314      * Queue of pending runnables. Used to postpone calls to post() until this
5315      * view is attached and has a handler.
5316      */
5317     private HandlerActionQueue mRunQueue;
5318 
5319     /**
5320      * The pointer icon when the mouse hovers on this view. The default is null.
5321      */
5322     private PointerIcon mPointerIcon;
5323 
5324     /**
5325      * @hide
5326      */
5327     @UnsupportedAppUsage
5328     String mStartActivityRequestWho;
5329 
5330     @Nullable
5331     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5332 
5333     /** Used to delay visibility updates sent to the autofill manager */
5334     private Handler mVisibilityChangeForAutofillHandler;
5335 
5336     /**
5337      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5338      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5339      */
5340     @Nullable
5341     private ContentCaptureSession mContentCaptureSession;
5342 
5343     /**
5344      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5345      */
5346     private boolean mContentCaptureSessionCached;
5347 
5348     @LayoutRes
5349     private int mSourceLayoutId = ID_NULL;
5350 
5351     @Nullable
5352     private SparseIntArray mAttributeSourceResId;
5353 
5354     @Nullable
5355     private SparseArray<int[]> mAttributeResolutionStacks;
5356 
5357     @StyleRes
5358     private int mExplicitStyle;
5359 
5360     /**
5361      * Specifies which input source classes should provide unbuffered input events to this view
5362      *
5363      * @see View#requestUnbufferedDispatch(int)
5364      */
5365     @InputSourceClass
5366     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5367 
5368     @Nullable
5369     private String[] mReceiveContentMimeTypes;
5370 
5371     @Nullable
5372     private ViewTranslationCallback mViewTranslationCallback;
5373 
5374     @Nullable
5375 
5376     private ViewTranslationResponse mViewTranslationResponse;
5377 
5378     /**
5379      * Simple constructor to use when creating a view from code.
5380      *
5381      * @param context The Context the view is running in, through which it can
5382      *        access the current theme, resources, etc.
5383      */
View(Context context)5384     public View(Context context) {
5385         mContext = context;
5386         mResources = context != null ? context.getResources() : null;
5387         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5388         // Set some flags defaults
5389         mPrivateFlags2 =
5390                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5391                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5392                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5393                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5394                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5395                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5396         mPrivateFlags4 = PFLAG4_AUTO_HANDWRITING_ENABLED;
5397 
5398         final ViewConfiguration configuration = ViewConfiguration.get(context);
5399         mTouchSlop = configuration.getScaledTouchSlop();
5400         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5401 
5402         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5403         mUserPaddingStart = UNDEFINED_PADDING;
5404         mUserPaddingEnd = UNDEFINED_PADDING;
5405         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5406 
5407         if (!sCompatibilityDone && context != null) {
5408             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5409 
5410             // Older apps may need this compatibility hack for measurement.
5411             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5412 
5413             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5414             // of whether a layout was requested on that View.
5415             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5416 
5417             // In M and newer, our widgets can pass a "hint" value in the size
5418             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5419             // know what the expected parent size is going to be, so e.g. list items can size
5420             // themselves at 1/3 the size of their container. It breaks older apps though,
5421             // specifically apps that use some popular open source libraries.
5422             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5423 
5424             // Old versions of the platform would give different results from
5425             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5426             // modes, so we always need to run an additional EXACTLY pass.
5427             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5428 
5429             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5430             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5431             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5432 
5433             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5434             // in apps so we target check it to avoid breaking existing apps.
5435             sPreserveMarginParamsInLayoutParamConversion =
5436                     targetSdkVersion >= Build.VERSION_CODES.N;
5437 
5438             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5439 
5440             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5441 
5442             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5443 
5444             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5445                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5446 
5447             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5448 
5449             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5450 
5451             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5452 
5453             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5454 
5455             sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
5456 
5457             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5458 
5459             GradientDrawable.sWrapNegativeAngleMeasurements =
5460                     targetSdkVersion >= Build.VERSION_CODES.Q;
5461 
5462             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5463 
5464             sCompatibilityDone = true;
5465         }
5466     }
5467 
5468     /**
5469      * Constructor that is called when inflating a view from XML. This is called
5470      * when a view is being constructed from an XML file, supplying attributes
5471      * that were specified in the XML file. This version uses a default style of
5472      * 0, so the only attribute values applied are those in the Context's Theme
5473      * and the given AttributeSet.
5474      *
5475      * <p>
5476      * The method onFinishInflate() will be called after all children have been
5477      * added.
5478      *
5479      * @param context The Context the view is running in, through which it can
5480      *        access the current theme, resources, etc.
5481      * @param attrs The attributes of the XML tag that is inflating the view.
5482      * @see #View(Context, AttributeSet, int)
5483      */
5484     public View(Context context, @Nullable AttributeSet attrs) {
5485         this(context, attrs, 0);
5486     }
5487 
5488     /**
5489      * Perform inflation from XML and apply a class-specific base style from a
5490      * theme attribute. This constructor of View allows subclasses to use their
5491      * own base style when they are inflating. For example, a Button class's
5492      * constructor would call this version of the super class constructor and
5493      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5494      * allows the theme's button style to modify all of the base view attributes
5495      * (in particular its background) as well as the Button class's attributes.
5496      *
5497      * @param context The Context the view is running in, through which it can
5498      *        access the current theme, resources, etc.
5499      * @param attrs The attributes of the XML tag that is inflating the view.
5500      * @param defStyleAttr An attribute in the current theme that contains a
5501      *        reference to a style resource that supplies default values for
5502      *        the view. Can be 0 to not look for defaults.
5503      * @see #View(Context, AttributeSet)
5504      */
5505     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5506         this(context, attrs, defStyleAttr, 0);
5507     }
5508 
5509     /**
5510      * Perform inflation from XML and apply a class-specific base style from a
5511      * theme attribute or style resource. This constructor of View allows
5512      * subclasses to use their own base style when they are inflating.
5513      * <p>
5514      * When determining the final value of a particular attribute, there are
5515      * four inputs that come into play:
5516      * <ol>
5517      * <li>Any attribute values in the given AttributeSet.
5518      * <li>The style resource specified in the AttributeSet (named "style").
5519      * <li>The default style specified by <var>defStyleAttr</var>.
5520      * <li>The default style specified by <var>defStyleRes</var>.
5521      * <li>The base values in this theme.
5522      * </ol>
5523      * <p>
5524      * Each of these inputs is considered in-order, with the first listed taking
5525      * precedence over the following ones. In other words, if in the
5526      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5527      * , then the button's text will <em>always</em> be black, regardless of
5528      * what is specified in any of the styles.
5529      *
5530      * @param context The Context the view is running in, through which it can
5531      *        access the current theme, resources, etc.
5532      * @param attrs The attributes of the XML tag that is inflating the view.
5533      * @param defStyleAttr An attribute in the current theme that contains a
5534      *        reference to a style resource that supplies default values for
5535      *        the view. Can be 0 to not look for defaults.
5536      * @param defStyleRes A resource identifier of a style resource that
5537      *        supplies default values for the view, used only if
5538      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5539      *        to not look for defaults.
5540      * @see #View(Context, AttributeSet, int)
5541      */
5542     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5543         this(context);
5544 
5545         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5546 
5547         final TypedArray a = context.obtainStyledAttributes(
5548                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5549 
5550         retrieveExplicitStyle(context.getTheme(), attrs);
5551         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5552                 defStyleAttr, defStyleRes);
5553 
5554         if (sDebugViewAttributes) {
5555             saveAttributeData(attrs, a);
5556         }
5557 
5558         Drawable background = null;
5559 
5560         int leftPadding = -1;
5561         int topPadding = -1;
5562         int rightPadding = -1;
5563         int bottomPadding = -1;
5564         int startPadding = UNDEFINED_PADDING;
5565         int endPadding = UNDEFINED_PADDING;
5566 
5567         int padding = -1;
5568         int paddingHorizontal = -1;
5569         int paddingVertical = -1;
5570 
5571         int viewFlagValues = 0;
5572         int viewFlagMasks = 0;
5573 
5574         boolean setScrollContainer = false;
5575 
5576         int x = 0;
5577         int y = 0;
5578 
5579         float tx = 0;
5580         float ty = 0;
5581         float tz = 0;
5582         float elevation = 0;
5583         float rotation = 0;
5584         float rotationX = 0;
5585         float rotationY = 0;
5586         float sx = 1f;
5587         float sy = 1f;
5588         boolean transformSet = false;
5589 
5590         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5591         int overScrollMode = mOverScrollMode;
5592         boolean initializeScrollbars = false;
5593         boolean initializeScrollIndicators = false;
5594 
5595         boolean startPaddingDefined = false;
5596         boolean endPaddingDefined = false;
5597         boolean leftPaddingDefined = false;
5598         boolean rightPaddingDefined = false;
5599 
5600         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5601 
5602         // Set default values.
5603         viewFlagValues |= FOCUSABLE_AUTO;
5604         viewFlagMasks |= FOCUSABLE_AUTO;
5605 
5606         final int N = a.getIndexCount();
5607         for (int i = 0; i < N; i++) {
5608             int attr = a.getIndex(i);
5609             switch (attr) {
5610                 case com.android.internal.R.styleable.View_background:
5611                     background = a.getDrawable(attr);
5612                     break;
5613                 case com.android.internal.R.styleable.View_padding:
5614                     padding = a.getDimensionPixelSize(attr, -1);
5615                     mUserPaddingLeftInitial = padding;
5616                     mUserPaddingRightInitial = padding;
5617                     leftPaddingDefined = true;
5618                     rightPaddingDefined = true;
5619                     break;
5620                 case com.android.internal.R.styleable.View_paddingHorizontal:
5621                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5622                     mUserPaddingLeftInitial = paddingHorizontal;
5623                     mUserPaddingRightInitial = paddingHorizontal;
5624                     leftPaddingDefined = true;
5625                     rightPaddingDefined = true;
5626                     break;
5627                 case com.android.internal.R.styleable.View_paddingVertical:
5628                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5629                     break;
5630                 case com.android.internal.R.styleable.View_paddingLeft:
5631                     leftPadding = a.getDimensionPixelSize(attr, -1);
5632                     mUserPaddingLeftInitial = leftPadding;
5633                     leftPaddingDefined = true;
5634                     break;
5635                 case com.android.internal.R.styleable.View_paddingTop:
5636                     topPadding = a.getDimensionPixelSize(attr, -1);
5637                     break;
5638                 case com.android.internal.R.styleable.View_paddingRight:
5639                     rightPadding = a.getDimensionPixelSize(attr, -1);
5640                     mUserPaddingRightInitial = rightPadding;
5641                     rightPaddingDefined = true;
5642                     break;
5643                 case com.android.internal.R.styleable.View_paddingBottom:
5644                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5645                     break;
5646                 case com.android.internal.R.styleable.View_paddingStart:
5647                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5648                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5649                     break;
5650                 case com.android.internal.R.styleable.View_paddingEnd:
5651                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5652                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5653                     break;
5654                 case com.android.internal.R.styleable.View_scrollX:
5655                     x = a.getDimensionPixelOffset(attr, 0);
5656                     break;
5657                 case com.android.internal.R.styleable.View_scrollY:
5658                     y = a.getDimensionPixelOffset(attr, 0);
5659                     break;
5660                 case com.android.internal.R.styleable.View_alpha:
5661                     setAlpha(a.getFloat(attr, 1f));
5662                     break;
5663                 case com.android.internal.R.styleable.View_transformPivotX:
5664                     setPivotX(a.getDimension(attr, 0));
5665                     break;
5666                 case com.android.internal.R.styleable.View_transformPivotY:
5667                     setPivotY(a.getDimension(attr, 0));
5668                     break;
5669                 case com.android.internal.R.styleable.View_translationX:
5670                     tx = a.getDimension(attr, 0);
5671                     transformSet = true;
5672                     break;
5673                 case com.android.internal.R.styleable.View_translationY:
5674                     ty = a.getDimension(attr, 0);
5675                     transformSet = true;
5676                     break;
5677                 case com.android.internal.R.styleable.View_translationZ:
5678                     tz = a.getDimension(attr, 0);
5679                     transformSet = true;
5680                     break;
5681                 case com.android.internal.R.styleable.View_elevation:
5682                     elevation = a.getDimension(attr, 0);
5683                     transformSet = true;
5684                     break;
5685                 case com.android.internal.R.styleable.View_rotation:
5686                     rotation = a.getFloat(attr, 0);
5687                     transformSet = true;
5688                     break;
5689                 case com.android.internal.R.styleable.View_rotationX:
5690                     rotationX = a.getFloat(attr, 0);
5691                     transformSet = true;
5692                     break;
5693                 case com.android.internal.R.styleable.View_rotationY:
5694                     rotationY = a.getFloat(attr, 0);
5695                     transformSet = true;
5696                     break;
5697                 case com.android.internal.R.styleable.View_scaleX:
5698                     sx = a.getFloat(attr, 1f);
5699                     transformSet = true;
5700                     break;
5701                 case com.android.internal.R.styleable.View_scaleY:
5702                     sy = a.getFloat(attr, 1f);
5703                     transformSet = true;
5704                     break;
5705                 case com.android.internal.R.styleable.View_id:
5706                     mID = a.getResourceId(attr, NO_ID);
5707                     break;
5708                 case com.android.internal.R.styleable.View_tag:
5709                     mTag = a.getText(attr);
5710                     break;
5711                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5712                     if (a.getBoolean(attr, false)) {
5713                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5714                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5715                     }
5716                     break;
5717                 case com.android.internal.R.styleable.View_focusable:
5718                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5719                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5720                         viewFlagMasks |= FOCUSABLE_MASK;
5721                     }
5722                     break;
5723                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5724                     if (a.getBoolean(attr, false)) {
5725                         // unset auto focus since focusableInTouchMode implies explicit focusable
5726                         viewFlagValues &= ~FOCUSABLE_AUTO;
5727                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5728                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5729                     }
5730                     break;
5731                 case com.android.internal.R.styleable.View_clickable:
5732                     if (a.getBoolean(attr, false)) {
5733                         viewFlagValues |= CLICKABLE;
5734                         viewFlagMasks |= CLICKABLE;
5735                     }
5736                     break;
5737                 case com.android.internal.R.styleable.View_allowClickWhenDisabled:
5738                     setAllowClickWhenDisabled(a.getBoolean(attr, false));
5739                     break;
5740                 case com.android.internal.R.styleable.View_longClickable:
5741                     if (a.getBoolean(attr, false)) {
5742                         viewFlagValues |= LONG_CLICKABLE;
5743                         viewFlagMasks |= LONG_CLICKABLE;
5744                     }
5745                     break;
5746                 case com.android.internal.R.styleable.View_contextClickable:
5747                     if (a.getBoolean(attr, false)) {
5748                         viewFlagValues |= CONTEXT_CLICKABLE;
5749                         viewFlagMasks |= CONTEXT_CLICKABLE;
5750                     }
5751                     break;
5752                 case com.android.internal.R.styleable.View_saveEnabled:
5753                     if (!a.getBoolean(attr, true)) {
5754                         viewFlagValues |= SAVE_DISABLED;
5755                         viewFlagMasks |= SAVE_DISABLED_MASK;
5756                     }
5757                     break;
5758                 case com.android.internal.R.styleable.View_duplicateParentState:
5759                     if (a.getBoolean(attr, false)) {
5760                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5761                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5762                     }
5763                     break;
5764                 case com.android.internal.R.styleable.View_visibility:
5765                     final int visibility = a.getInt(attr, 0);
5766                     if (visibility != 0) {
5767                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5768                         viewFlagMasks |= VISIBILITY_MASK;
5769                     }
5770                     break;
5771                 case com.android.internal.R.styleable.View_layoutDirection:
5772                     // Clear any layout direction flags (included resolved bits) already set
5773                     mPrivateFlags2 &=
5774                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5775                     // Set the layout direction flags depending on the value of the attribute
5776                     final int layoutDirection = a.getInt(attr, -1);
5777                     final int value = (layoutDirection != -1) ?
5778                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5779                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5780                     break;
5781                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5782                     final int cacheQuality = a.getInt(attr, 0);
5783                     if (cacheQuality != 0) {
5784                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5785                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5786                     }
5787                     break;
5788                 case com.android.internal.R.styleable.View_contentDescription:
5789                     setContentDescription(a.getString(attr));
5790                     break;
5791                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5792                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5793                     break;
5794                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5795                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5796                     break;
5797                 case com.android.internal.R.styleable.View_labelFor:
5798                     setLabelFor(a.getResourceId(attr, NO_ID));
5799                     break;
5800                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5801                     if (!a.getBoolean(attr, true)) {
5802                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5803                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5804                     }
5805                     break;
5806                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5807                     if (!a.getBoolean(attr, true)) {
5808                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5809                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5810                     }
5811                     break;
5812                 case R.styleable.View_scrollbars:
5813                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5814                     if (scrollbars != SCROLLBARS_NONE) {
5815                         viewFlagValues |= scrollbars;
5816                         viewFlagMasks |= SCROLLBARS_MASK;
5817                         initializeScrollbars = true;
5818                     }
5819                     break;
5820                 //noinspection deprecation
5821                 case R.styleable.View_fadingEdge:
5822                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5823                         // Ignore the attribute starting with ICS
5824                         break;
5825                     }
5826                     // With builds < ICS, fall through and apply fading edges
5827                 case R.styleable.View_requiresFadingEdge:
5828                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5829                     if (fadingEdge != FADING_EDGE_NONE) {
5830                         viewFlagValues |= fadingEdge;
5831                         viewFlagMasks |= FADING_EDGE_MASK;
5832                         initializeFadingEdgeInternal(a);
5833                     }
5834                     break;
5835                 case R.styleable.View_scrollbarStyle:
5836                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5837                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5838                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5839                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5840                     }
5841                     break;
5842                 case R.styleable.View_isScrollContainer:
5843                     setScrollContainer = true;
5844                     if (a.getBoolean(attr, false)) {
5845                         setScrollContainer(true);
5846                     }
5847                     break;
5848                 case com.android.internal.R.styleable.View_keepScreenOn:
5849                     if (a.getBoolean(attr, false)) {
5850                         viewFlagValues |= KEEP_SCREEN_ON;
5851                         viewFlagMasks |= KEEP_SCREEN_ON;
5852                     }
5853                     break;
5854                 case R.styleable.View_filterTouchesWhenObscured:
5855                     if (a.getBoolean(attr, false)) {
5856                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5857                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5858                     }
5859                     break;
5860                 case R.styleable.View_nextFocusLeft:
5861                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5862                     break;
5863                 case R.styleable.View_nextFocusRight:
5864                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5865                     break;
5866                 case R.styleable.View_nextFocusUp:
5867                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5868                     break;
5869                 case R.styleable.View_nextFocusDown:
5870                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5871                     break;
5872                 case R.styleable.View_nextFocusForward:
5873                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5874                     break;
5875                 case R.styleable.View_nextClusterForward:
5876                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5877                     break;
5878                 case R.styleable.View_minWidth:
5879                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5880                     break;
5881                 case R.styleable.View_minHeight:
5882                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5883                     break;
5884                 case R.styleable.View_onClick:
5885                     if (context.isRestricted()) {
5886                         throw new IllegalStateException("The android:onClick attribute cannot "
5887                                 + "be used within a restricted context");
5888                     }
5889 
5890                     final String handlerName = a.getString(attr);
5891                     if (handlerName != null) {
5892                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5893                     }
5894                     break;
5895                 case R.styleable.View_overScrollMode:
5896                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5897                     break;
5898                 case R.styleable.View_verticalScrollbarPosition:
5899                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5900                     break;
5901                 case R.styleable.View_layerType:
5902                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5903                     break;
5904                 case R.styleable.View_textDirection:
5905                     // Clear any text direction flag already set
5906                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5907                     // Set the text direction flags depending on the value of the attribute
5908                     final int textDirection = a.getInt(attr, -1);
5909                     if (textDirection != -1) {
5910                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5911                     }
5912                     break;
5913                 case R.styleable.View_textAlignment:
5914                     // Clear any text alignment flag already set
5915                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5916                     // Set the text alignment flag depending on the value of the attribute
5917                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5918                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5919                     break;
5920                 case R.styleable.View_importantForAccessibility:
5921                     setImportantForAccessibility(a.getInt(attr,
5922                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5923                     break;
5924                 case R.styleable.View_accessibilityLiveRegion:
5925                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5926                     break;
5927                 case R.styleable.View_transitionName:
5928                     setTransitionName(a.getString(attr));
5929                     break;
5930                 case R.styleable.View_nestedScrollingEnabled:
5931                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5932                     break;
5933                 case R.styleable.View_stateListAnimator:
5934                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5935                             a.getResourceId(attr, 0)));
5936                     break;
5937                 case R.styleable.View_backgroundTint:
5938                     // This will get applied later during setBackground().
5939                     if (mBackgroundTint == null) {
5940                         mBackgroundTint = new TintInfo();
5941                     }
5942                     mBackgroundTint.mTintList = a.getColorStateList(
5943                             R.styleable.View_backgroundTint);
5944                     mBackgroundTint.mHasTintList = true;
5945                     break;
5946                 case R.styleable.View_backgroundTintMode:
5947                     // This will get applied later during setBackground().
5948                     if (mBackgroundTint == null) {
5949                         mBackgroundTint = new TintInfo();
5950                     }
5951                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
5952                             R.styleable.View_backgroundTintMode, -1), null);
5953                     mBackgroundTint.mHasTintMode = true;
5954                     break;
5955                 case R.styleable.View_outlineProvider:
5956                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5957                             PROVIDER_BACKGROUND));
5958                     break;
5959                 case R.styleable.View_foreground:
5960                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5961                         setForeground(a.getDrawable(attr));
5962                     }
5963                     break;
5964                 case R.styleable.View_foregroundGravity:
5965                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5966                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5967                     }
5968                     break;
5969                 case R.styleable.View_foregroundTintMode:
5970                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5971                         setForegroundTintBlendMode(
5972                                 Drawable.parseBlendMode(a.getInt(attr, -1),
5973                                         null));
5974                     }
5975                     break;
5976                 case R.styleable.View_foregroundTint:
5977                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5978                         setForegroundTintList(a.getColorStateList(attr));
5979                     }
5980                     break;
5981                 case R.styleable.View_foregroundInsidePadding:
5982                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5983                         if (mForegroundInfo == null) {
5984                             mForegroundInfo = new ForegroundInfo();
5985                         }
5986                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5987                                 mForegroundInfo.mInsidePadding);
5988                     }
5989                     break;
5990                 case R.styleable.View_scrollIndicators:
5991                     final int scrollIndicators =
5992                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5993                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5994                     if (scrollIndicators != 0) {
5995                         mPrivateFlags3 |= scrollIndicators;
5996                         initializeScrollIndicators = true;
5997                     }
5998                     break;
5999                 case R.styleable.View_pointerIcon:
6000                     final int resourceId = a.getResourceId(attr, 0);
6001                     if (resourceId != 0) {
6002                         setPointerIcon(PointerIcon.load(
6003                                 context.getResources(), resourceId));
6004                     } else {
6005                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
6006                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
6007                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
6008                         }
6009                     }
6010                     break;
6011                 case R.styleable.View_forceHasOverlappingRendering:
6012                     if (a.peekValue(attr) != null) {
6013                         forceHasOverlappingRendering(a.getBoolean(attr, true));
6014                     }
6015                     break;
6016                 case R.styleable.View_tooltipText:
6017                     setTooltipText(a.getText(attr));
6018                     break;
6019                 case R.styleable.View_keyboardNavigationCluster:
6020                     if (a.peekValue(attr) != null) {
6021                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
6022                     }
6023                     break;
6024                 case R.styleable.View_focusedByDefault:
6025                     if (a.peekValue(attr) != null) {
6026                         setFocusedByDefault(a.getBoolean(attr, true));
6027                     }
6028                     break;
6029                 case R.styleable.View_autofillHints:
6030                     if (a.peekValue(attr) != null) {
6031                         CharSequence[] rawHints = null;
6032                         String rawString = null;
6033 
6034                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
6035                             int resId = a.getResourceId(attr, 0);
6036 
6037                             try {
6038                                 rawHints = a.getTextArray(attr);
6039                             } catch (Resources.NotFoundException e) {
6040                                 rawString = getResources().getString(resId);
6041                             }
6042                         } else {
6043                             rawString = a.getString(attr);
6044                         }
6045 
6046                         if (rawHints == null) {
6047                             if (rawString == null) {
6048                                 throw new IllegalArgumentException(
6049                                         "Could not resolve autofillHints");
6050                             } else {
6051                                 rawHints = rawString.split(",");
6052                             }
6053                         }
6054 
6055                         String[] hints = new String[rawHints.length];
6056 
6057                         int numHints = rawHints.length;
6058                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
6059                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
6060                         }
6061                         setAutofillHints(hints);
6062                     }
6063                     break;
6064                 case R.styleable.View_importantForAutofill:
6065                     if (a.peekValue(attr) != null) {
6066                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
6067                     }
6068                     break;
6069                 case R.styleable.View_importantForContentCapture:
6070                     if (a.peekValue(attr) != null) {
6071                         setImportantForContentCapture(a.getInt(attr,
6072                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
6073                     }
6074                 case R.styleable.View_defaultFocusHighlightEnabled:
6075                     if (a.peekValue(attr) != null) {
6076                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
6077                     }
6078                     break;
6079                 case R.styleable.View_screenReaderFocusable:
6080                     if (a.peekValue(attr) != null) {
6081                         setScreenReaderFocusable(a.getBoolean(attr, false));
6082                     }
6083                     break;
6084                 case R.styleable.View_accessibilityPaneTitle:
6085                     if (a.peekValue(attr) != null) {
6086                         setAccessibilityPaneTitle(a.getString(attr));
6087                     }
6088                     break;
6089                 case R.styleable.View_outlineSpotShadowColor:
6090                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6091                     break;
6092                 case R.styleable.View_outlineAmbientShadowColor:
6093                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6094                     break;
6095                 case com.android.internal.R.styleable.View_accessibilityHeading:
6096                     setAccessibilityHeading(a.getBoolean(attr, false));
6097                     break;
6098                 case R.styleable.View_forceDarkAllowed:
6099                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6100                     break;
6101                 case R.styleable.View_scrollCaptureHint:
6102                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6103                     break;
6104                 case R.styleable.View_clipToOutline:
6105                     setClipToOutline(a.getBoolean(attr, false));
6106                     break;
6107                 case R.styleable.View_preferKeepClear:
6108                     setPreferKeepClear(a.getBoolean(attr, false));
6109                     break;
6110                 case R.styleable.View_autoHandwritingEnabled:
6111                     setAutoHandwritingEnabled(a.getBoolean(attr, true));
6112                     break;
6113             }
6114         }
6115 
6116         setOverScrollMode(overScrollMode);
6117 
6118         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6119         // the resolved layout direction). Those cached values will be used later during padding
6120         // resolution.
6121         mUserPaddingStart = startPadding;
6122         mUserPaddingEnd = endPadding;
6123 
6124         if (background != null) {
6125             setBackground(background);
6126         }
6127 
6128         // setBackground above will record that padding is currently provided by the background.
6129         // If we have padding specified via xml, record that here instead and use it.
6130         mLeftPaddingDefined = leftPaddingDefined;
6131         mRightPaddingDefined = rightPaddingDefined;
6132 
6133         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6134         // bottomPadding, and padding set by background.  Valid padding beats everything.
6135         if (padding >= 0) {
6136             leftPadding = padding;
6137             topPadding = padding;
6138             rightPadding = padding;
6139             bottomPadding = padding;
6140             mUserPaddingLeftInitial = padding;
6141             mUserPaddingRightInitial = padding;
6142         } else {
6143             if (paddingHorizontal >= 0) {
6144                 leftPadding = paddingHorizontal;
6145                 rightPadding = paddingHorizontal;
6146                 mUserPaddingLeftInitial = paddingHorizontal;
6147                 mUserPaddingRightInitial = paddingHorizontal;
6148             }
6149             if (paddingVertical >= 0) {
6150                 topPadding = paddingVertical;
6151                 bottomPadding = paddingVertical;
6152             }
6153         }
6154 
6155         if (isRtlCompatibilityMode()) {
6156             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6157             // left / right padding are used if defined (meaning here nothing to do). If they are not
6158             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6159             // start / end and resolve them as left / right (layout direction is not taken into account).
6160             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6161             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6162             // defined.
6163             if (!mLeftPaddingDefined && startPaddingDefined) {
6164                 leftPadding = startPadding;
6165             }
6166             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6167             if (!mRightPaddingDefined && endPaddingDefined) {
6168                 rightPadding = endPadding;
6169             }
6170             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6171         } else {
6172             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6173             // values defined. Otherwise, left /right values are used.
6174             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6175             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6176             // defined.
6177             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6178 
6179             if (mLeftPaddingDefined && !hasRelativePadding) {
6180                 mUserPaddingLeftInitial = leftPadding;
6181             }
6182             if (mRightPaddingDefined && !hasRelativePadding) {
6183                 mUserPaddingRightInitial = rightPadding;
6184             }
6185         }
6186 
6187         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6188         // them on if topPadding or bottomPadding are not valid.
6189         internalSetPadding(
6190                 mUserPaddingLeftInitial,
6191                 topPadding >= 0 ? topPadding : mPaddingTop,
6192                 mUserPaddingRightInitial,
6193                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6194 
6195         if (viewFlagMasks != 0) {
6196             setFlags(viewFlagValues, viewFlagMasks);
6197         }
6198 
6199         if (initializeScrollbars) {
6200             initializeScrollbarsInternal(a);
6201         }
6202 
6203         if (initializeScrollIndicators) {
6204             initializeScrollIndicatorsInternal();
6205         }
6206 
6207         a.recycle();
6208 
6209         // Needs to be called after mViewFlags is set
6210         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6211             recomputePadding();
6212         }
6213 
6214         if (x != 0 || y != 0) {
6215             scrollTo(x, y);
6216         }
6217 
6218         if (transformSet) {
6219             setTranslationX(tx);
6220             setTranslationY(ty);
6221             setTranslationZ(tz);
6222             setElevation(elevation);
6223             setRotation(rotation);
6224             setRotationX(rotationX);
6225             setRotationY(rotationY);
6226             setScaleX(sx);
6227             setScaleY(sy);
6228         }
6229 
6230         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6231             setScrollContainer(true);
6232         }
6233 
6234         computeOpaqueFlags();
6235     }
6236 
6237     /**
6238      * Returns the ordered list of resource ID that are considered when resolving attribute values
6239      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6240      * XML. It will also include a set of explicit styles if specified in XML using
6241      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6242      *
6243      * <p>
6244      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6245      * is enabled in Android developer options.
6246      *
6247      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6248      * @return ordered list of resource ID that are considered when resolving attribute values for
6249      * this {@link View}.
6250      */
6251     @NonNull
6252     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6253         if (!sDebugViewAttributes
6254                 || mAttributeResolutionStacks == null
6255                 || mAttributeResolutionStacks.get(attribute) == null) {
6256             return new int[0];
6257         }
6258         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6259         int stackSize = attributeResolutionStack.length;
6260         if (mSourceLayoutId != ID_NULL) {
6261             stackSize++;
6262         }
6263 
6264         int currentIndex = 0;
6265         int[] stack = new int[stackSize];
6266 
6267         if (mSourceLayoutId != ID_NULL) {
6268             stack[currentIndex] = mSourceLayoutId;
6269             currentIndex++;
6270         }
6271         for (int i = 0; i < attributeResolutionStack.length; i++) {
6272             stack[currentIndex] = attributeResolutionStack[i];
6273             currentIndex++;
6274         }
6275         return stack;
6276     }
6277 
6278     /**
6279      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6280      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6281      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6282      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6283      *
6284      * <p>
6285      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6286      * is enabled in Android developer options.
6287      *
6288      * @return mapping of attribute resource ID to source resource ID where the attribute value
6289      * was set.
6290      */
6291     @NonNull
6292     @SuppressWarnings("AndroidFrameworkEfficientCollections")
6293     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6294         HashMap<Integer, Integer> map = new HashMap<>();
6295         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6296             return map;
6297         }
6298         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6299             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6300         }
6301         return map;
6302     }
6303 
6304     /**
6305      * Returns the resource ID for the style specified using {@code style="..."} in the
6306      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6307      * specified or otherwise not applicable.
6308      * <p>
6309      * Each {@link View} can have an explicit style specified in the layout file.
6310      * This style is used first during the {@link View} attribute resolution, then if an attribute
6311      * is not defined there the resource system looks at default style and theme as fallbacks.
6312      *
6313      * <p>
6314      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6315      * is enabled in Android developer options.
6316      *
6317      * @return The resource ID for the style specified using {@code style="..."} in the
6318      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6319      *      if not specified or otherwise not applicable.
6320      */
6321     @StyleRes
6322     public int getExplicitStyle() {
6323         if (!sDebugViewAttributes) {
6324             return ID_NULL;
6325         }
6326         return mExplicitStyle;
6327     }
6328 
6329     /**
6330      * An implementation of OnClickListener that attempts to lazily load a
6331      * named click handling method from a parent or ancestor context.
6332      */
6333     private static class DeclaredOnClickListener implements OnClickListener {
6334         private final View mHostView;
6335         private final String mMethodName;
6336 
6337         private Method mResolvedMethod;
6338         private Context mResolvedContext;
6339 
6340         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6341             mHostView = hostView;
6342             mMethodName = methodName;
6343         }
6344 
6345         @Override
6346         public void onClick(@NonNull View v) {
6347             if (mResolvedMethod == null) {
6348                 resolveMethod(mHostView.getContext(), mMethodName);
6349             }
6350 
6351             try {
6352                 mResolvedMethod.invoke(mResolvedContext, v);
6353             } catch (IllegalAccessException e) {
6354                 throw new IllegalStateException(
6355                         "Could not execute non-public method for android:onClick", e);
6356             } catch (InvocationTargetException e) {
6357                 throw new IllegalStateException(
6358                         "Could not execute method for android:onClick", e);
6359             }
6360         }
6361 
6362         @NonNull
6363         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6364             while (context != null) {
6365                 try {
6366                     if (!context.isRestricted()) {
6367                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6368                         if (method != null) {
6369                             mResolvedMethod = method;
6370                             mResolvedContext = context;
6371                             return;
6372                         }
6373                     }
6374                 } catch (NoSuchMethodException e) {
6375                     // Failed to find method, keep searching up the hierarchy.
6376                 }
6377 
6378                 if (context instanceof ContextWrapper) {
6379                     context = ((ContextWrapper) context).getBaseContext();
6380                 } else {
6381                     // Can't search up the hierarchy, null out and fail.
6382                     context = null;
6383                 }
6384             }
6385 
6386             final int id = mHostView.getId();
6387             final String idText = id == NO_ID ? "" : " with id '"
6388                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6389             throw new IllegalStateException("Could not find method " + mMethodName
6390                     + "(View) in a parent or ancestor Context for android:onClick "
6391                     + "attribute defined on view " + mHostView.getClass() + idText);
6392         }
6393     }
6394 
6395     /**
6396      * Non-public constructor for use in testing
6397      */
6398     @UnsupportedAppUsage
6399     View() {
6400         mResources = null;
6401         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6402     }
6403 
6404     /**
6405      * Returns {@code true} when the View is attached and the system developer setting to show
6406      * the layout bounds is enabled or {@code false} otherwise.
6407      */
6408     public final boolean isShowingLayoutBounds() {
6409         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6410     }
6411 
6412     /**
6413      * Used to test isShowingLayoutBounds(). This sets the local value used
6414      * by that function. This method does nothing if the layout isn't attached.
6415      *
6416      * @hide
6417      */
6418     @TestApi
6419     public final void setShowingLayoutBounds(boolean debugLayout) {
6420         if (mAttachInfo != null) {
6421             mAttachInfo.mDebugLayout = debugLayout;
6422         }
6423     }
6424 
6425     private static SparseArray<String> getAttributeMap() {
6426         if (mAttributeMap == null) {
6427             mAttributeMap = new SparseArray<>();
6428         }
6429         return mAttributeMap;
6430     }
6431 
6432     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6433             @Nullable AttributeSet attrs) {
6434         if (!sDebugViewAttributes) {
6435             return;
6436         }
6437         mExplicitStyle = theme.getExplicitStyle(attrs);
6438     }
6439 
6440     /**
6441      * Stores debugging information about attributes. This should be called in a constructor by
6442      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6443      * then the custom attributes used by this view will not be visible in layout inspection tools.
6444      *
6445      *  @param context Context under which this view is created.
6446      * @param styleable A reference to styleable array R.styleable.Foo
6447      * @param attrs AttributeSet used to construct this view.
6448      * @param t Resolved {@link TypedArray} returned by a call to
6449      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6450      * @param defStyleAttr Default style attribute passed into the view constructor.
6451      * @param defStyleRes Default style resource passed into the view constructor.
6452      */
6453     public final void saveAttributeDataForStyleable(@NonNull Context context,
6454             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6455             int defStyleAttr, int defStyleRes) {
6456         if (!sDebugViewAttributes) {
6457             return;
6458         }
6459 
6460         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6461                 defStyleAttr, defStyleRes, mExplicitStyle);
6462 
6463         if (mAttributeResolutionStacks == null) {
6464             mAttributeResolutionStacks = new SparseArray<>();
6465         }
6466 
6467         if (mAttributeSourceResId == null) {
6468             mAttributeSourceResId = new SparseIntArray();
6469         }
6470 
6471         final int indexCount = t.getIndexCount();
6472         for (int j = 0; j < indexCount; ++j) {
6473             final int index = t.getIndex(j);
6474             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6475             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6476         }
6477     }
6478 
6479     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6480         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6481         final int indexCount = t.getIndexCount();
6482         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6483 
6484         int i = 0;
6485 
6486         // Store raw XML attributes.
6487         for (int j = 0; j < attrsCount; ++j) {
6488             attributes[i] = attrs.getAttributeName(j);
6489             attributes[i + 1] = attrs.getAttributeValue(j);
6490             i += 2;
6491         }
6492 
6493         // Store resolved styleable attributes.
6494         final Resources res = t.getResources();
6495         final SparseArray<String> attributeMap = getAttributeMap();
6496         for (int j = 0; j < indexCount; ++j) {
6497             final int index = t.getIndex(j);
6498             if (!t.hasValueOrEmpty(index)) {
6499                 // Value is undefined. Skip it.
6500                 continue;
6501             }
6502 
6503             final int resourceId = t.getResourceId(index, 0);
6504             if (resourceId == 0) {
6505                 // Value is not a reference. Skip it.
6506                 continue;
6507             }
6508 
6509             String resourceName = attributeMap.get(resourceId);
6510             if (resourceName == null) {
6511                 try {
6512                     resourceName = res.getResourceName(resourceId);
6513                 } catch (Resources.NotFoundException e) {
6514                     resourceName = "0x" + Integer.toHexString(resourceId);
6515                 }
6516                 attributeMap.put(resourceId, resourceName);
6517             }
6518 
6519             attributes[i] = resourceName;
6520             attributes[i + 1] = t.getString(index);
6521             i += 2;
6522         }
6523 
6524         // Trim to fit contents.
6525         final String[] trimmed = new String[i];
6526         System.arraycopy(attributes, 0, trimmed, 0, i);
6527         mAttributes = trimmed;
6528     }
6529 
6530     @Override
6531     public String toString() {
6532         StringBuilder out = new StringBuilder(256);
6533         out.append(getClass().getName());
6534         out.append('{');
6535         out.append(Integer.toHexString(System.identityHashCode(this)));
6536         out.append(' ');
6537         switch (mViewFlags&VISIBILITY_MASK) {
6538             case VISIBLE: out.append('V'); break;
6539             case INVISIBLE: out.append('I'); break;
6540             case GONE: out.append('G'); break;
6541             default: out.append('.'); break;
6542         }
6543         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6544         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6545         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6546         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6547         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6548         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6549         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6550         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6551         out.append(' ');
6552         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6553         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6554         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6555         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6556             out.append('p');
6557         } else {
6558             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6559         }
6560         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6561         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6562         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6563         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6564         out.append(' ');
6565         out.append(mLeft);
6566         out.append(',');
6567         out.append(mTop);
6568         out.append('-');
6569         out.append(mRight);
6570         out.append(',');
6571         out.append(mBottom);
6572         appendId(out);
6573         if (mAutofillId != null) {
6574             out.append(" aid="); out.append(mAutofillId);
6575         }
6576         out.append("}");
6577         return out.toString();
6578     }
6579 
6580     void appendId(StringBuilder out) {
6581         final int id = getId();
6582         if (id != NO_ID) {
6583             out.append(" #");
6584             out.append(Integer.toHexString(id));
6585             final Resources r = mResources;
6586             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6587                 try {
6588                     String pkgname;
6589                     switch (id&0xff000000) {
6590                         case 0x7f000000:
6591                             pkgname="app";
6592                             break;
6593                         case 0x01000000:
6594                             pkgname="android";
6595                             break;
6596                         default:
6597                             pkgname = r.getResourcePackageName(id);
6598                             break;
6599                     }
6600                     String typename = r.getResourceTypeName(id);
6601                     String entryname = r.getResourceEntryName(id);
6602                     out.append(" ");
6603                     out.append(pkgname);
6604                     out.append(":");
6605                     out.append(typename);
6606                     out.append("/");
6607                     out.append(entryname);
6608                 } catch (Resources.NotFoundException e) {
6609                 }
6610             }
6611         }
6612     }
6613 
6614     /**
6615      * <p>
6616      * Initializes the fading edges from a given set of styled attributes. This
6617      * method should be called by subclasses that need fading edges and when an
6618      * instance of these subclasses is created programmatically rather than
6619      * being inflated from XML. This method is automatically called when the XML
6620      * is inflated.
6621      * </p>
6622      *
6623      * @param a the styled attributes set to initialize the fading edges from
6624      *
6625      * @removed
6626      */
6627     protected void initializeFadingEdge(TypedArray a) {
6628         // This method probably shouldn't have been included in the SDK to begin with.
6629         // It relies on 'a' having been initialized using an attribute filter array that is
6630         // not publicly available to the SDK. The old method has been renamed
6631         // to initializeFadingEdgeInternal and hidden for framework use only;
6632         // this one initializes using defaults to make it safe to call for apps.
6633 
6634         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6635 
6636         initializeFadingEdgeInternal(arr);
6637 
6638         arr.recycle();
6639     }
6640 
6641     /**
6642      * <p>
6643      * Initializes the fading edges from a given set of styled attributes. This
6644      * method should be called by subclasses that need fading edges and when an
6645      * instance of these subclasses is created programmatically rather than
6646      * being inflated from XML. This method is automatically called when the XML
6647      * is inflated.
6648      * </p>
6649      *
6650      * @param a the styled attributes set to initialize the fading edges from
6651      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6652      */
6653     protected void initializeFadingEdgeInternal(TypedArray a) {
6654         initScrollCache();
6655 
6656         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6657                 R.styleable.View_fadingEdgeLength,
6658                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6659     }
6660 
6661     /**
6662      * Returns the size of the vertical faded edges used to indicate that more
6663      * content in this view is visible.
6664      *
6665      * @return The size in pixels of the vertical faded edge or 0 if vertical
6666      *         faded edges are not enabled for this view.
6667      * @attr ref android.R.styleable#View_fadingEdgeLength
6668      */
6669     public int getVerticalFadingEdgeLength() {
6670         if (isVerticalFadingEdgeEnabled()) {
6671             ScrollabilityCache cache = mScrollCache;
6672             if (cache != null) {
6673                 return cache.fadingEdgeLength;
6674             }
6675         }
6676         return 0;
6677     }
6678 
6679     /**
6680      * Set the size of the faded edge used to indicate that more content in this
6681      * view is available.  Will not change whether the fading edge is enabled; use
6682      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6683      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6684      * for the vertical or horizontal fading edges.
6685      *
6686      * @param length The size in pixels of the faded edge used to indicate that more
6687      *        content in this view is visible.
6688      */
6689     public void setFadingEdgeLength(int length) {
6690         initScrollCache();
6691         mScrollCache.fadingEdgeLength = length;
6692     }
6693 
6694     /**
6695      * Returns the size of the horizontal faded edges used to indicate that more
6696      * content in this view is visible.
6697      *
6698      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6699      *         faded edges are not enabled for this view.
6700      * @attr ref android.R.styleable#View_fadingEdgeLength
6701      */
6702     public int getHorizontalFadingEdgeLength() {
6703         if (isHorizontalFadingEdgeEnabled()) {
6704             ScrollabilityCache cache = mScrollCache;
6705             if (cache != null) {
6706                 return cache.fadingEdgeLength;
6707             }
6708         }
6709         return 0;
6710     }
6711 
6712     /**
6713      * Returns the width of the vertical scrollbar.
6714      *
6715      * @return The width in pixels of the vertical scrollbar or 0 if there
6716      *         is no vertical scrollbar.
6717      */
6718     public int getVerticalScrollbarWidth() {
6719         ScrollabilityCache cache = mScrollCache;
6720         if (cache != null) {
6721             ScrollBarDrawable scrollBar = cache.scrollBar;
6722             if (scrollBar != null) {
6723                 int size = scrollBar.getSize(true);
6724                 if (size <= 0) {
6725                     size = cache.scrollBarSize;
6726                 }
6727                 return size;
6728             }
6729             return 0;
6730         }
6731         return 0;
6732     }
6733 
6734     /**
6735      * Returns the height of the horizontal scrollbar.
6736      *
6737      * @return The height in pixels of the horizontal scrollbar or 0 if
6738      *         there is no horizontal scrollbar.
6739      */
6740     protected int getHorizontalScrollbarHeight() {
6741         ScrollabilityCache cache = mScrollCache;
6742         if (cache != null) {
6743             ScrollBarDrawable scrollBar = cache.scrollBar;
6744             if (scrollBar != null) {
6745                 int size = scrollBar.getSize(false);
6746                 if (size <= 0) {
6747                     size = cache.scrollBarSize;
6748                 }
6749                 return size;
6750             }
6751             return 0;
6752         }
6753         return 0;
6754     }
6755 
6756     /**
6757      * <p>
6758      * Initializes the scrollbars from a given set of styled attributes. This
6759      * method should be called by subclasses that need scrollbars and when an
6760      * instance of these subclasses is created programmatically rather than
6761      * being inflated from XML. This method is automatically called when the XML
6762      * is inflated.
6763      * </p>
6764      *
6765      * @param a the styled attributes set to initialize the scrollbars from
6766      *
6767      * @removed
6768      */
6769     protected void initializeScrollbars(TypedArray a) {
6770         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6771         // using the View filter array which is not available to the SDK. As such, internal
6772         // framework usage now uses initializeScrollbarsInternal and we grab a default
6773         // TypedArray with the right filter instead here.
6774         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6775 
6776         initializeScrollbarsInternal(arr);
6777 
6778         // We ignored the method parameter. Recycle the one we actually did use.
6779         arr.recycle();
6780     }
6781 
6782     private void initializeScrollBarDrawable() {
6783         initScrollCache();
6784 
6785         if (mScrollCache.scrollBar == null) {
6786             mScrollCache.scrollBar = new ScrollBarDrawable();
6787             mScrollCache.scrollBar.setState(getDrawableState());
6788             mScrollCache.scrollBar.setCallback(this);
6789         }
6790     }
6791 
6792     /**
6793      * <p>
6794      * Initializes the scrollbars from a given set of styled attributes. This
6795      * method should be called by subclasses that need scrollbars and when an
6796      * instance of these subclasses is created programmatically rather than
6797      * being inflated from XML. This method is automatically called when the XML
6798      * is inflated.
6799      * </p>
6800      *
6801      * @param a the styled attributes set to initialize the scrollbars from
6802      * @hide
6803      */
6804     @UnsupportedAppUsage
6805     protected void initializeScrollbarsInternal(TypedArray a) {
6806         initScrollCache();
6807 
6808         final ScrollabilityCache scrollabilityCache = mScrollCache;
6809 
6810         if (scrollabilityCache.scrollBar == null) {
6811             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6812             scrollabilityCache.scrollBar.setState(getDrawableState());
6813             scrollabilityCache.scrollBar.setCallback(this);
6814         }
6815 
6816         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6817 
6818         if (!fadeScrollbars) {
6819             scrollabilityCache.state = ScrollabilityCache.ON;
6820         }
6821         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6822 
6823 
6824         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6825                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6826                         .getScrollBarFadeDuration());
6827         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6828                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6829                 ViewConfiguration.getScrollDefaultDelay());
6830 
6831 
6832         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6833                 com.android.internal.R.styleable.View_scrollbarSize,
6834                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6835 
6836         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6837         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6838 
6839         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6840         if (thumb != null) {
6841             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6842         }
6843 
6844         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6845                 false);
6846         if (alwaysDraw) {
6847             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6848         }
6849 
6850         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6851         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6852 
6853         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6854         if (thumb != null) {
6855             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6856         }
6857 
6858         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6859                 false);
6860         if (alwaysDraw) {
6861             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6862         }
6863 
6864         // Apply layout direction to the new Drawables if needed
6865         final int layoutDirection = getLayoutDirection();
6866         if (track != null) {
6867             track.setLayoutDirection(layoutDirection);
6868         }
6869         if (thumb != null) {
6870             thumb.setLayoutDirection(layoutDirection);
6871         }
6872 
6873         // Re-apply user/background padding so that scrollbar(s) get added
6874         resolvePadding();
6875     }
6876 
6877     /**
6878      * Defines the vertical scrollbar thumb drawable
6879      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6880      *
6881      * @see #awakenScrollBars(int)
6882      * @see #isVerticalScrollBarEnabled()
6883      * @see #setVerticalScrollBarEnabled(boolean)
6884      */
6885     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6886         initializeScrollBarDrawable();
6887         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
6888     }
6889 
6890     /**
6891      * Defines the vertical scrollbar track drawable
6892      * @attr ref android.R.styleable#View_scrollbarTrackVertical
6893      *
6894      * @see #awakenScrollBars(int)
6895      * @see #isVerticalScrollBarEnabled()
6896      * @see #setVerticalScrollBarEnabled(boolean)
6897      */
6898     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6899         initializeScrollBarDrawable();
6900         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
6901     }
6902 
6903     /**
6904      * Defines the horizontal thumb drawable
6905      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
6906      *
6907      * @see #awakenScrollBars(int)
6908      * @see #isHorizontalScrollBarEnabled()
6909      * @see #setHorizontalScrollBarEnabled(boolean)
6910      */
6911     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6912         initializeScrollBarDrawable();
6913         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
6914     }
6915 
6916     /**
6917      * Defines the horizontal track drawable
6918      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
6919      *
6920      * @see #awakenScrollBars(int)
6921      * @see #isHorizontalScrollBarEnabled()
6922      * @see #setHorizontalScrollBarEnabled(boolean)
6923      */
6924     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6925         initializeScrollBarDrawable();
6926         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
6927     }
6928 
6929     /**
6930      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
6931      * exists, null otherwise.
6932      *
6933      * @see #awakenScrollBars(int)
6934      * @see #isVerticalScrollBarEnabled()
6935      * @see #setVerticalScrollBarEnabled(boolean)
6936      */
6937     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
6938         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
6939     }
6940 
6941     /**
6942      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
6943      * exists, null otherwise.
6944      *
6945      * @see #awakenScrollBars(int)
6946      * @see #isVerticalScrollBarEnabled()
6947      * @see #setVerticalScrollBarEnabled(boolean)
6948      */
6949     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
6950         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
6951     }
6952 
6953     /**
6954      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
6955      * exists, null otherwise.
6956      *
6957      * @see #awakenScrollBars(int)
6958      * @see #isHorizontalScrollBarEnabled()
6959      * @see #setHorizontalScrollBarEnabled(boolean)
6960      */
6961     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
6962         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
6963     }
6964 
6965     /**
6966      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
6967      * exists, null otherwise.
6968      *
6969      * @see #awakenScrollBars(int)
6970      * @see #isHorizontalScrollBarEnabled()
6971      * @see #setHorizontalScrollBarEnabled(boolean)
6972      */
6973     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
6974         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
6975     }
6976 
6977     private void initializeScrollIndicatorsInternal() {
6978         // Some day maybe we'll break this into top/left/start/etc. and let the
6979         // client control it. Until then, you can have any scroll indicator you
6980         // want as long as it's a 1dp foreground-colored rectangle.
6981         if (mScrollIndicatorDrawable == null) {
6982             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6983         }
6984     }
6985 
6986     /**
6987      * <p>
6988      * Initalizes the scrollability cache if necessary.
6989      * </p>
6990      */
6991     private void initScrollCache() {
6992         if (mScrollCache == null) {
6993             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6994         }
6995     }
6996 
6997     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
6998     private ScrollabilityCache getScrollCache() {
6999         initScrollCache();
7000         return mScrollCache;
7001     }
7002 
7003     /**
7004      * Set the position of the vertical scroll bar. Should be one of
7005      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
7006      * {@link #SCROLLBAR_POSITION_RIGHT}.
7007      *
7008      * @param position Where the vertical scroll bar should be positioned.
7009      */
7010     public void setVerticalScrollbarPosition(int position) {
7011         if (mVerticalScrollbarPosition != position) {
7012             mVerticalScrollbarPosition = position;
7013             computeOpaqueFlags();
7014             resolvePadding();
7015         }
7016     }
7017 
7018     /**
7019      * @return The position where the vertical scroll bar will show, if applicable.
7020      * @see #setVerticalScrollbarPosition(int)
7021      */
7022     public int getVerticalScrollbarPosition() {
7023         return mVerticalScrollbarPosition;
7024     }
7025 
7026     boolean isOnScrollbar(float x, float y) {
7027         if (mScrollCache == null) {
7028             return false;
7029         }
7030         x += getScrollX();
7031         y += getScrollY();
7032         final boolean canScrollVertically =
7033                 computeVerticalScrollRange() > computeVerticalScrollExtent();
7034         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
7035             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7036             getVerticalScrollBarBounds(null, touchBounds);
7037             if (touchBounds.contains((int) x, (int) y)) {
7038                 return true;
7039             }
7040         }
7041         final boolean canScrollHorizontally =
7042                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
7043         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
7044             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7045             getHorizontalScrollBarBounds(null, touchBounds);
7046             if (touchBounds.contains((int) x, (int) y)) {
7047                 return true;
7048             }
7049         }
7050         return false;
7051     }
7052 
7053     @UnsupportedAppUsage
7054     boolean isOnScrollbarThumb(float x, float y) {
7055         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
7056     }
7057 
7058     private boolean isOnVerticalScrollbarThumb(float x, float y) {
7059         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
7060             return false;
7061         }
7062         final int range = computeVerticalScrollRange();
7063         final int extent = computeVerticalScrollExtent();
7064         if (range > extent) {
7065             x += getScrollX();
7066             y += getScrollY();
7067             final Rect bounds = mScrollCache.mScrollBarBounds;
7068             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7069             getVerticalScrollBarBounds(bounds, touchBounds);
7070             final int offset = computeVerticalScrollOffset();
7071             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
7072                     extent, range);
7073             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
7074                     extent, range, offset);
7075             final int thumbTop = bounds.top + thumbOffset;
7076             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7077             if (x >= touchBounds.left && x <= touchBounds.right
7078                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
7079                 return true;
7080             }
7081         }
7082         return false;
7083     }
7084 
7085     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
7086         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
7087             return false;
7088         }
7089         final int range = computeHorizontalScrollRange();
7090         final int extent = computeHorizontalScrollExtent();
7091         if (range > extent) {
7092             x += getScrollX();
7093             y += getScrollY();
7094             final Rect bounds = mScrollCache.mScrollBarBounds;
7095             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7096             getHorizontalScrollBarBounds(bounds, touchBounds);
7097             final int offset = computeHorizontalScrollOffset();
7098 
7099             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
7100                     extent, range);
7101             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7102                     extent, range, offset);
7103             final int thumbLeft = bounds.left + thumbOffset;
7104             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7105             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7106                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7107                 return true;
7108             }
7109         }
7110         return false;
7111     }
7112 
7113     @UnsupportedAppUsage
7114     boolean isDraggingScrollBar() {
7115         return mScrollCache != null
7116                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7117     }
7118 
7119     /**
7120      * Sets the state of all scroll indicators.
7121      * <p>
7122      * See {@link #setScrollIndicators(int, int)} for usage information.
7123      *
7124      * @param indicators a bitmask of indicators that should be enabled, or
7125      *                   {@code 0} to disable all indicators
7126      * @see #setScrollIndicators(int, int)
7127      * @see #getScrollIndicators()
7128      * @attr ref android.R.styleable#View_scrollIndicators
7129      */
7130     @RemotableViewMethod
7131     public void setScrollIndicators(@ScrollIndicators int indicators) {
7132         setScrollIndicators(indicators,
7133                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7134     }
7135 
7136     /**
7137      * Sets the state of the scroll indicators specified by the mask. To change
7138      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7139      * <p>
7140      * When a scroll indicator is enabled, it will be displayed if the view
7141      * can scroll in the direction of the indicator.
7142      * <p>
7143      * Multiple indicator types may be enabled or disabled by passing the
7144      * logical OR of the desired types. If multiple types are specified, they
7145      * will all be set to the same enabled state.
7146      * <p>
7147      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7148      *
7149      * @param indicators the indicator direction, or the logical OR of multiple
7150      *             indicator directions. One or more of:
7151      *             <ul>
7152      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7153      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7154      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7155      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7156      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7157      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7158      *             </ul>
7159      * @see #setScrollIndicators(int)
7160      * @see #getScrollIndicators()
7161      * @attr ref android.R.styleable#View_scrollIndicators
7162      */
7163     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7164         // Shift and sanitize mask.
7165         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7166         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7167 
7168         // Shift and mask indicators.
7169         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7170         indicators &= mask;
7171 
7172         // Merge with non-masked flags.
7173         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7174 
7175         if (mPrivateFlags3 != updatedFlags) {
7176             mPrivateFlags3 = updatedFlags;
7177 
7178             if (indicators != 0) {
7179                 initializeScrollIndicatorsInternal();
7180             }
7181             invalidate();
7182         }
7183     }
7184 
7185     /**
7186      * Returns a bitmask representing the enabled scroll indicators.
7187      * <p>
7188      * For example, if the top and left scroll indicators are enabled and all
7189      * other indicators are disabled, the return value will be
7190      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7191      * <p>
7192      * To check whether the bottom scroll indicator is enabled, use the value
7193      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7194      *
7195      * @return a bitmask representing the enabled scroll indicators
7196      */
7197     @InspectableProperty(flagMapping = {
7198             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7199             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7200             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7201             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7202             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7203             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7204             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7205     })
7206     @ScrollIndicators
7207     public int getScrollIndicators() {
7208         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7209                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7210     }
7211 
7212     @UnsupportedAppUsage
7213     ListenerInfo getListenerInfo() {
7214         if (mListenerInfo != null) {
7215             return mListenerInfo;
7216         }
7217         mListenerInfo = new ListenerInfo();
7218         return mListenerInfo;
7219     }
7220 
7221     /**
7222      * Register a callback to be invoked when the scroll X or Y positions of
7223      * this view change.
7224      * <p>
7225      * <b>Note:</b> Some views handle scrolling independently from View and may
7226      * have their own separate listeners for scroll-type events. For example,
7227      * {@link android.widget.ListView ListView} allows clients to register an
7228      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7229      * to listen for changes in list scroll position.
7230      *
7231      * @param l The listener to notify when the scroll X or Y position changes.
7232      * @see android.view.View#getScrollX()
7233      * @see android.view.View#getScrollY()
7234      */
7235     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7236         getListenerInfo().mOnScrollChangeListener = l;
7237     }
7238 
7239     /**
7240      * Register a callback to be invoked when focus of this view changed.
7241      *
7242      * @param l The callback that will run.
7243      */
7244     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7245         getListenerInfo().mOnFocusChangeListener = l;
7246     }
7247 
7248     /**
7249      * Add a listener that will be called when the bounds of the view change due to
7250      * layout processing.
7251      *
7252      * @param listener The listener that will be called when layout bounds change.
7253      */
7254     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7255         ListenerInfo li = getListenerInfo();
7256         if (li.mOnLayoutChangeListeners == null) {
7257             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7258         }
7259         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7260             li.mOnLayoutChangeListeners.add(listener);
7261         }
7262     }
7263 
7264     /**
7265      * Remove a listener for layout changes.
7266      *
7267      * @param listener The listener for layout bounds change.
7268      */
7269     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7270         ListenerInfo li = mListenerInfo;
7271         if (li == null || li.mOnLayoutChangeListeners == null) {
7272             return;
7273         }
7274         li.mOnLayoutChangeListeners.remove(listener);
7275     }
7276 
7277     /**
7278      * Add a listener for attach state changes.
7279      *
7280      * This listener will be called whenever this view is attached or detached
7281      * from a window. Remove the listener using
7282      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7283      *
7284      * @param listener Listener to attach
7285      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7286      */
7287     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7288         ListenerInfo li = getListenerInfo();
7289         if (li.mOnAttachStateChangeListeners == null) {
7290             li.mOnAttachStateChangeListeners
7291                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7292         }
7293         li.mOnAttachStateChangeListeners.add(listener);
7294     }
7295 
7296     /**
7297      * Remove a listener for attach state changes. The listener will receive no further
7298      * notification of window attach/detach events.
7299      *
7300      * @param listener Listener to remove
7301      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7302      */
7303     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7304         ListenerInfo li = mListenerInfo;
7305         if (li == null || li.mOnAttachStateChangeListeners == null) {
7306             return;
7307         }
7308         li.mOnAttachStateChangeListeners.remove(listener);
7309     }
7310 
7311     /**
7312      * Returns the focus-change callback registered for this view.
7313      *
7314      * @return The callback, or null if one is not registered.
7315      */
7316     public OnFocusChangeListener getOnFocusChangeListener() {
7317         ListenerInfo li = mListenerInfo;
7318         return li != null ? li.mOnFocusChangeListener : null;
7319     }
7320 
7321     /**
7322      * Register a callback to be invoked when this view is clicked. If this view is not
7323      * clickable, it becomes clickable.
7324      *
7325      * @param l The callback that will run
7326      *
7327      * @see #setClickable(boolean)
7328      */
7329     public void setOnClickListener(@Nullable OnClickListener l) {
7330         if (!isClickable()) {
7331             setClickable(true);
7332         }
7333         getListenerInfo().mOnClickListener = l;
7334     }
7335 
7336     /**
7337      * Return whether this view has an attached OnClickListener.  Returns
7338      * true if there is a listener, false if there is none.
7339      */
7340     public boolean hasOnClickListeners() {
7341         ListenerInfo li = mListenerInfo;
7342         return (li != null && li.mOnClickListener != null);
7343     }
7344 
7345     /**
7346      * Register a callback to be invoked when this view is clicked and held. If this view is not
7347      * long clickable, it becomes long clickable.
7348      *
7349      * @param l The callback that will run
7350      *
7351      * @see #setLongClickable(boolean)
7352      */
7353     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7354         if (!isLongClickable()) {
7355             setLongClickable(true);
7356         }
7357         getListenerInfo().mOnLongClickListener = l;
7358     }
7359 
7360     /**
7361      * Return whether this view has an attached OnLongClickListener.  Returns
7362      * true if there is a listener, false if there is none.
7363      */
7364     public boolean hasOnLongClickListeners() {
7365         ListenerInfo li = mListenerInfo;
7366         return (li != null && li.mOnLongClickListener != null);
7367     }
7368 
7369     /**
7370      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7371      * @hide
7372      */
7373     @Nullable
7374     public OnLongClickListener getOnLongClickListener() {
7375         ListenerInfo li = mListenerInfo;
7376         return (li != null) ? li.mOnLongClickListener : null;
7377     }
7378 
7379     /**
7380      * Register a callback to be invoked when this view is context clicked. If the view is not
7381      * context clickable, it becomes context clickable.
7382      *
7383      * @param l The callback that will run
7384      * @see #setContextClickable(boolean)
7385      */
7386     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7387         if (!isContextClickable()) {
7388             setContextClickable(true);
7389         }
7390         getListenerInfo().mOnContextClickListener = l;
7391     }
7392 
7393     /**
7394      * Register a callback to be invoked when the context menu for this view is
7395      * being built. If this view is not long clickable, it becomes long clickable.
7396      *
7397      * @param l The callback that will run
7398      *
7399      */
7400     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7401         if (!isLongClickable()) {
7402             setLongClickable(true);
7403         }
7404         getListenerInfo().mOnCreateContextMenuListener = l;
7405     }
7406 
7407     /**
7408      * Set an observer to collect stats for each frame rendered for this view.
7409      *
7410      * @hide
7411      */
7412     public void addFrameMetricsListener(Window window,
7413             Window.OnFrameMetricsAvailableListener listener,
7414             Handler handler) {
7415         if (mAttachInfo != null) {
7416             if (mAttachInfo.mThreadedRenderer != null) {
7417                 if (mFrameMetricsObservers == null) {
7418                     mFrameMetricsObservers = new ArrayList<>();
7419                 }
7420 
7421                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7422                 mFrameMetricsObservers.add(fmo);
7423                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7424             } else {
7425                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7426             }
7427         } else {
7428             if (mFrameMetricsObservers == null) {
7429                 mFrameMetricsObservers = new ArrayList<>();
7430             }
7431 
7432             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7433             mFrameMetricsObservers.add(fmo);
7434         }
7435     }
7436 
7437     /**
7438      * Remove observer configured to collect frame stats for this view.
7439      *
7440      * @hide
7441      */
7442     public void removeFrameMetricsListener(
7443             Window.OnFrameMetricsAvailableListener listener) {
7444         ThreadedRenderer renderer = getThreadedRenderer();
7445         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7446         if (fmo == null) {
7447             throw new IllegalArgumentException(
7448                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7449         }
7450 
7451         if (mFrameMetricsObservers != null) {
7452             mFrameMetricsObservers.remove(fmo);
7453             if (renderer != null) {
7454                 renderer.removeObserver(fmo.getRendererObserver());
7455             }
7456         }
7457     }
7458 
7459     private void registerPendingFrameMetricsObservers() {
7460         if (mFrameMetricsObservers != null) {
7461             ThreadedRenderer renderer = getThreadedRenderer();
7462             if (renderer != null) {
7463                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7464                     renderer.addObserver(fmo.getRendererObserver());
7465                 }
7466             } else {
7467                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7468             }
7469         }
7470     }
7471 
7472     private FrameMetricsObserver findFrameMetricsObserver(
7473             Window.OnFrameMetricsAvailableListener listener) {
7474         if (mFrameMetricsObservers != null) {
7475             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7476                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7477                 if (observer.mListener == listener) {
7478                     return observer;
7479                 }
7480             }
7481         }
7482 
7483         return null;
7484     }
7485 
7486     /** @hide */
7487     public void setNotifyAutofillManagerOnClick(boolean notify) {
7488         if (notify) {
7489             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7490         } else {
7491             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7492         }
7493     }
7494 
7495     private void notifyAutofillManagerOnClick() {
7496         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7497             try {
7498                 getAutofillManager().notifyViewClicked(this);
7499             } finally {
7500                 // Set it to already called so it's not called twice when called by
7501                 // performClickInternal()
7502                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7503             }
7504         }
7505     }
7506 
7507     /**
7508      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7509      * {@code performClick()} directly to make sure the autofill manager is notified when
7510      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7511      * method).
7512      */
7513     private boolean performClickInternal() {
7514         // Must notify autofill manager before performing the click actions to avoid scenarios where
7515         // the app has a click listener that changes the state of views the autofill service might
7516         // be interested on.
7517         notifyAutofillManagerOnClick();
7518 
7519         return performClick();
7520     }
7521 
7522     /**
7523      * Call this view's OnClickListener, if it is defined.  Performs all normal
7524      * actions associated with clicking: reporting accessibility event, playing
7525      * a sound, etc.
7526      *
7527      * @return True there was an assigned OnClickListener that was called, false
7528      *         otherwise is returned.
7529      */
7530     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7531     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7532     // could extend this method without calling super.performClick()).
7533     public boolean performClick() {
7534         // We still need to call this method to handle the cases where performClick() was called
7535         // externally, instead of through performClickInternal()
7536         notifyAutofillManagerOnClick();
7537 
7538         final boolean result;
7539         final ListenerInfo li = mListenerInfo;
7540         if (li != null && li.mOnClickListener != null) {
7541             playSoundEffect(SoundEffectConstants.CLICK);
7542             li.mOnClickListener.onClick(this);
7543             result = true;
7544         } else {
7545             result = false;
7546         }
7547 
7548         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7549 
7550         notifyEnterOrExitForAutoFillIfNeeded(true);
7551 
7552         return result;
7553     }
7554 
7555     /**
7556      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7557      * this only calls the listener, and does not do any associated clicking
7558      * actions like reporting an accessibility event.
7559      *
7560      * @return True there was an assigned OnClickListener that was called, false
7561      *         otherwise is returned.
7562      */
7563     public boolean callOnClick() {
7564         ListenerInfo li = mListenerInfo;
7565         if (li != null && li.mOnClickListener != null) {
7566             li.mOnClickListener.onClick(this);
7567             return true;
7568         }
7569         return false;
7570     }
7571 
7572     /**
7573      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7574      * context menu if the OnLongClickListener did not consume the event.
7575      *
7576      * @return {@code true} if one of the above receivers consumed the event,
7577      *         {@code false} otherwise
7578      */
7579     public boolean performLongClick() {
7580         return performLongClickInternal(mLongClickX, mLongClickY);
7581     }
7582 
7583     /**
7584      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7585      * context menu if the OnLongClickListener did not consume the event,
7586      * anchoring it to an (x,y) coordinate.
7587      *
7588      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7589      *          to disable anchoring
7590      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7591      *          to disable anchoring
7592      * @return {@code true} if one of the above receivers consumed the event,
7593      *         {@code false} otherwise
7594      */
7595     public boolean performLongClick(float x, float y) {
7596         mLongClickX = x;
7597         mLongClickY = y;
7598         final boolean handled = performLongClick();
7599         mLongClickX = Float.NaN;
7600         mLongClickY = Float.NaN;
7601         return handled;
7602     }
7603 
7604     /**
7605      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7606      * context menu if the OnLongClickListener did not consume the event,
7607      * optionally anchoring it to an (x,y) coordinate.
7608      *
7609      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7610      *          to disable anchoring
7611      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7612      *          to disable anchoring
7613      * @return {@code true} if one of the above receivers consumed the event,
7614      *         {@code false} otherwise
7615      */
7616     private boolean performLongClickInternal(float x, float y) {
7617         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7618 
7619         boolean handled = false;
7620         final ListenerInfo li = mListenerInfo;
7621         if (li != null && li.mOnLongClickListener != null) {
7622             handled = li.mOnLongClickListener.onLongClick(View.this);
7623         }
7624         if (!handled) {
7625             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7626             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7627         }
7628         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7629             if (!handled) {
7630                 handled = showLongClickTooltip((int) x, (int) y);
7631             }
7632         }
7633         if (handled) {
7634             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7635         }
7636         return handled;
7637     }
7638 
7639     /**
7640      * Call this view's OnContextClickListener, if it is defined.
7641      *
7642      * @param x the x coordinate of the context click
7643      * @param y the y coordinate of the context click
7644      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7645      *         otherwise.
7646      */
7647     public boolean performContextClick(float x, float y) {
7648         return performContextClick();
7649     }
7650 
7651     /**
7652      * Call this view's OnContextClickListener, if it is defined.
7653      *
7654      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7655      *         otherwise.
7656      */
7657     public boolean performContextClick() {
7658         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7659 
7660         boolean handled = false;
7661         ListenerInfo li = mListenerInfo;
7662         if (li != null && li.mOnContextClickListener != null) {
7663             handled = li.mOnContextClickListener.onContextClick(View.this);
7664         }
7665         if (handled) {
7666             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7667         }
7668         return handled;
7669     }
7670 
7671     /**
7672      * Performs button-related actions during a touch down event.
7673      *
7674      * @param event The event.
7675      * @return True if the down was consumed.
7676      *
7677      * @hide
7678      */
7679     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7680         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7681             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7682             showContextMenu(event.getX(), event.getY());
7683             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7684             return true;
7685         }
7686         return false;
7687     }
7688 
7689     /**
7690      * Shows the context menu for this view.
7691      *
7692      * @return {@code true} if the context menu was shown, {@code false}
7693      *         otherwise
7694      * @see #showContextMenu(float, float)
7695      */
7696     public boolean showContextMenu() {
7697         return getParent().showContextMenuForChild(this);
7698     }
7699 
7700     /**
7701      * Shows the context menu for this view anchored to the specified
7702      * view-relative coordinate.
7703      *
7704      * @param x the X coordinate in pixels relative to the view to which the
7705      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7706      * @param y the Y coordinate in pixels relative to the view to which the
7707      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7708      * @return {@code true} if the context menu was shown, {@code false}
7709      *         otherwise
7710      */
7711     public boolean showContextMenu(float x, float y) {
7712         return getParent().showContextMenuForChild(this, x, y);
7713     }
7714 
7715     /**
7716      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7717      *
7718      * @param callback Callback that will control the lifecycle of the action mode
7719      * @return The new action mode if it is started, null otherwise
7720      *
7721      * @see ActionMode
7722      * @see #startActionMode(android.view.ActionMode.Callback, int)
7723      */
7724     public ActionMode startActionMode(ActionMode.Callback callback) {
7725         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7726     }
7727 
7728     /**
7729      * Start an action mode with the given type.
7730      *
7731      * @param callback Callback that will control the lifecycle of the action mode
7732      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7733      * @return The new action mode if it is started, null otherwise
7734      *
7735      * @see ActionMode
7736      */
7737     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7738         ViewParent parent = getParent();
7739         if (parent == null) return null;
7740         try {
7741             return parent.startActionModeForChild(this, callback, type);
7742         } catch (AbstractMethodError ame) {
7743             // Older implementations of custom views might not implement this.
7744             return parent.startActionModeForChild(this, callback);
7745         }
7746     }
7747 
7748     /**
7749      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7750      * Context, creating a unique View identifier to retrieve the result.
7751      *
7752      * @param intent The Intent to be started.
7753      * @param requestCode The request code to use.
7754      * @hide
7755      */
7756     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7757     public void startActivityForResult(Intent intent, int requestCode) {
7758         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7759         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7760     }
7761 
7762     /**
7763      * If this View corresponds to the calling who, dispatches the activity result.
7764      * @param who The identifier for the targeted View to receive the result.
7765      * @param requestCode The integer request code originally supplied to
7766      *                    startActivityForResult(), allowing you to identify who this
7767      *                    result came from.
7768      * @param resultCode The integer result code returned by the child activity
7769      *                   through its setResult().
7770      * @param data An Intent, which can return result data to the caller
7771      *               (various data can be attached to Intent "extras").
7772      * @return {@code true} if the activity result was dispatched.
7773      * @hide
7774      */
7775     public boolean dispatchActivityResult(
7776             String who, int requestCode, int resultCode, Intent data) {
7777         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7778             onActivityResult(requestCode, resultCode, data);
7779             mStartActivityRequestWho = null;
7780             return true;
7781         }
7782         return false;
7783     }
7784 
7785     /**
7786      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7787      *
7788      * @param requestCode The integer request code originally supplied to
7789      *                    startActivityForResult(), allowing you to identify who this
7790      *                    result came from.
7791      * @param resultCode The integer result code returned by the child activity
7792      *                   through its setResult().
7793      * @param data An Intent, which can return result data to the caller
7794      *               (various data can be attached to Intent "extras").
7795      * @hide
7796      */
7797     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7798         // Do nothing.
7799     }
7800 
7801     /**
7802      * Register a callback to be invoked when a hardware key is pressed in this view.
7803      * Key presses in software input methods will generally not trigger the methods of
7804      * this listener.
7805      * @param l the key listener to attach to this view
7806      */
7807     public void setOnKeyListener(OnKeyListener l) {
7808         getListenerInfo().mOnKeyListener = l;
7809     }
7810 
7811     /**
7812      * Register a callback to be invoked when a touch event is sent to this view.
7813      * @param l the touch listener to attach to this view
7814      */
7815     public void setOnTouchListener(OnTouchListener l) {
7816         getListenerInfo().mOnTouchListener = l;
7817     }
7818 
7819     /**
7820      * Register a callback to be invoked when a generic motion event is sent to this view.
7821      * @param l the generic motion listener to attach to this view
7822      */
7823     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7824         getListenerInfo().mOnGenericMotionListener = l;
7825     }
7826 
7827     /**
7828      * Register a callback to be invoked when a hover event is sent to this view.
7829      * @param l the hover listener to attach to this view
7830      */
7831     public void setOnHoverListener(OnHoverListener l) {
7832         getListenerInfo().mOnHoverListener = l;
7833     }
7834 
7835     /**
7836      * Register a drag event listener callback object for this View. The parameter is
7837      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7838      * View, the system calls the
7839      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7840      * @param l An implementation of {@link android.view.View.OnDragListener}.
7841      */
7842     public void setOnDragListener(OnDragListener l) {
7843         getListenerInfo().mOnDragListener = l;
7844     }
7845 
7846     /**
7847      * Give this view focus. This will cause
7848      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7849      *
7850      * Note: this does not check whether this {@link View} should get focus, it just
7851      * gives it focus no matter what.  It should only be called internally by framework
7852      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7853      *
7854      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7855      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7856      *        focus moved when requestFocus() is called. It may not always
7857      *        apply, in which case use the default View.FOCUS_DOWN.
7858      * @param previouslyFocusedRect The rectangle of the view that had focus
7859      *        prior in this View's coordinate system.
7860      */
7861     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7862         if (DBG) {
7863             System.out.println(this + " requestFocus()");
7864         }
7865 
7866         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7867             mPrivateFlags |= PFLAG_FOCUSED;
7868 
7869             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7870 
7871             if (mParent != null) {
7872                 mParent.requestChildFocus(this, this);
7873                 updateFocusedInCluster(oldFocus, direction);
7874             }
7875 
7876             if (mAttachInfo != null) {
7877                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
7878             }
7879 
7880             onFocusChanged(true, direction, previouslyFocusedRect);
7881             refreshDrawableState();
7882         }
7883     }
7884 
7885     /**
7886      * Sets this view's preference for reveal behavior when it gains focus.
7887      *
7888      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
7889      * this view would prefer to be brought fully into view when it gains focus.
7890      * For example, a text field that a user is meant to type into. Other views such
7891      * as scrolling containers may prefer to opt-out of this behavior.</p>
7892      *
7893      * <p>The default value for views is true, though subclasses may change this
7894      * based on their preferred behavior.</p>
7895      *
7896      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
7897      *
7898      * @see #getRevealOnFocusHint()
7899      */
7900     public final void setRevealOnFocusHint(boolean revealOnFocus) {
7901         if (revealOnFocus) {
7902             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
7903         } else {
7904             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
7905         }
7906     }
7907 
7908     /**
7909      * Returns this view's preference for reveal behavior when it gains focus.
7910      *
7911      * <p>When this method returns true for a child view requesting focus, ancestor
7912      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
7913      * should make a best effort to make the newly focused child fully visible to the user.
7914      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
7915      * other properties affecting visibility to the user as part of the focus change.</p>
7916      *
7917      * @return true if this view would prefer to become fully visible when it gains focus,
7918      *         false if it would prefer not to disrupt scroll positioning
7919      *
7920      * @see #setRevealOnFocusHint(boolean)
7921      */
7922     public final boolean getRevealOnFocusHint() {
7923         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
7924     }
7925 
7926     /**
7927      * Populates <code>outRect</code> with the hotspot bounds. By default,
7928      * the hotspot bounds are identical to the screen bounds.
7929      *
7930      * @param outRect rect to populate with hotspot bounds
7931      * @hide Only for internal use by views and widgets.
7932      */
7933     public void getHotspotBounds(Rect outRect) {
7934         final Drawable background = getBackground();
7935         if (background != null) {
7936             background.getHotspotBounds(outRect);
7937         } else {
7938             getBoundsOnScreen(outRect);
7939         }
7940     }
7941 
7942     /**
7943      * Request that a rectangle of this view be visible on the screen,
7944      * scrolling if necessary just enough.
7945      *
7946      * <p>A View should call this if it maintains some notion of which part
7947      * of its content is interesting.  For example, a text editing view
7948      * should call this when its cursor moves.
7949      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7950      * It should not be affected by which part of the View is currently visible or its scroll
7951      * position.
7952      *
7953      * @param rectangle The rectangle in the View's content coordinate space
7954      * @return Whether any parent scrolled.
7955      */
7956     public boolean requestRectangleOnScreen(Rect rectangle) {
7957         return requestRectangleOnScreen(rectangle, false);
7958     }
7959 
7960     /**
7961      * Request that a rectangle of this view be visible on the screen,
7962      * scrolling if necessary just enough.
7963      *
7964      * <p>A View should call this if it maintains some notion of which part
7965      * of its content is interesting.  For example, a text editing view
7966      * should call this when its cursor moves.
7967      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7968      * It should not be affected by which part of the View is currently visible or its scroll
7969      * position.
7970      * <p>When <code>immediate</code> is set to true, scrolling will not be
7971      * animated.
7972      *
7973      * @param rectangle The rectangle in the View's content coordinate space
7974      * @param immediate True to forbid animated scrolling, false otherwise
7975      * @return Whether any parent scrolled.
7976      */
7977     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7978         if (mParent == null) {
7979             return false;
7980         }
7981 
7982         View child = this;
7983 
7984         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7985         position.set(rectangle);
7986 
7987         ViewParent parent = mParent;
7988         boolean scrolled = false;
7989         while (parent != null) {
7990             rectangle.set((int) position.left, (int) position.top,
7991                     (int) position.right, (int) position.bottom);
7992 
7993             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7994 
7995             if (!(parent instanceof View)) {
7996                 break;
7997             }
7998 
7999             // move it from child's content coordinate space to parent's content coordinate space
8000             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
8001 
8002             child = (View) parent;
8003             parent = child.getParent();
8004         }
8005 
8006         return scrolled;
8007     }
8008 
8009     /**
8010      * Called when this view wants to give up focus. If focus is cleared
8011      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
8012      * <p>
8013      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
8014      * to the first focusable View from the top after focus is cleared. Hence, if this
8015      * View is the first from the top that can take focus, then all callbacks
8016      * related to clearing focus will be invoked after which the framework will
8017      * give focus to this view.
8018      * </p>
8019      */
8020     public void clearFocus() {
8021         if (DBG) {
8022             System.out.println(this + " clearFocus()");
8023         }
8024 
8025         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
8026         clearFocusInternal(null, true, refocus);
8027     }
8028 
8029     /**
8030      * Clears focus from the view, optionally propagating the change up through
8031      * the parent hierarchy and requesting that the root view place new focus.
8032      *
8033      * @param propagate whether to propagate the change up through the parent
8034      *            hierarchy
8035      * @param refocus when propagate is true, specifies whether to request the
8036      *            root view place new focus
8037      */
8038     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
8039         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
8040             mPrivateFlags &= ~PFLAG_FOCUSED;
8041             clearParentsWantFocus();
8042 
8043             if (propagate && mParent != null) {
8044                 mParent.clearChildFocus(this);
8045             }
8046 
8047             onFocusChanged(false, 0, null);
8048             refreshDrawableState();
8049 
8050             if (propagate && (!refocus || !rootViewRequestFocus())) {
8051                 notifyGlobalFocusCleared(this);
8052             }
8053         }
8054     }
8055 
8056     void notifyGlobalFocusCleared(View oldFocus) {
8057         if (oldFocus != null && mAttachInfo != null) {
8058             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
8059         }
8060     }
8061 
8062     boolean rootViewRequestFocus() {
8063         final View root = getRootView();
8064         return root != null && root.requestFocus();
8065     }
8066 
8067     /**
8068      * Called internally by the view system when a new view is getting focus.
8069      * This is what clears the old focus.
8070      * <p>
8071      * <b>NOTE:</b> The parent view's focused child must be updated manually
8072      * after calling this method. Otherwise, the view hierarchy may be left in
8073      * an inconstent state.
8074      */
8075     void unFocus(View focused) {
8076         if (DBG) {
8077             System.out.println(this + " unFocus()");
8078         }
8079 
8080         clearFocusInternal(focused, false, false);
8081     }
8082 
8083     /**
8084      * Returns true if this view has focus itself, or is the ancestor of the
8085      * view that has focus.
8086      *
8087      * @return True if this view has or contains focus, false otherwise.
8088      */
8089     @ViewDebug.ExportedProperty(category = "focus")
8090     public boolean hasFocus() {
8091         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8092     }
8093 
8094     /**
8095      * Returns true if this view is focusable or if it contains a reachable View
8096      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
8097      * is a view whose parents do not block descendants focus.
8098      * Only {@link #VISIBLE} views are considered focusable.
8099      *
8100      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8101      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8102      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8103      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8104      * {@code false} for views not explicitly marked as focusable.
8105      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8106      * behavior.</p>
8107      *
8108      * @return {@code true} if the view is focusable or if the view contains a focusable
8109      *         view, {@code false} otherwise
8110      *
8111      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8112      * @see ViewGroup#getTouchscreenBlocksFocus()
8113      * @see #hasExplicitFocusable()
8114      */
8115     public boolean hasFocusable() {
8116         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8117     }
8118 
8119     /**
8120      * Returns true if this view is focusable or if it contains a reachable View
8121      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8122      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8123      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8124      * {@link #FOCUSABLE} are considered focusable.
8125      *
8126      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8127      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8128      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8129      * to focusable will not.</p>
8130      *
8131      * @return {@code true} if the view is focusable or if the view contains a focusable
8132      *         view, {@code false} otherwise
8133      *
8134      * @see #hasFocusable()
8135      */
8136     public boolean hasExplicitFocusable() {
8137         return hasFocusable(false, true);
8138     }
8139 
8140     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8141         if (!isFocusableInTouchMode()) {
8142             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8143                 final ViewGroup g = (ViewGroup) p;
8144                 if (g.shouldBlockFocusForTouchscreen()) {
8145                     return false;
8146                 }
8147             }
8148         }
8149 
8150         // Invisible, gone, or disabled views are never focusable.
8151         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8152                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8153             return false;
8154         }
8155 
8156         // Only use effective focusable value when allowed.
8157         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8158             return true;
8159         }
8160 
8161         return false;
8162     }
8163 
8164     /**
8165      * Called by the view system when the focus state of this view changes.
8166      * When the focus change event is caused by directional navigation, direction
8167      * and previouslyFocusedRect provide insight into where the focus is coming from.
8168      * When overriding, be sure to call up through to the super class so that
8169      * the standard focus handling will occur.
8170      *
8171      * @param gainFocus True if the View has focus; false otherwise.
8172      * @param direction The direction focus has moved when requestFocus()
8173      *                  is called to give this view focus. Values are
8174      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8175      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8176      *                  It may not always apply, in which case use the default.
8177      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8178      *        system, of the previously focused view.  If applicable, this will be
8179      *        passed in as finer grained information about where the focus is coming
8180      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8181      */
8182     @CallSuper
8183     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8184             @Nullable Rect previouslyFocusedRect) {
8185         if (gainFocus) {
8186             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8187         } else {
8188             notifyViewAccessibilityStateChangedIfNeeded(
8189                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8190         }
8191 
8192         // Here we check whether we still need the default focus highlight, and switch it on/off.
8193         switchDefaultFocusHighlight();
8194 
8195         if (!gainFocus) {
8196             if (isPressed()) {
8197                 setPressed(false);
8198             }
8199             if (hasWindowFocus()) {
8200                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8201             }
8202             onFocusLost();
8203         } else if (hasWindowFocus()) {
8204             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8205         }
8206 
8207         invalidate(true);
8208         ListenerInfo li = mListenerInfo;
8209         if (li != null && li.mOnFocusChangeListener != null) {
8210             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8211         }
8212 
8213         if (mAttachInfo != null) {
8214             mAttachInfo.mKeyDispatchState.reset(this);
8215         }
8216 
8217         if (mParent != null) {
8218             mParent.onDescendantUnbufferedRequested();
8219         }
8220 
8221         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8222         updatePreferKeepClearForFocus();
8223     }
8224 
8225     /**
8226      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8227      *
8228      * @param hasFocus {@code true} when the {@link View} is being focused.
8229      */
8230     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8231         if (mAttachInfo == null) {
8232             return;
8233         }
8234         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8235     }
8236 
8237     /** @hide */
8238     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8239         if (canNotifyAutofillEnterExitEvent()) {
8240             AutofillManager afm = getAutofillManager();
8241             if (afm != null) {
8242                 if (enter) {
8243                     // We have not been laid out yet, hence cannot evaluate
8244                     // whether this view is visible to the user, we will do
8245                     // the evaluation once layout is complete.
8246                     // Sometimes, views are already laid out, but it's still
8247                     // not visible to the user, we also do the evaluation once
8248                     // the view is visible. ex: There is a fade-in animation
8249                     // for the activity, the view will be laid out when the
8250                     // animation beginning. On the time, the view is not visible
8251                     // to the user. And then as the animation progresses, the view
8252                     // becomes visible to the user.
8253                     if (!isLaidOut() || !isVisibleToUser()) {
8254                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8255                     } else if (isVisibleToUser()) {
8256                         if (isFocused()) {
8257                             // TODO This is a potential problem that View gets focus before it's
8258                             // visible to User. Ideally View should handle the event when
8259                             // isVisibleToUser() becomes true where it should issue
8260                             // notifyViewEntered().
8261                             afm.notifyViewEntered(this);
8262                         } else {
8263                             afm.notifyViewEnteredForFillDialog(this);
8264                         }
8265                     }
8266                 } else if (!isFocused()) {
8267                     afm.notifyViewExited(this);
8268                 }
8269             }
8270         }
8271     }
8272 
8273     /**
8274      * Visually distinct portion of a window with window-like semantics are considered panes for
8275      * accessibility purposes. One example is the content view of a fragment that is replaced.
8276      * In order for accessibility services to understand a pane's window-like behavior, panes
8277      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
8278      * when they appear, disappear, or change title.
8279      *
8280      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8281      *                               View is not a pane.
8282      *
8283      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8284      *
8285      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8286      */
8287     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8288         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8289             boolean currentPaneTitleEmpty = mAccessibilityPaneTitle == null;
8290             boolean newPaneTitleEmpty =  accessibilityPaneTitle == null;
8291             mAccessibilityPaneTitle = accessibilityPaneTitle;
8292             // Make explicitly important as nulled titles need to be important for DISAPPEARED
8293             // events.
8294             if (mAccessibilityPaneTitle != null
8295                     && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8296                 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8297             }
8298             if (currentPaneTitleEmpty) {
8299                 notifyViewAccessibilityStateChangedIfNeeded(
8300                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED);
8301             } else if (newPaneTitleEmpty) {
8302                 notifyViewAccessibilityStateChangedIfNeeded(
8303                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
8304             } else {
8305                 notifyViewAccessibilityStateChangedIfNeeded(
8306                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8307             }
8308         }
8309     }
8310 
8311     /**
8312      * Get the title of the pane for purposes of accessibility.
8313      *
8314      * @return The current pane title.
8315      *
8316      * {@see #setAccessibilityPaneTitle}.
8317      *
8318      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8319      */
8320     @InspectableProperty
8321     @Nullable
8322     public CharSequence getAccessibilityPaneTitle() {
8323         return mAccessibilityPaneTitle;
8324     }
8325 
8326     private boolean isAccessibilityPane() {
8327         return mAccessibilityPaneTitle != null;
8328     }
8329 
8330     /**
8331      * Sends an accessibility event of the given type. If accessibility is
8332      * not enabled this method has no effect. The default implementation calls
8333      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8334      * to populate information about the event source (this View), then calls
8335      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8336      * populate the text content of the event source including its descendants,
8337      * then for events type {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
8338      * and {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} with
8339      * subtype {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION},
8340      * throttle the events, and last calls
8341      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8342      * on its parent to request sending of the event to interested parties.
8343      * <p>
8344      * If an {@link AccessibilityDelegate} has been specified via calling
8345      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8346      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8347      * responsible for handling this call.
8348      * </p>
8349      * <p>
8350      * If this view uses {@link AccessibilityNodeProvider} to provide virtual view hierarchy rooted
8351      * at this view, this method should not be called to send events from virtual children because
8352      * it will populate the events with wrong information and the events should be throttled per
8353      * child instead at the virtual root level. To send events from virtual children, call
8354      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} on the view's
8355      * parent to request sending of the event to interested parties.
8356      * </p>
8357      *
8358      * @param eventType The type of the event to send, as defined by several types from
8359      * {@link AccessibilityEvent}, such as
8360      * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} or
8361      * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8362      *
8363      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8364      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8365      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8366      * @see AccessibilityDelegate
8367      */
8368     public void sendAccessibilityEvent(int eventType) {
8369         if (mAccessibilityDelegate != null) {
8370             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8371         } else {
8372             sendAccessibilityEventInternal(eventType);
8373         }
8374     }
8375 
8376     /**
8377      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8378      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8379      * specified text to its users.
8380      * <p>
8381      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8382      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8383      * accurately supplying the semantics of their UI.
8384      * They should not need to specify what exactly is announced to users.
8385      *
8386      * @param text The announcement text.
8387      */
8388     public void announceForAccessibility(CharSequence text) {
8389         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8390             AccessibilityEvent event = AccessibilityEvent.obtain(
8391                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8392             onInitializeAccessibilityEvent(event);
8393             event.getText().add(text);
8394             event.setContentDescription(null);
8395             mParent.requestSendAccessibilityEvent(this, event);
8396         }
8397     }
8398 
8399     /**
8400      * @see #sendAccessibilityEvent(int)
8401      *
8402      * Note: Called from the default {@link AccessibilityDelegate}.
8403      *
8404      * @hide
8405      */
8406     public void sendAccessibilityEventInternal(int eventType) {
8407         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8408             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8409         }
8410     }
8411 
8412     /**
8413      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8414      * takes as an argument an empty {@link AccessibilityEvent} and does not
8415      * perform a check whether accessibility is enabled.
8416      * <p>
8417      * If an {@link AccessibilityDelegate} has been specified via calling
8418      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8419      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8420      * is responsible for handling this call.
8421      * </p>
8422      *
8423      * @param event The event to send.
8424      *
8425      * @see #sendAccessibilityEvent(int)
8426      */
8427     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8428         if (mAccessibilityDelegate != null) {
8429             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8430         } else {
8431             sendAccessibilityEventUncheckedInternal(event);
8432         }
8433     }
8434 
8435     /**
8436      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8437      *
8438      * Note: Called from the default {@link AccessibilityDelegate}.
8439      *
8440      * @hide
8441      */
8442     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8443         // Panes disappearing are relevant even if though the view is no longer visible.
8444         boolean isWindowStateChanged =
8445                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8446         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8447                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8448         boolean detached = detached();
8449         if (!isShown() && !isWindowDisappearedEvent && !detached) {
8450             return;
8451         }
8452         onInitializeAccessibilityEvent(event);
8453         // Only a subset of accessibility events populates text content.
8454         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8455             dispatchPopulateAccessibilityEvent(event);
8456         }
8457         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
8458         if (throttle != null) {
8459             throttle.post(event);
8460         } else if (!isWindowDisappearedEvent && detached) {
8461             // Views could be attached soon later. Accessibility events during this temporarily
8462             // detached period should be sent too.
8463             postDelayed(() -> {
8464                 if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
8465                     requestParentSendAccessibilityEvent(event);
8466                 }
8467             }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8468         } else {
8469             requestParentSendAccessibilityEvent(event);
8470         }
8471     }
8472 
8473     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
8474         ViewParent parent = getParent();
8475         if (parent != null) {
8476             getParent().requestSendAccessibilityEvent(this, event);
8477         }
8478     }
8479 
8480     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
8481             AccessibilityEvent event) {
8482         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
8483             if (mSendViewScrolledAccessibilityEvent == null) {
8484                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8485             }
8486             return mSendViewScrolledAccessibilityEvent;
8487         }
8488         boolean isStateContentChanged = (event.getContentChangeTypes()
8489                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
8490         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
8491                 && isStateContentChanged) {
8492             if (mSendStateChangedAccessibilityEvent == null) {
8493                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
8494             }
8495             return mSendStateChangedAccessibilityEvent;
8496         }
8497         return null;
8498     }
8499 
8500     private void clearAccessibilityThrottles() {
8501         cancel(mSendViewScrolledAccessibilityEvent);
8502         cancel(mSendStateChangedAccessibilityEvent);
8503     }
8504 
8505     /**
8506      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8507      * to its children for adding their text content to the event. Note that the
8508      * event text is populated in a separate dispatch path since we add to the
8509      * event not only the text of the source but also the text of all its descendants.
8510      * A typical implementation will call
8511      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8512      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8513      * on each child. Override this method if custom population of the event text
8514      * content is required.
8515      * <p>
8516      * If an {@link AccessibilityDelegate} has been specified via calling
8517      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8518      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8519      * is responsible for handling this call.
8520      * </p>
8521      * <p>
8522      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8523      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8524      * </p>
8525      *
8526      * @param event The event.
8527      *
8528      * @return True if the event population was completed.
8529      */
8530     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8531         if (mAccessibilityDelegate != null) {
8532             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8533         } else {
8534             return dispatchPopulateAccessibilityEventInternal(event);
8535         }
8536     }
8537 
8538     /**
8539      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8540      *
8541      * Note: Called from the default {@link AccessibilityDelegate}.
8542      *
8543      * @hide
8544      */
8545     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8546         onPopulateAccessibilityEvent(event);
8547         return false;
8548     }
8549 
8550     /**
8551      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8552      * giving a chance to this View to populate the accessibility event with its
8553      * text content. While this method is free to modify event
8554      * attributes other than text content, doing so should normally be performed in
8555      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8556      * <p>
8557      * Example: Adding formatted date string to an accessibility event in addition
8558      *          to the text added by the super implementation:
8559      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8560      *     super.onPopulateAccessibilityEvent(event);
8561      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8562      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8563      *         mCurrentDate.getTimeInMillis(), flags);
8564      *     event.getText().add(selectedDateUtterance);
8565      * }</pre>
8566      * <p>
8567      * If an {@link AccessibilityDelegate} has been specified via calling
8568      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8569      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8570      * is responsible for handling this call.
8571      * </p>
8572      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8573      * information to the event, in case the default implementation has basic information to add.
8574      * </p>
8575      *
8576      * @param event The accessibility event which to populate.
8577      *
8578      * @see #sendAccessibilityEvent(int)
8579      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8580      */
8581     @CallSuper
8582     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8583         if (mAccessibilityDelegate != null) {
8584             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8585         } else {
8586             onPopulateAccessibilityEventInternal(event);
8587         }
8588     }
8589 
8590     /**
8591      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8592      *
8593      * Note: Called from the default {@link AccessibilityDelegate}.
8594      *
8595      * @hide
8596      */
8597     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8598         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8599                 && isAccessibilityPane()) {
8600             event.getText().add(getAccessibilityPaneTitle());
8601         }
8602     }
8603 
8604     /**
8605      * Initializes an {@link AccessibilityEvent} with information about
8606      * this View which is the event source. In other words, the source of
8607      * an accessibility event is the view whose state change triggered firing
8608      * the event.
8609      * <p>
8610      * Example: Setting the password property of an event in addition
8611      *          to properties set by the super implementation:
8612      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8613      *     super.onInitializeAccessibilityEvent(event);
8614      *     event.setPassword(true);
8615      * }</pre>
8616      * <p>
8617      * If an {@link AccessibilityDelegate} has been specified via calling
8618      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8619      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8620      * is responsible for handling this call.
8621      * </p>
8622      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8623      * information to the event, in case the default implementation has basic information to add.
8624      * </p>
8625      * @param event The event to initialize.
8626      *
8627      * @see #sendAccessibilityEvent(int)
8628      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8629      */
8630     @CallSuper
8631     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8632         if (mAccessibilityDelegate != null) {
8633             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8634         } else {
8635             onInitializeAccessibilityEventInternal(event);
8636         }
8637     }
8638 
8639     /**
8640      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8641      *
8642      * Note: Called from the default {@link AccessibilityDelegate}.
8643      *
8644      * @hide
8645      */
8646     @UnsupportedAppUsage
8647     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8648         event.setSource(this);
8649         event.setClassName(getAccessibilityClassName());
8650         event.setPackageName(getContext().getPackageName());
8651         event.setEnabled(isEnabled());
8652         event.setContentDescription(mContentDescription);
8653         event.setScrollX(getScrollX());
8654         event.setScrollY(getScrollY());
8655 
8656         switch (event.getEventType()) {
8657             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8658                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8659                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8660                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8661                 event.setItemCount(focusablesTempList.size());
8662                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8663                 if (mAttachInfo != null) {
8664                     focusablesTempList.clear();
8665                 }
8666             } break;
8667             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8668                 CharSequence text = getIterableTextForAccessibility();
8669                 if (text != null && text.length() > 0) {
8670                     event.setFromIndex(getAccessibilitySelectionStart());
8671                     event.setToIndex(getAccessibilitySelectionEnd());
8672                     event.setItemCount(text.length());
8673                 }
8674             } break;
8675         }
8676     }
8677 
8678     /**
8679      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8680      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8681      * This method is responsible for obtaining an accessibility node info from a
8682      * pool of reusable instances and calling
8683      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8684      * initialize the former.
8685      * <p>
8686      * Note: The client is responsible for recycling the obtained instance by calling
8687      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8688      * </p>
8689      *
8690      * @return A populated {@link AccessibilityNodeInfo}.
8691      *
8692      * @see AccessibilityNodeInfo
8693      */
8694     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8695         if (mAccessibilityDelegate != null) {
8696             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8697         } else {
8698             return createAccessibilityNodeInfoInternal();
8699         }
8700     }
8701 
8702     /**
8703      * @see #createAccessibilityNodeInfo()
8704      *
8705      * @hide
8706      */
8707     public @Nullable AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8708         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8709         if (provider != null) {
8710             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8711         } else {
8712             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8713             onInitializeAccessibilityNodeInfo(info);
8714             return info;
8715         }
8716     }
8717 
8718     /**
8719      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8720      * The base implementation sets:
8721      * <ul>
8722      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8723      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8724      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8725      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8726      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8727      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8728      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8729      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8730      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8731      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8732      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8733      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8734      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8735      * </ul>
8736      * <p>
8737      * Subclasses should override this method, call the super implementation,
8738      * and set additional attributes.
8739      * </p>
8740      * <p>
8741      * If an {@link AccessibilityDelegate} has been specified via calling
8742      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8743      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8744      * is responsible for handling this call.
8745      * </p>
8746      *
8747      * @param info The instance to initialize.
8748      */
8749     @CallSuper
8750     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8751         if (mAccessibilityDelegate != null) {
8752             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8753         } else {
8754             onInitializeAccessibilityNodeInfoInternal(info);
8755         }
8756     }
8757 
8758     /**
8759      * Gets the location of this view in screen coordinates.
8760      *
8761      * @param outRect The output location
8762      * @hide
8763      */
8764     @UnsupportedAppUsage
8765     public void getBoundsOnScreen(Rect outRect) {
8766         getBoundsOnScreen(outRect, false);
8767     }
8768 
8769     /**
8770      * Gets the location of this view in screen coordinates.
8771      *
8772      * @param outRect The output location
8773      * @param clipToParent Whether to clip child bounds to the parent ones.
8774      * @hide
8775      */
8776     @UnsupportedAppUsage
8777     @TestApi
8778     public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
8779         if (mAttachInfo == null) {
8780             return;
8781         }
8782         RectF position = mAttachInfo.mTmpTransformRect;
8783         getBoundsToScreenInternal(position, clipToParent);
8784         outRect.set(Math.round(position.left), Math.round(position.top),
8785                 Math.round(position.right), Math.round(position.bottom));
8786         // If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
8787         // will sandbox outRect within window bounds.
8788         mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
8789     }
8790 
8791     /**
8792      * Gets the location of this view in screen coordinates.
8793      *
8794      * @param outRect The output location
8795      * @param clipToParent Whether to clip child bounds to the parent ones.
8796      * @hide
8797      */
8798     public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
8799         if (mAttachInfo == null) {
8800             return;
8801         }
8802         RectF position = mAttachInfo.mTmpTransformRect;
8803         getBoundsToScreenInternal(position, clipToParent);
8804         outRect.set(position.left, position.top, position.right, position.bottom);
8805     }
8806 
8807     private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
8808         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8809         mapRectFromViewToScreenCoords(position, clipToParent);
8810     }
8811 
8812     /**
8813      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8814      *
8815      * @param rect The rectangle to be mapped
8816      * @param clipToParent Whether to clip child bounds to the parent ones.
8817      * @hide
8818      */
8819     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8820         if (!hasIdentityMatrix()) {
8821             getMatrix().mapRect(rect);
8822         }
8823 
8824         rect.offset(mLeft, mTop);
8825 
8826         ViewParent parent = mParent;
8827         while (parent instanceof View) {
8828             View parentView = (View) parent;
8829 
8830             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
8831 
8832             if (clipToParent) {
8833                 rect.left = Math.max(rect.left, 0);
8834                 rect.top = Math.max(rect.top, 0);
8835                 rect.right = Math.min(rect.right, parentView.getWidth());
8836                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
8837             }
8838 
8839             if (!parentView.hasIdentityMatrix()) {
8840                 parentView.getMatrix().mapRect(rect);
8841             }
8842 
8843             rect.offset(parentView.mLeft, parentView.mTop);
8844 
8845             parent = parentView.mParent;
8846         }
8847 
8848         if (parent instanceof ViewRootImpl) {
8849             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
8850             rect.offset(0, -viewRootImpl.mCurScrollY);
8851         }
8852 
8853         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8854     }
8855 
8856     /**
8857      * Return the class name of this object to be used for accessibility purposes.
8858      * Subclasses should only override this if they are implementing something that
8859      * should be seen as a completely new class of view when used by accessibility,
8860      * unrelated to the class it is deriving from.  This is used to fill in
8861      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
8862      */
8863     public CharSequence getAccessibilityClassName() {
8864         return View.class.getName();
8865     }
8866 
8867     /**
8868      * Called when assist structure is being retrieved from a view as part of
8869      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
8870      * @param structure Fill in with structured view data.  The default implementation
8871      * fills in all data that can be inferred from the view itself.
8872      */
8873     public void onProvideStructure(ViewStructure structure) {
8874         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
8875     }
8876 
8877     /**
8878      * Populates a {@link ViewStructure} to fullfil an autofill request.
8879      *
8880      * <p>The structure should contain at least the following properties:
8881      * <ul>
8882      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
8883      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
8884      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
8885      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
8886      * </ul>
8887      *
8888      * <p>It's also recommended to set the following properties - the more properties the structure
8889      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
8890      * using the structure:
8891      *
8892      * <ul>
8893      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
8894      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
8895      *       view can only be filled with predefined values (typically used when the autofill type
8896      *       is {@link #AUTOFILL_TYPE_LIST}).
8897      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
8898      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
8899      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
8900      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
8901      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
8902      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
8903      *   <li>For views representing text fields, text properties such as the text itself
8904      *       ({@link ViewStructure#setText(CharSequence)}), text hints
8905      *       ({@link ViewStructure#setHint(CharSequence)}, input type
8906      *       ({@link ViewStructure#setInputType(int)}),
8907      *   <li>For views representing HTML nodes, its web domain
8908      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
8909      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
8910      * </ul>
8911      *
8912      * <p>The default implementation of this method already sets most of these properties based on
8913      * related {@link View} methods (for example, the autofill id is set using
8914      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
8915      * and views in the standard Android widgets library also override it to set their
8916      * relevant properties (for example, {@link android.widget.TextView} already sets the text
8917      * properties), so it's recommended to only override this method
8918      * (and call {@code super.onProvideAutofillStructure()}) when:
8919      *
8920      * <ul>
8921      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
8922      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
8923      *   <li>The view can only be autofilled with predefined options, so it can call
8924      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
8925      * </ul>
8926      *
8927      * <p><b>Note:</b> The {@code left} and {@code top} values set in
8928      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
8929      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
8930      *
8931      * <p>Views support the Autofill Framework mainly by:
8932      * <ul>
8933      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8934      *   <li>Notifying the Android System when the view value changed by calling
8935      *       {@link AutofillManager#notifyValueChanged(View)}.
8936      *   <li>Implementing the methods that autofill the view.
8937      * </ul>
8938      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
8939      * for the latter.
8940      *
8941      * @param structure fill in with structured view data for autofill purposes.
8942      * @param flags optional flags.
8943      *
8944      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8945      */
8946     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
8947         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
8948     }
8949 
8950     /**
8951      * Populates a {@link ViewStructure} for content capture.
8952      *
8953      * <p>This method is called after a view that is eligible for content capture
8954      * (for example, if it {@link #isImportantForContentCapture()}, an intelligence service is
8955      * enabled for the user, and the activity rendering the view is enabled for content capture)
8956      * is laid out and is visible. The populated structure is then passed to the service through
8957      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
8958      *
8959      * <p>The default implementation of this method sets the most relevant properties based on
8960      * related {@link View} methods, and views in the standard Android widgets library also
8961      * override it to set their relevant properties. Therefore, if overriding this method, it
8962      * is recommended to call {@code super.onProvideContentCaptureStructure()}.
8963      *
8964      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
8965      * the node representing this view and return right away, then asynchronously report (not
8966      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
8967      * changed by calling
8968      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
8969      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
8970      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
8971      * respectively. The structure for a child must be created using
8972      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
8973      * {@code autofillId} for a child can be obtained either through
8974      * {@code childStructure.getAutofillId()} or
8975      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
8976      *
8977      * <p>When the virtual view hierarchy represents a web page, you should also:
8978      *
8979      * <ul>
8980      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
8981      *   capture events should be generate for that URL.
8982      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
8983      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
8984      *   that subtree.
8985      * </ul>
8986      *
8987      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
8988      * <ul>
8989      *   <li>{@link ViewStructure#setChildCount(int)}
8990      *   <li>{@link ViewStructure#addChildCount(int)}
8991      *   <li>{@link ViewStructure#getChildCount()}
8992      *   <li>{@link ViewStructure#newChild(int)}
8993      *   <li>{@link ViewStructure#asyncNewChild(int)}
8994      *   <li>{@link ViewStructure#asyncCommit()}
8995      *   <li>{@link ViewStructure#setWebDomain(String)}
8996      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
8997      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
8998      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
8999      *   <li>{@link ViewStructure#setAlpha(float)}
9000      *   <li>{@link ViewStructure#setElevation(float)}
9001      *   <li>{@link ViewStructure#setTransformation(Matrix)}
9002      *
9003      * </ul>
9004      */
9005     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
9006         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
9007     }
9008 
9009     /** @hide */
9010     protected void onProvideStructure(@NonNull ViewStructure structure,
9011             @ViewStructureType int viewFor, int flags) {
9012         final int id = mID;
9013         if (id != NO_ID && !isViewIdGenerated(id)) {
9014             String pkg, type, entry;
9015             try {
9016                 final Resources res = getResources();
9017                 entry = res.getResourceEntryName(id);
9018                 type = res.getResourceTypeName(id);
9019                 pkg = res.getResourcePackageName(id);
9020             } catch (Resources.NotFoundException e) {
9021                 entry = type = pkg = null;
9022             }
9023             structure.setId(id, pkg, type, entry);
9024         } else {
9025             structure.setId(id, null, null, null);
9026         }
9027 
9028         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9029                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
9030             final @AutofillType int autofillType = getAutofillType();
9031             // Don't need to fill autofill info if view does not support it.
9032             // For example, only TextViews that are editable support autofill
9033             if (autofillType != AUTOFILL_TYPE_NONE) {
9034                 structure.setAutofillType(autofillType);
9035                 structure.setAutofillHints(getAutofillHints());
9036                 structure.setAutofillValue(getAutofillValue());
9037             }
9038             structure.setImportantForAutofill(getImportantForAutofill());
9039             structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
9040         }
9041 
9042         int ignoredParentLeft = 0;
9043         int ignoredParentTop = 0;
9044         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9045                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
9046             View parentGroup = null;
9047 
9048             ViewParent viewParent = getParent();
9049             if (viewParent instanceof View) {
9050                 parentGroup = (View) viewParent;
9051             }
9052 
9053             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
9054                 ignoredParentLeft += parentGroup.mLeft;
9055                 ignoredParentTop += parentGroup.mTop;
9056 
9057                 viewParent = parentGroup.getParent();
9058                 if (viewParent instanceof View) {
9059                     parentGroup = (View) viewParent;
9060                 } else {
9061                     break;
9062                 }
9063             }
9064         }
9065 
9066         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
9067                 mRight - mLeft, mBottom - mTop);
9068         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
9069             if (!hasIdentityMatrix()) {
9070                 structure.setTransformation(getMatrix());
9071             }
9072             structure.setElevation(getZ());
9073         }
9074         structure.setVisibility(getVisibility());
9075         structure.setEnabled(isEnabled());
9076         if (isClickable()) {
9077             structure.setClickable(true);
9078         }
9079         if (isFocusable()) {
9080             structure.setFocusable(true);
9081         }
9082         if (isFocused()) {
9083             structure.setFocused(true);
9084         }
9085         if (isAccessibilityFocused()) {
9086             structure.setAccessibilityFocused(true);
9087         }
9088         if (isSelected()) {
9089             structure.setSelected(true);
9090         }
9091         if (isActivated()) {
9092             structure.setActivated(true);
9093         }
9094         if (isLongClickable()) {
9095             structure.setLongClickable(true);
9096         }
9097         if (this instanceof Checkable) {
9098             structure.setCheckable(true);
9099             if (((Checkable)this).isChecked()) {
9100                 structure.setChecked(true);
9101             }
9102         }
9103         if (isOpaque()) {
9104             structure.setOpaque(true);
9105         }
9106         if (isContextClickable()) {
9107             structure.setContextClickable(true);
9108         }
9109         structure.setClassName(getAccessibilityClassName().toString());
9110         structure.setContentDescription(getContentDescription());
9111     }
9112 
9113     /**
9114      * Called when assist structure is being retrieved from a view as part of
9115      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
9116      * generate additional virtual structure under this view.  The default implementation
9117      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
9118      * view's virtual accessibility nodes, if any.  You can override this for a more
9119      * optimal implementation providing this data.
9120      */
9121     public void onProvideVirtualStructure(ViewStructure structure) {
9122         onProvideVirtualStructureCompat(structure, false);
9123     }
9124 
9125     /**
9126      * Fallback implementation to populate a ViewStructure from accessibility state.
9127      *
9128      * @param structure The structure to populate.
9129      * @param forAutofill Whether the structure is needed for autofill.
9130      */
9131     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
9132         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9133         if (provider != null) {
9134             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9135                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
9136             }
9137             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
9138             structure.setChildCount(1);
9139             final ViewStructure root = structure.newChild(0);
9140             populateVirtualStructure(root, provider, info, forAutofill);
9141             info.recycle();
9142         }
9143     }
9144 
9145     /**
9146      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
9147      * request.
9148      *
9149      * <p>This method should be used when the view manages a virtual structure under this view. For
9150      * example, a view that draws input fields using {@link #draw(Canvas)}.
9151      *
9152      * <p>When implementing this method, subclasses must follow the rules below:
9153      *
9154      * <ul>
9155      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
9156      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
9157      *       identifying the children in the virtual structure.
9158      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
9159      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
9160      *       autofill performance.
9161      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
9162      *       children.
9163      *   <li>Set the autofill properties of the child structure as defined by
9164      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
9165      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
9166      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
9167      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
9168      *       when the focused virtual child changed.
9169      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9170      *       whether a given virtual view is visible to the user in order to support triggering
9171      *       save when all views of interest go away.
9172      *   <li>Call
9173      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9174      *       when the value of a virtual child changed.
9175      *   <li>Call {@link
9176      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9177      *       when the visibility of a virtual child changed.
9178      *   <li>Call
9179      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9180      *       child is clicked.
9181      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9182      *       changed and the current context should be committed (for example, when the user tapped
9183      *       a {@code SUBMIT} button in an HTML page).
9184      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9185      *       changed and the current context should be canceled (for example, when the user tapped
9186      *       a {@code CANCEL} button in an HTML page).
9187      *   <li>Provide ways for users to manually request autofill by calling
9188      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9189      *   <li>The {@code left} and {@code top} values set in
9190      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9191      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9192      *       structure.
9193      * </ul>
9194      *
9195      * <p>Views with virtual children support the Autofill Framework mainly by:
9196      * <ul>
9197      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9198      *       autofilled.
9199      *   <li>Implementing the methods that autofill the virtual children.
9200      * </ul>
9201      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9202      * for the latter.
9203      *
9204      * @param structure fill in with virtual children data for autofill purposes.
9205      * @param flags optional flags.
9206      *
9207      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9208      */
9209     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9210         if (mContext.isAutofillCompatibilityEnabled()) {
9211             onProvideVirtualStructureCompat(structure, true);
9212         }
9213     }
9214 
9215     /**
9216      * Sets the listener to be {@link #performReceiveContent used} to handle insertion of
9217      * content into this view.
9218      *
9219      * <p>Depending on the type of view, this listener may be invoked for different scenarios. For
9220      * example, for an editable {@link android.widget.TextView}, this listener will be invoked for
9221      * the following scenarios:
9222      * <ol>
9223      *     <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
9224      *     insertion/selection menu)
9225      *     <li>Content insertion from the keyboard (from {@link InputConnection#commitContent})
9226      *     <li>Drag and drop (drop events from {@link #onDragEvent})
9227      *     <li>Autofill
9228      *     <li>Selection replacement via {@link Intent#ACTION_PROCESS_TEXT}
9229      * </ol>
9230      *
9231      * <p>When setting a listener, clients must also declare the accepted MIME types.
9232      * The listener will still be invoked even if the MIME type of the content is not one of the
9233      * declared MIME types (e.g. if the user pastes content whose type is not one of the declared
9234      * MIME types).
9235      * In that case, the listener may reject the content (defer to the default platform behavior)
9236      * or execute some other fallback logic (e.g. show an appropriate message to the user).
9237      * The declared MIME types serve as a hint to allow different features to optionally alter
9238      * their behavior. For example, a soft keyboard may optionally choose to hide its UI for
9239      * inserting GIFs for a particular input field if the MIME types set here for that field
9240      * don't include "image/gif" or "image/*".
9241      *
9242      * <p>Note: MIME type matching in the Android framework is case-sensitive, unlike formal RFC
9243      * MIME types. As a result, you should always write your MIME types with lowercase letters,
9244      * or use {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9245      * lowercase.
9246      *
9247      * @param mimeTypes The MIME types accepted by the given listener. These may use patterns
9248      *                  such as "image/*", but may not start with a wildcard. This argument must
9249      *                  not be null or empty if a non-null listener is passed in.
9250      * @param listener The listener to use. This can be null to reset to the default behavior.
9251      */
9252     public void setOnReceiveContentListener(
9253             @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
9254             @Nullable OnReceiveContentListener listener) {
9255         if (listener != null) {
9256             Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
9257                     "When the listener is set, MIME types must also be set");
9258         }
9259         if (mimeTypes != null) {
9260             Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
9261                     "A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
9262         }
9263         mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
9264         getListenerInfo().mOnReceiveContentListener = listener;
9265     }
9266 
9267     /**
9268      * Receives the given content. If no listener is set, invokes {@link #onReceiveContent}. If a
9269      * listener is {@link #setOnReceiveContentListener set}, invokes the listener instead; if the
9270      * listener returns a non-null result, invokes {@link #onReceiveContent} to handle it.
9271      *
9272      * @param payload The content to insert and related metadata.
9273      *
9274      * @return The portion of the passed-in content that was not accepted (may be all, some, or none
9275      * of the passed-in content).
9276      */
9277     @Nullable
performReceiveContent(@onNull ContentInfo payload)9278     public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
9279         final OnReceiveContentListener listener = (mListenerInfo == null) ? null
9280                 : getListenerInfo().mOnReceiveContentListener;
9281         if (listener != null) {
9282             final ContentInfo remaining = listener.onReceiveContent(this, payload);
9283             return (remaining == null) ? null : onReceiveContent(remaining);
9284         }
9285         return onReceiveContent(payload);
9286     }
9287 
9288     /**
9289      * Implements the default behavior for receiving content for this type of view. The default
9290      * view implementation is a no-op (returns the passed-in content without acting on it).
9291      *
9292      * <p>Widgets should override this method to define their default behavior for receiving
9293      * content. Apps should {@link #setOnReceiveContentListener set a listener} to provide
9294      * app-specific handling for receiving content.
9295      *
9296      * <p>See {@link #setOnReceiveContentListener} and {@link #performReceiveContent} for more info.
9297      *
9298      * @param payload The content to insert and related metadata.
9299      *
9300      * @return The portion of the passed-in content that was not handled (may be all, some, or none
9301      * of the passed-in content).
9302      */
9303     @Nullable
onReceiveContent(@onNull ContentInfo payload)9304     public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
9305         return payload;
9306     }
9307 
9308     /**
9309      * Returns the MIME types accepted by {@link #performReceiveContent} for this view, as
9310      * configured via {@link #setOnReceiveContentListener}. By default returns null.
9311      *
9312      * <p>Different features (e.g. pasting from the clipboard, inserting stickers from the soft
9313      * keyboard, etc) may optionally use this metadata to conditionally alter their behavior. For
9314      * example, a soft keyboard may choose to hide its UI for inserting GIFs for a particular
9315      * input field if the MIME types returned here for that field don't include "image/gif" or
9316      * "image/*".
9317      *
9318      * <p>Note: Comparisons of MIME types should be performed using utilities such as
9319      * {@link ClipDescription#compareMimeTypes} rather than simple string equality, in order to
9320      * correctly handle patterns such as "text/*", "image/*", etc. Note that MIME type matching
9321      * in the Android framework is case-sensitive, unlike formal RFC MIME types. As a result,
9322      * you should always write your MIME types with lowercase letters, or use
9323      * {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9324      * lowercase.
9325      *
9326      * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
9327      * include patterns such as "image/*").
9328      */
9329     @SuppressLint("NullableCollection")
9330     @Nullable
getReceiveContentMimeTypes()9331     public String[] getReceiveContentMimeTypes() {
9332         return mReceiveContentMimeTypes;
9333     }
9334 
9335     /**
9336      * Automatically fills the content of this view with the {@code value}.
9337      *
9338      * <p>Views support the Autofill Framework mainly by:
9339      * <ul>
9340      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9341      *   <li>Implementing the methods that autofill the view.
9342      * </ul>
9343      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
9344      * this method is responsible for latter.
9345      *
9346      * <p>This method does nothing by default, but when overridden it typically:
9347      * <ol>
9348      *   <li>Checks if the provided value matches the expected type (which is defined by
9349      *       {@link #getAutofillType()}).
9350      *   <li>Checks if the view is editable - if it isn't, it should return right away.
9351      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
9352      *   <li>Pass the actual value to the equivalent setter in the view.
9353      * </ol>
9354      *
9355      * <p>For example, a text-field view could implement the method this way:
9356      *
9357      * <pre class="prettyprint">
9358      * &#64;Override
9359      * public void autofill(AutofillValue value) {
9360      *   if (!value.isText() || !this.isEditable()) {
9361      *      return;
9362      *   }
9363      *   CharSequence text = value.getTextValue();
9364      *   if (text != null) {
9365      *     this.setText(text);
9366      *   }
9367      * }
9368      * </pre>
9369      *
9370      * <p>If the value is updated asynchronously, the next call to
9371      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
9372      * changed to the autofilled value. If not, the view will not be considered autofilled.
9373      *
9374      * <p><b>Note:</b> After this method is called, the value returned by
9375      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
9376      * view will not be highlighted as autofilled.
9377      *
9378      * @param value value to be autofilled.
9379      */
autofill(@uppressWarnings"unused") AutofillValue value)9380     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
9381     }
9382 
9383     /**
9384      * Automatically fills the content of the virtual children within this view.
9385      *
9386      * <p>Views with virtual children support the Autofill Framework mainly by:
9387      * <ul>
9388      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9389      *       autofilled.
9390      *   <li>Implementing the methods that autofill the virtual children.
9391      * </ul>
9392      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
9393      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
9394      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
9395      *
9396      * <p>If a child value is updated asynchronously, the next call to
9397      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
9398      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
9399      * considered autofilled.
9400      *
9401      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
9402      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
9403      * changes.
9404      *
9405      * @param values map of values to be autofilled, keyed by virtual child id.
9406      *
9407      * @attr ref android.R.styleable#Theme_autofilledHighlight
9408      */
autofill(@onNull @uppressWarnings"unused") SparseArray<AutofillValue> values)9409     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
9410         if (!mContext.isAutofillCompatibilityEnabled()) {
9411             return;
9412         }
9413         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9414         if (provider == null) {
9415             return;
9416         }
9417         final int valueCount = values.size();
9418         for (int i = 0; i < valueCount; i++) {
9419             final AutofillValue value = values.valueAt(i);
9420             if (value.isText()) {
9421                 final int virtualId = values.keyAt(i);
9422                 final CharSequence text = value.getTextValue();
9423                 final Bundle arguments = new Bundle();
9424                 arguments.putCharSequence(
9425                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
9426                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
9427             }
9428         }
9429     }
9430 
9431     /**
9432      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
9433      *
9434      * <p>The autofill id is created on demand, unless it is explicitly set by
9435      * {@link #setAutofillId(AutofillId)}.
9436      *
9437      * <p>See {@link #setAutofillId(AutofillId)} for more info.
9438      *
9439      * @return The View's autofill id.
9440      */
getAutofillId()9441     public final AutofillId getAutofillId() {
9442         if (mAutofillId == null) {
9443             // The autofill id needs to be unique, but its value doesn't matter,
9444             // so it's better to reuse the accessibility id to save space.
9445             mAutofillId = new AutofillId(getAutofillViewId());
9446         }
9447         return mAutofillId;
9448     }
9449 
9450     /**
9451      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
9452      *
9453      * <p>The autofill id is created on demand, and this method should only be called when a view is
9454      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
9455      * that method creates a snapshot of the view that is passed along to the autofill service.
9456      *
9457      * <p>This method is typically used when view subtrees are recycled to represent different
9458      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
9459      * out, and restored later when it's swapped back in. For example:
9460      *
9461      * <pre>
9462      * EditText reusableView = ...;
9463      * ViewGroup parentView = ...;
9464      * AutofillManager afm = ...;
9465      *
9466      * // Swap out the view and change its contents
9467      * AutofillId oldId = reusableView.getAutofillId();
9468      * CharSequence oldText = reusableView.getText();
9469      * parentView.removeView(reusableView);
9470      * AutofillId newId = afm.getNextAutofillId();
9471      * reusableView.setText("New I am");
9472      * reusableView.setAutofillId(newId);
9473      * parentView.addView(reusableView);
9474      *
9475      * // Later, swap the old content back in
9476      * parentView.removeView(reusableView);
9477      * reusableView.setAutofillId(oldId);
9478      * reusableView.setText(oldText);
9479      * parentView.addView(reusableView);
9480      * </pre>
9481      *
9482      * <p>NOTE: If this view is a descendant of an {@link android.widget.AdapterView}, the system
9483      * may reset its autofill id when this view is recycled. If the autofill ids need to be stable,
9484      * they should be set again in
9485      * {@link android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
9486      *
9487      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
9488      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
9489      * obtained through {@link #getAutofillId()}), or a new value obtained through
9490      * {@link AutofillManager#getNextAutofillId()}.
9491      *
9492      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
9493      * a window}.
9494      *
9495      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
9496      */
setAutofillId(@ullable AutofillId id)9497     public void setAutofillId(@Nullable AutofillId id) {
9498         // TODO(b/37566627): add unit / CTS test for all possible combinations below
9499         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9500             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
9501         }
9502         if (isAttachedToWindow()) {
9503             throw new IllegalStateException("Cannot set autofill id when view is attached");
9504         }
9505         if (id != null && !id.isNonVirtual()) {
9506             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
9507         }
9508         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
9509             // Ignore reset because it was never explicitly set before.
9510             return;
9511         }
9512         mAutofillId = id;
9513         if (id != null) {
9514             mAutofillViewId = id.getViewId();
9515             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9516         } else {
9517             mAutofillViewId = NO_ID;
9518             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9519         }
9520     }
9521 
9522     /**
9523      * Forces a reset of the autofill ids of the subtree rooted at this view. Like calling
9524      * {@link #setAutofillId(AutofillId) setAutofillId(null)} for each view, but works even if the
9525      * views are attached to a window.
9526      *
9527      * <p>This is useful if the views are being recycled, since an autofill id should uniquely
9528      * identify a particular piece of content.
9529      *
9530      * @hide
9531      */
resetSubtreeAutofillIds()9532     public void resetSubtreeAutofillIds() {
9533         if (mAutofillViewId == NO_ID) {
9534             return;
9535         }
9536         if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9537             Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9538         } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9539             Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9540         }
9541         mAutofillId = null;
9542         mAutofillViewId = NO_ID;
9543         mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9544     }
9545 
9546     /**
9547      * Describes the autofill type of this view, so an
9548      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
9549      * when autofilling the view.
9550      *
9551      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
9552      * support the Autofill Framework.
9553      *
9554      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
9555      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
9556      *
9557      * @see #onProvideAutofillStructure(ViewStructure, int)
9558      * @see #autofill(AutofillValue)
9559      */
getAutofillType()9560     public @AutofillType int getAutofillType() {
9561         return AUTOFILL_TYPE_NONE;
9562     }
9563 
9564     /**
9565      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
9566      * to autofill the view with the user's data.
9567      *
9568      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
9569      *
9570      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
9571      * {@code null} if no hints were set.
9572      *
9573      * @attr ref android.R.styleable#View_autofillHints
9574      */
9575     @ViewDebug.ExportedProperty()
9576     @InspectableProperty
getAutofillHints()9577     @Nullable public String[] getAutofillHints() {
9578         return mAutofillHints;
9579     }
9580 
9581     /**
9582      * @hide
9583      */
9584     @TestApi
isAutofilled()9585     public boolean isAutofilled() {
9586         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
9587     }
9588 
9589     /**
9590      * @hide
9591      */
hideAutofillHighlight()9592     public boolean hideAutofillHighlight() {
9593         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
9594     }
9595 
9596     /**
9597      * Gets the {@link View}'s current autofill value.
9598      *
9599      * <p>By default returns {@code null}, but subclasses should override it and return an
9600      * appropriate value to properly support the Autofill Framework.
9601      *
9602      * @see #onProvideAutofillStructure(ViewStructure, int)
9603      * @see #autofill(AutofillValue)
9604      */
9605     @Nullable
getAutofillValue()9606     public AutofillValue getAutofillValue() {
9607         return null;
9608     }
9609 
9610     /**
9611      * Gets the mode for determining whether this view is important for autofill.
9612      *
9613      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
9614      * info about this mode.
9615      *
9616      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
9617      * {@link #setImportantForAutofill(int)}.
9618      *
9619      * @attr ref android.R.styleable#View_importantForAutofill
9620      */
9621     @ViewDebug.ExportedProperty(mapping = {
9622             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
9623             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
9624             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
9625             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9626                 to = "yesExcludeDescendants"),
9627             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9628                 to = "noExcludeDescendants")})
9629     @InspectableProperty(enumMapping = {
9630             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
9631             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
9632             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
9633             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9634                     name = "yesExcludeDescendants"),
9635             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9636                     name = "noExcludeDescendants"),
9637     })
getImportantForAutofill()9638     public @AutofillImportance int getImportantForAutofill() {
9639         return (mPrivateFlags3
9640                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
9641     }
9642 
9643     /**
9644      * Sets the mode for determining whether this view is considered important for autofill.
9645      *
9646      * <p>The platform determines the importance for autofill automatically but you
9647      * can use this method to customize the behavior. For example:
9648      *
9649      * <ol>
9650      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
9651      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
9652      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
9653      *       view of an activity containing a spreadhseet editor), it should be
9654      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9655      *   <li>When the view content is relevant for autofill but its children aren't (for example,
9656      *       a credit card expiration date represented by a custom view that overrides the proper
9657      *       autofill methods and has 2 children representing the month and year), it should
9658      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
9659      * </ol>
9660      *
9661      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9662      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
9663      * children) will be always be considered not important; for example, when the user explicitly
9664      * makes an autofill request, all views are considered important. See
9665      * {@link #isImportantForAutofill()} for more details about how the View's importance for
9666      * autofill is used.
9667      *
9668      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
9669      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
9670      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9671      *
9672      * @attr ref android.R.styleable#View_importantForAutofill
9673      */
setImportantForAutofill(@utofillImportance int mode)9674     public void setImportantForAutofill(@AutofillImportance int mode) {
9675         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9676         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
9677                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9678     }
9679 
9680     /**
9681      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
9682      * associated with this view is considered important for autofill purposes.
9683      *
9684      * <p>Generally speaking, a view is important for autofill if:
9685      * <ol>
9686      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
9687      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
9688      *     determine how other views can be autofilled.
9689      * <ol>
9690      *
9691      * <p>For example, view containers should typically return {@code false} for performance reasons
9692      * (since the important info is provided by their children), but if its properties have relevant
9693      * information (for example, a resource id called {@code credentials}, it should return
9694      * {@code true}. On the other hand, views representing labels or editable fields should
9695      * typically return {@code true}, but in some cases they could return {@code false}
9696      * (for example, if they're part of a "Captcha" mechanism).
9697      *
9698      * <p>The value returned by this method depends on the value returned by
9699      * {@link #getImportantForAutofill()}:
9700      *
9701      * <ol>
9702      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
9703      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
9704      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9705      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
9706      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
9707      *       that can return {@code true} in some cases (like a container with a resource id),
9708      *       but {@code false} in most.
9709      *   <li>otherwise, it returns {@code false}.
9710      * </ol>
9711      *
9712      * <p>When a view is considered important for autofill:
9713      * <ul>
9714      *   <li>The view might automatically trigger an autofill request when focused on.
9715      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
9716      *       request.
9717      * </ul>
9718      *
9719      * <p>On the other hand, when a view is considered not important for autofill:
9720      * <ul>
9721      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
9722      *       request through {@link AutofillManager#requestAutofill(View)}.
9723      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
9724      *       autofill request, unless the request has the
9725      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9726      * </ul>
9727      *
9728      * @return whether the view is considered important for autofill.
9729      *
9730      * @see #setImportantForAutofill(int)
9731      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9732      * @see #IMPORTANT_FOR_AUTOFILL_YES
9733      * @see #IMPORTANT_FOR_AUTOFILL_NO
9734      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9735      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9736      * @see AutofillManager#requestAutofill(View)
9737      */
isImportantForAutofill()9738     public final boolean isImportantForAutofill() {
9739         // Check parent mode to ensure we're not hidden.
9740         ViewParent parent = mParent;
9741         while (parent instanceof View) {
9742             final int parentImportance = ((View) parent).getImportantForAutofill();
9743             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9744                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9745                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9746                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9747                             + "because parent " + parent + "'s importance is " + parentImportance);
9748                 }
9749                 return false;
9750             }
9751             parent = parent.getParent();
9752         }
9753 
9754         final int importance = getImportantForAutofill();
9755 
9756         // First, check the explicit states.
9757         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9758                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9759             return true;
9760         }
9761         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9762                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9763             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9764                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9765                         + "because its importance is " + importance);
9766             }
9767             return false;
9768         }
9769 
9770         // Then use some heuristics to handle AUTO.
9771         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9772             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9773                     + this);
9774             return false;
9775         }
9776 
9777         // Always include views that have an explicit resource id.
9778         final int id = mID;
9779         if (id != NO_ID && !isViewIdGenerated(id)) {
9780             final Resources res = getResources();
9781             String entry = null;
9782             String pkg = null;
9783             try {
9784                 entry = res.getResourceEntryName(id);
9785                 pkg = res.getResourcePackageName(id);
9786             } catch (Resources.NotFoundException e) {
9787                 // ignore
9788             }
9789             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9790                 return true;
9791             }
9792         }
9793 
9794         // If the app developer explicitly set hints for it, it's important.
9795         if (getAutofillHints() != null) {
9796             return true;
9797         }
9798 
9799         // Otherwise, assume it's not important...
9800         return false;
9801     }
9802 
9803     /**
9804      * Gets the mode for determining whether this view is important for content capture.
9805      *
9806      * <p>See {@link #setImportantForContentCapture(int)} and
9807      * {@link #isImportantForContentCapture()} for more info about this mode.
9808      *
9809      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
9810      * {@link #setImportantForContentCapture(int)}.
9811      *
9812      * @attr ref android.R.styleable#View_importantForContentCapture
9813      */
9814     @ViewDebug.ExportedProperty(mapping = {
9815             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
9816             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
9817             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
9818             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9819                 to = "yesExcludeDescendants"),
9820             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9821                 to = "noExcludeDescendants")})
9822     @InspectableProperty(enumMapping = {
9823             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
9824             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
9825             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
9826             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9827                     name = "yesExcludeDescendants"),
9828             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9829                     name = "noExcludeDescendants"),
9830     })
getImportantForContentCapture()9831     public @ContentCaptureImportance int getImportantForContentCapture() {
9832         // NOTE: the important for content capture values were the first flags added and are set in
9833         // the rightmost position, so we don't need to shift them
9834         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9835     }
9836 
9837     /**
9838      * Sets the mode for determining whether this view is considered important for content capture.
9839      *
9840      * <p>The platform determines the importance for autofill automatically but you
9841      * can use this method to customize the behavior. Typically, a view that provides text should
9842      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
9843      *
9844      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
9845      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
9846      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
9847      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
9848      *
9849      * @attr ref android.R.styleable#View_importantForContentCapture
9850      */
setImportantForContentCapture(@ontentCaptureImportance int mode)9851     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
9852         // Reset first
9853         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9854         // Then set again
9855         // NOTE: the important for content capture values were the first flags added and are set in
9856         // the rightmost position, so we don't need to shift them
9857         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
9858     }
9859 
9860     /**
9861      * Hints the Android System whether this view is considered important for content capture, based
9862      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
9863      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
9864      *
9865      * <p>See {@link ContentCaptureManager} for more info about content capture.
9866      *
9867      * @return whether the view is considered important for content capture.
9868      *
9869      * @see #setImportantForContentCapture(int)
9870      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
9871      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
9872      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
9873      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9874      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9875      */
isImportantForContentCapture()9876     public final boolean isImportantForContentCapture() {
9877         boolean isImportant;
9878         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
9879             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
9880             return isImportant;
9881         }
9882 
9883         isImportant = calculateIsImportantForContentCapture();
9884 
9885         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9886         if (isImportant) {
9887             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9888         }
9889         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
9890         return isImportant;
9891     }
9892 
9893     /**
9894      * Calculates whether the flag is important for content capture so it can be used by
9895      * {@link #isImportantForContentCapture()} while the tree is traversed.
9896      */
calculateIsImportantForContentCapture()9897     private boolean calculateIsImportantForContentCapture() {
9898         // Check parent mode to ensure we're important
9899         ViewParent parent = mParent;
9900         while (parent instanceof View) {
9901             final int parentImportance = ((View) parent).getImportantForContentCapture();
9902             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9903                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
9904                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9905                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
9906                             + "content capture because parent " + parent + "'s importance is "
9907                             + parentImportance);
9908                 }
9909                 return false;
9910             }
9911             parent = parent.getParent();
9912         }
9913 
9914         final int importance = getImportantForContentCapture();
9915 
9916         // First, check the explicit states.
9917         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9918                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
9919             return true;
9920         }
9921         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9922                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
9923             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9924                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
9925                         + "capture because its importance is " + importance);
9926             }
9927             return false;
9928         }
9929 
9930         // Then use some heuristics to handle AUTO.
9931         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
9932             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
9933                     + " on view " + this);
9934             return false;
9935         }
9936 
9937         // View group is important if at least one children also is
9938         if (this instanceof ViewGroup) {
9939             final ViewGroup group = (ViewGroup) this;
9940             for (int i = 0; i < group.getChildCount(); i++) {
9941                 final View child = group.getChildAt(i);
9942                 if (child.isImportantForContentCapture()) {
9943                     return true;
9944                 }
9945             }
9946         }
9947 
9948         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
9949         if (getAutofillHints() != null) {
9950             return true;
9951         }
9952 
9953         // Otherwise, assume it's not important...
9954         return false;
9955     }
9956 
9957     /**
9958      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
9959      * added, based on whether it's laid out and visible, and without knowing if the parent removed
9960      * it from the view hierarchy.
9961      *
9962      * <p>This method is called from many places (visibility changed, view laid out, view attached
9963      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
9964      * described below:
9965      *
9966      * <ol>
9967      *   <li>It should only be called when content capture is enabled for the view.
9968      *   <li>It must call viewAppeared() before viewDisappeared()
9969      *   <li>viewAppeared() can only be called when the view is visible and laid out
9970      *   <li>It should not call the same event twice.
9971      * </ol>
9972      */
notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared)9973     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
9974         AttachInfo ai = mAttachInfo;
9975         // Skip it while the view is being laid out for the first time
9976         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
9977 
9978         // First check if context has client, so it saves a service lookup when it doesn't
9979         if (mContext.getContentCaptureOptions() == null) return;
9980 
9981         if (appeared) {
9982             // The appeared event stops sending to AiAi.
9983             // 1. The view is hidden.
9984             // 2. The same event was sent.
9985             // 3. The view is not laid out, and it will be laid out in the future.
9986             //    Some recycled views cached its layout and a relayout is unnecessary. In this case,
9987             // system still needs to notify content capture the view appeared. When a view is
9988             // recycled, it will set the flag PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED.
9989             final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
9990                     && getVisibility() == VISIBLE
9991                     && !isLayoutRequested();
9992             if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
9993                     || !(isLaidOut() || isRecycledWithoutRelayout)) {
9994                 if (DEBUG_CONTENT_CAPTURE) {
9995                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
9996                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9997                             + ", visible=" + (getVisibility() == VISIBLE)
9998                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
9999                             + ", alreadyNotifiedDisappeared="
10000                             + getNotifiedContentCaptureDisappeared());
10001                 }
10002                 return;
10003             }
10004         } else {
10005             if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
10006                 if (DEBUG_CONTENT_CAPTURE) {
10007                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
10008                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10009                             + ", visible=" + (getVisibility() == VISIBLE)
10010                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10011                             + ", alreadyNotifiedDisappeared="
10012                             + getNotifiedContentCaptureDisappeared());
10013                 }
10014                 return;
10015             }
10016         }
10017 
10018         ContentCaptureSession session = getContentCaptureSession();
10019         if (session == null) return;
10020 
10021         // ... and finally at the view level
10022         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
10023         if (!isImportantForContentCapture()) return;
10024 
10025         if (appeared) {
10026             setNotifiedContentCaptureAppeared();
10027 
10028             if (ai != null) {
10029                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10030             } else {
10031                 if (DEBUG_CONTENT_CAPTURE) {
10032                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
10033                 }
10034             }
10035         } else {
10036             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10037             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10038 
10039             if (ai != null) {
10040                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10041             } else {
10042                 if (DEBUG_CONTENT_CAPTURE) {
10043                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
10044                 }
10045             }
10046 
10047             // We reset any translation state as views may be re-used (e.g., as in ListView and
10048             // RecyclerView). We only need to do this for views important for content capture since
10049             // views unimportant for content capture won't be translated anyway.
10050             if (!isTemporarilyDetached()) {
10051                 clearTranslationState();
10052             }
10053         }
10054     }
10055 
setNotifiedContentCaptureAppeared()10056     private void setNotifiedContentCaptureAppeared() {
10057         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10058         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10059     }
10060 
10061     /** @hide */
getNotifiedContentCaptureAppeared()10062     protected boolean getNotifiedContentCaptureAppeared() {
10063         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
10064     }
10065 
10066 
getNotifiedContentCaptureDisappeared()10067     private boolean getNotifiedContentCaptureDisappeared() {
10068         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
10069     }
10070 
10071     /**
10072      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
10073      *
10074      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
10075      * the content capture events associated with this view or its view hierarchy (if it's a
10076      * {@link ViewGroup}).
10077      *
10078      * <p>For example, if your activity is associated with a web domain, first you would need to
10079      * set the context for the main DOM:
10080      *
10081      * <pre>
10082      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
10083      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
10084      * </pre>
10085      *
10086      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
10087      *
10088      * <pre>
10089      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
10090      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
10091      *   iframeView.setContentCaptureSession(iframeSession);
10092      * </pre>
10093      *
10094      * @param contentCaptureSession a session created by
10095      * {@link ContentCaptureSession#createContentCaptureSession(
10096      *        android.view.contentcapture.ContentCaptureContext)}.
10097      */
setContentCaptureSession(@ullable ContentCaptureSession contentCaptureSession)10098     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
10099         mContentCaptureSession = contentCaptureSession;
10100     }
10101 
10102     /**
10103      * Gets the session used to notify content capture events.
10104      *
10105      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
10106      * inherited by ancestors, default session or {@code null} if content capture is disabled for
10107      * this view.
10108      */
10109     @Nullable
getContentCaptureSession()10110     public final ContentCaptureSession getContentCaptureSession() {
10111         if (mContentCaptureSessionCached) {
10112             return mContentCaptureSession;
10113         }
10114 
10115         mContentCaptureSession = getAndCacheContentCaptureSession();
10116         mContentCaptureSessionCached = true;
10117         return mContentCaptureSession;
10118     }
10119 
10120     @Nullable
getAndCacheContentCaptureSession()10121     private ContentCaptureSession getAndCacheContentCaptureSession() {
10122         // First try the session explicitly set by setContentCaptureSession()
10123         if (mContentCaptureSession != null) {
10124             return mContentCaptureSession;
10125         }
10126 
10127         // Then the session explicitly set in an ancestor
10128         ContentCaptureSession session = null;
10129         if (mParent instanceof View) {
10130             session = ((View) mParent).getContentCaptureSession();
10131         }
10132 
10133         // Finally, if no session was explicitly set, use the context's default session.
10134         if (session == null) {
10135             final ContentCaptureManager ccm = mContext
10136                     .getSystemService(ContentCaptureManager.class);
10137             return ccm == null ? null : ccm.getMainContentCaptureSession();
10138         }
10139         return session;
10140     }
10141 
10142     @Nullable
getAutofillManager()10143     private AutofillManager getAutofillManager() {
10144         return mContext.getSystemService(AutofillManager.class);
10145     }
10146 
isAutofillable()10147     private boolean isAutofillable() {
10148         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
10149 
10150         if (!isImportantForAutofill()) {
10151             // View is not important for "regular" autofill, so we must check if Augmented Autofill
10152             // is enabled for the activity
10153             final AutofillOptions options = mContext.getAutofillOptions();
10154             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
10155                 return false;
10156             }
10157             final AutofillManager afm = getAutofillManager();
10158             if (afm == null) return false;
10159             afm.notifyViewEnteredForAugmentedAutofill(this);
10160         }
10161 
10162         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
10163     }
10164 
10165     /** @hide */
canNotifyAutofillEnterExitEvent()10166     public boolean canNotifyAutofillEnterExitEvent() {
10167         return isAutofillable() && isAttachedToWindow();
10168     }
10169 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill)10170     private void populateVirtualStructure(ViewStructure structure,
10171             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
10172             boolean forAutofill) {
10173         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
10174                 null, null, info.getViewIdResourceName());
10175         Rect rect = structure.getTempRect();
10176         info.getBoundsInParent(rect);
10177         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
10178         structure.setVisibility(VISIBLE);
10179         structure.setEnabled(info.isEnabled());
10180         if (info.isClickable()) {
10181             structure.setClickable(true);
10182         }
10183         if (info.isFocusable()) {
10184             structure.setFocusable(true);
10185         }
10186         if (info.isFocused()) {
10187             structure.setFocused(true);
10188         }
10189         if (info.isAccessibilityFocused()) {
10190             structure.setAccessibilityFocused(true);
10191         }
10192         if (info.isSelected()) {
10193             structure.setSelected(true);
10194         }
10195         if (info.isLongClickable()) {
10196             structure.setLongClickable(true);
10197         }
10198         if (info.isCheckable()) {
10199             structure.setCheckable(true);
10200             if (info.isChecked()) {
10201                 structure.setChecked(true);
10202             }
10203         }
10204         if (info.isContextClickable()) {
10205             structure.setContextClickable(true);
10206         }
10207         if (forAutofill) {
10208             structure.setAutofillId(new AutofillId(getAutofillId(),
10209                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
10210         }
10211         CharSequence cname = info.getClassName();
10212         structure.setClassName(cname != null ? cname.toString() : null);
10213         structure.setContentDescription(info.getContentDescription());
10214         if (forAutofill) {
10215             final int maxTextLength = info.getMaxTextLength();
10216             if (maxTextLength != -1) {
10217                 structure.setMaxTextLength(maxTextLength);
10218             }
10219             structure.setHint(info.getHintText());
10220         }
10221         CharSequence text = info.getText();
10222         boolean hasText = text != null || info.getError() != null;
10223         if (hasText) {
10224             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
10225         }
10226         if (forAutofill) {
10227             if (info.isEditable()) {
10228                 structure.setDataIsSensitive(true);
10229                 if (hasText) {
10230                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
10231                     structure.setAutofillValue(AutofillValue.forText(text));
10232                 }
10233                 int inputType = info.getInputType();
10234                 if (inputType == 0 && info.isPassword()) {
10235                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
10236                 }
10237                 structure.setInputType(inputType);
10238             } else {
10239                 structure.setDataIsSensitive(false);
10240             }
10241         }
10242         final int NCHILDREN = info.getChildCount();
10243         if (NCHILDREN > 0) {
10244             structure.setChildCount(NCHILDREN);
10245             for (int i=0; i<NCHILDREN; i++) {
10246                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
10247                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
10248                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
10249                     continue;
10250                 }
10251                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
10252                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
10253                 if (cinfo != null) {
10254                     ViewStructure child = structure.newChild(i);
10255                     populateVirtualStructure(child, provider, cinfo, forAutofill);
10256                     cinfo.recycle();
10257                 }
10258             }
10259         }
10260     }
10261 
10262     /**
10263      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
10264      * implementation calls {@link #onProvideStructure} and
10265      * {@link #onProvideVirtualStructure}.
10266      */
dispatchProvideStructure(ViewStructure structure)10267     public void dispatchProvideStructure(ViewStructure structure) {
10268         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
10269     }
10270 
10271     /**
10272      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
10273      * when an Assist structure is being created as part of an autofill request.
10274      *
10275      * <p>The default implementation does the following:
10276      * <ul>
10277      *   <li>Sets the {@link AutofillId} in the structure.
10278      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
10279      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
10280      * </ul>
10281      *
10282      * <p>Typically, this method should only be overridden by subclasses that provide a view
10283      * hierarchy (such as {@link ViewGroup}) - other classes should override
10284      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
10285      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
10286      *
10287      * <p>When overridden, it must:
10288      *
10289      * <ul>
10290      *   <li>Either call
10291      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
10292      *       set the {@link AutofillId} in the structure (for example, by calling
10293      *       {@code structure.setAutofillId(getAutofillId())}).
10294      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
10295      *       set, all views in the structure should be considered important for autofill,
10296      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
10297      *       respect this flag to provide a better user experience - this flag is typically used
10298      *       when an user explicitly requested autofill. If the flag is not set,
10299      *       then only views marked as important for autofill should be included in the
10300      *       structure - skipping non-important views optimizes the overall autofill performance.
10301      * </ul>
10302      *
10303      * @param structure fill in with structured view data for autofill purposes.
10304      * @param flags optional flags.
10305      *
10306      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
10307      */
dispatchProvideAutofillStructure(@onNull ViewStructure structure, @AutofillFlags int flags)10308     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
10309             @AutofillFlags int flags) {
10310         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
10311     }
10312 
dispatchProvideStructure(@onNull ViewStructure structure, @ViewStructureType int viewFor, @AutofillFlags int flags)10313     private void dispatchProvideStructure(@NonNull ViewStructure structure,
10314             @ViewStructureType int viewFor, @AutofillFlags int flags) {
10315         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
10316             structure.setAutofillId(getAutofillId());
10317             onProvideAutofillStructure(structure, flags);
10318             onProvideAutofillVirtualStructure(structure, flags);
10319         } else if (!isAssistBlocked()) {
10320             onProvideStructure(structure);
10321             onProvideVirtualStructure(structure);
10322         } else {
10323             structure.setClassName(getAccessibilityClassName().toString());
10324             structure.setAssistBlocked(true);
10325         }
10326     }
10327 
10328     /**
10329      * Dispatches the initial content capture events for a view structure.
10330      *
10331      * @hide
10332      */
dispatchInitialProvideContentCaptureStructure()10333     public void dispatchInitialProvideContentCaptureStructure() {
10334         AttachInfo ai = mAttachInfo;
10335         if (ai == null) {
10336             Log.w(CONTENT_CAPTURE_LOG_TAG,
10337                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
10338             return;
10339         }
10340         ContentCaptureManager ccm = ai.mContentCaptureManager;
10341         if (ccm == null) {
10342             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
10343                     + "no ContentCaptureManager for " + this);
10344             return;
10345         }
10346 
10347         // We must set it before checkign if the view itself is important, because it might
10348         // initially not be (for example, if it's empty), although that might change later (for
10349         // example, if important views are added)
10350         ai.mReadyForContentCaptureUpdates = true;
10351 
10352         if (!isImportantForContentCapture()) {
10353             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10354                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10355                         "dispatchProvideContentCaptureStructure(): decorView is not important");
10356             }
10357             return;
10358         }
10359 
10360         ai.mContentCaptureManager = ccm;
10361 
10362         ContentCaptureSession session = getContentCaptureSession();
10363         if (session == null) {
10364             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10365                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10366                         "dispatchProvideContentCaptureStructure(): no session for " + this);
10367             }
10368             return;
10369         }
10370 
10371         session.internalNotifyViewTreeEvent(/* started= */ true);
10372         try {
10373             dispatchProvideContentCaptureStructure();
10374         } finally {
10375             session.internalNotifyViewTreeEvent(/* started= */ false);
10376         }
10377     }
10378 
10379     /** @hide */
dispatchProvideContentCaptureStructure()10380     void dispatchProvideContentCaptureStructure() {
10381         ContentCaptureSession session = getContentCaptureSession();
10382         if (session != null) {
10383             ViewStructure structure = session.newViewStructure(this);
10384             onProvideContentCaptureStructure(structure, /* flags= */ 0);
10385             setNotifiedContentCaptureAppeared();
10386             session.notifyViewAppeared(structure);
10387         }
10388     }
10389 
10390     /**
10391      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
10392      *
10393      * Note: Called from the default {@link AccessibilityDelegate}.
10394      *
10395      * @hide
10396      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)10397     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
10398         if (mAttachInfo == null) {
10399             return;
10400         }
10401 
10402         Rect bounds = mAttachInfo.mTmpInvalRect;
10403 
10404         getDrawingRect(bounds);
10405         info.setBoundsInParent(bounds);
10406 
10407         getBoundsOnScreen(bounds, true);
10408         info.setBoundsInScreen(bounds);
10409 
10410         ViewParent parent = getParentForAccessibility();
10411         if (parent instanceof View) {
10412             info.setParent((View) parent);
10413         }
10414 
10415         if (mID != View.NO_ID) {
10416             View rootView = getRootView();
10417             if (rootView == null) {
10418                 rootView = this;
10419             }
10420 
10421             View label = rootView.findLabelForView(this, mID);
10422             if (label != null) {
10423                 info.setLabeledBy(label);
10424             }
10425 
10426             if ((mAttachInfo.mAccessibilityFetchFlags
10427                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
10428                     && Resources.resourceHasPackage(mID)) {
10429                 try {
10430                     String viewId = getResources().getResourceName(mID);
10431                     info.setViewIdResourceName(viewId);
10432                 } catch (Resources.NotFoundException nfe) {
10433                     /* ignore */
10434                 }
10435             }
10436         }
10437 
10438         if (mLabelForId != View.NO_ID) {
10439             View rootView = getRootView();
10440             if (rootView == null) {
10441                 rootView = this;
10442             }
10443             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
10444             if (labeled != null) {
10445                 info.setLabelFor(labeled);
10446             }
10447         }
10448 
10449         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
10450             View rootView = getRootView();
10451             if (rootView == null) {
10452                 rootView = this;
10453             }
10454             View next = rootView.findViewInsideOutShouldExist(this,
10455                     mAccessibilityTraversalBeforeId);
10456             if (next != null && next.includeForAccessibility()) {
10457                 info.setTraversalBefore(next);
10458             }
10459         }
10460 
10461         if (mAccessibilityTraversalAfterId != View.NO_ID) {
10462             View rootView = getRootView();
10463             if (rootView == null) {
10464                 rootView = this;
10465             }
10466             View next = rootView.findViewInsideOutShouldExist(this,
10467                     mAccessibilityTraversalAfterId);
10468             if (next != null && next.includeForAccessibility()) {
10469                 info.setTraversalAfter(next);
10470             }
10471         }
10472 
10473         info.setVisibleToUser(isVisibleToUser());
10474 
10475         info.setImportantForAccessibility(isImportantForAccessibility());
10476         info.setPackageName(mContext.getPackageName());
10477         info.setClassName(getAccessibilityClassName());
10478         info.setStateDescription(getStateDescription());
10479         info.setContentDescription(getContentDescription());
10480 
10481         info.setEnabled(isEnabled());
10482         info.setClickable(isClickable());
10483         info.setFocusable(isFocusable());
10484         info.setScreenReaderFocusable(isScreenReaderFocusable());
10485         info.setFocused(isFocused());
10486         info.setAccessibilityFocused(isAccessibilityFocused());
10487         info.setSelected(isSelected());
10488         info.setLongClickable(isLongClickable());
10489         info.setContextClickable(isContextClickable());
10490         info.setLiveRegion(getAccessibilityLiveRegion());
10491         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
10492             info.setTooltipText(mTooltipInfo.mTooltipText);
10493             info.addAction((mTooltipInfo.mTooltipPopup == null)
10494                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
10495                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
10496         }
10497 
10498         // TODO: These make sense only if we are in an AdapterView but all
10499         // views can be selected. Maybe from accessibility perspective
10500         // we should report as selectable view in an AdapterView.
10501         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
10502         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
10503 
10504         if (isFocusable()) {
10505             if (isFocused()) {
10506                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
10507             } else {
10508                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
10509             }
10510         }
10511 
10512         if (!isAccessibilityFocused()) {
10513             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
10514         } else {
10515             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
10516         }
10517 
10518         if (isClickable() && isEnabled()) {
10519             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
10520         }
10521 
10522         if (isLongClickable() && isEnabled()) {
10523             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
10524         }
10525 
10526         if (isContextClickable() && isEnabled()) {
10527             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
10528         }
10529 
10530         CharSequence text = getIterableTextForAccessibility();
10531         if (text != null && text.length() > 0) {
10532             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
10533 
10534             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
10535             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
10536             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
10537             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
10538                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
10539                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
10540         }
10541 
10542         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
10543         populateAccessibilityNodeInfoDrawingOrderInParent(info);
10544         info.setPaneTitle(mAccessibilityPaneTitle);
10545         info.setHeading(isAccessibilityHeading());
10546 
10547         if (mTouchDelegate != null) {
10548             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
10549         }
10550 
10551         if (startedSystemDragForAccessibility()) {
10552             info.addAction(AccessibilityAction.ACTION_DRAG_CANCEL);
10553         }
10554 
10555         if (canAcceptAccessibilityDrop()) {
10556             info.addAction(AccessibilityAction.ACTION_DRAG_DROP);
10557         }
10558     }
10559 
10560 
10561     /**
10562      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
10563      * additional data.
10564      * <p>
10565      * This method only needs overloading if the node is marked as having extra data available.
10566      * </p>
10567      *
10568      * @param info The info to which to add the extra data. Never {@code null}.
10569      * @param extraDataKey A key specifying the type of extra data to add to the info. The
10570      *                     extra data should be added to the {@link Bundle} returned by
10571      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
10572      *                     {@code null}.
10573      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
10574      *                  {@code null} if the service provided no arguments.
10575      *
10576      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
10577      */
addExtraDataToAccessibilityNodeInfo( @onNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)10578     public void addExtraDataToAccessibilityNodeInfo(
10579             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
10580             @Nullable Bundle arguments) {
10581     }
10582 
10583     /**
10584      * Determine the order in which this view will be drawn relative to its siblings for a11y
10585      *
10586      * @param info The info whose drawing order should be populated
10587      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)10588     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
10589         /*
10590          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
10591          * drawing order may not be well-defined, and some Views with custom drawing order may
10592          * not be initialized sufficiently to respond properly getChildDrawingOrder.
10593          */
10594         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
10595             info.setDrawingOrder(0);
10596             return;
10597         }
10598         int drawingOrderInParent = 1;
10599         // Iterate up the hierarchy if parents are not important for a11y
10600         View viewAtDrawingLevel = this;
10601         final ViewParent parent = getParentForAccessibility();
10602         while (viewAtDrawingLevel != parent) {
10603             final ViewParent currentParent = viewAtDrawingLevel.getParent();
10604             if (!(currentParent instanceof ViewGroup)) {
10605                 // Should only happen for the Decor
10606                 drawingOrderInParent = 0;
10607                 break;
10608             } else {
10609                 final ViewGroup parentGroup = (ViewGroup) currentParent;
10610                 final int childCount = parentGroup.getChildCount();
10611                 if (childCount > 1) {
10612                     List<View> preorderedList = parentGroup.buildOrderedChildList();
10613                     if (preorderedList != null) {
10614                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
10615                         for (int i = 0; i < childDrawIndex; i++) {
10616                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
10617                         }
10618                         preorderedList.clear();
10619                     } else {
10620                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
10621                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
10622                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
10623                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
10624                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
10625                         if (childDrawIndex != 0) {
10626                             for (int i = 0; i < numChildrenToIterate; i++) {
10627                                 final int otherDrawIndex = (customOrder ?
10628                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
10629                                 if (otherDrawIndex < childDrawIndex) {
10630                                     drawingOrderInParent +=
10631                                             numViewsForAccessibility(parentGroup.getChildAt(i));
10632                                 }
10633                             }
10634                         }
10635                     }
10636                 }
10637             }
10638             viewAtDrawingLevel = (View) currentParent;
10639         }
10640         info.setDrawingOrder(drawingOrderInParent);
10641     }
10642 
numViewsForAccessibility(View view)10643     private static int numViewsForAccessibility(View view) {
10644         if (view != null) {
10645             if (view.includeForAccessibility()) {
10646                 return 1;
10647             } else if (view instanceof ViewGroup) {
10648                 return ((ViewGroup) view).getNumChildrenForAccessibility();
10649             }
10650         }
10651         return 0;
10652     }
10653 
findLabelForView(View view, int labeledId)10654     private View findLabelForView(View view, int labeledId) {
10655         if (mMatchLabelForPredicate == null) {
10656             mMatchLabelForPredicate = new MatchLabelForPredicate();
10657         }
10658         mMatchLabelForPredicate.mLabeledId = labeledId;
10659         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
10660     }
10661 
10662     /**
10663      * Computes whether this virtual autofill view is visible to the user.
10664      *
10665      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
10666      * view must override it.
10667      *
10668      * @return Whether the view is visible on the screen.
10669      */
isVisibleToUserForAutofill(int virtualId)10670     public boolean isVisibleToUserForAutofill(int virtualId) {
10671         if (mContext.isAutofillCompatibilityEnabled()) {
10672             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10673             if (provider != null) {
10674                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
10675                 if (node != null) {
10676                     return node.isVisibleToUser();
10677                 }
10678                 // if node is null, assume it's not visible anymore
10679             } else {
10680                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
10681             }
10682             return false;
10683         }
10684         return true;
10685     }
10686 
10687     /**
10688      * Computes whether this view is visible to the user. Such a view is
10689      * attached, visible, all its predecessors are visible, it is not clipped
10690      * entirely by its predecessors, and has an alpha greater than zero.
10691      *
10692      * @return Whether the view is visible on the screen.
10693      *
10694      * @hide
10695      */
10696     @UnsupportedAppUsage
isVisibleToUser()10697     public boolean isVisibleToUser() {
10698         return isVisibleToUser(null);
10699     }
10700 
10701     /**
10702      * Computes whether the given portion of this view is visible to the user.
10703      * Such a view is attached, visible, all its predecessors are visible,
10704      * has an alpha greater than zero, and the specified portion is not
10705      * clipped entirely by its predecessors.
10706      *
10707      * @param boundInView the portion of the view to test; coordinates should be relative; may be
10708      *                    <code>null</code>, and the entire view will be tested in this case.
10709      *                    When <code>true</code> is returned by the function, the actual visible
10710      *                    region will be stored in this parameter; that is, if boundInView is fully
10711      *                    contained within the view, no modification will be made, otherwise regions
10712      *                    outside of the visible area of the view will be clipped.
10713      *
10714      * @return Whether the specified portion of the view is visible on the screen.
10715      *
10716      * @hide
10717      */
10718     @UnsupportedAppUsage(trackingBug = 171933273)
isVisibleToUser(Rect boundInView)10719     protected boolean isVisibleToUser(Rect boundInView) {
10720         if (mAttachInfo != null) {
10721             // Attached to invisible window means this view is not visible.
10722             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
10723                 return false;
10724             }
10725             // An invisible predecessor or one with alpha zero means
10726             // that this view is not visible to the user.
10727             Object current = this;
10728             while (current instanceof View) {
10729                 View view = (View) current;
10730                 // We have attach info so this view is attached and there is no
10731                 // need to check whether we reach to ViewRootImpl on the way up.
10732                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
10733                         view.getVisibility() != VISIBLE) {
10734                     return false;
10735                 }
10736                 current = view.mParent;
10737             }
10738             // Check if the view is entirely covered by its predecessors.
10739             Rect visibleRect = mAttachInfo.mTmpInvalRect;
10740             Point offset = mAttachInfo.mPoint;
10741             if (!getGlobalVisibleRect(visibleRect, offset)) {
10742                 return false;
10743             }
10744             // Check if the visible portion intersects the rectangle of interest.
10745             if (boundInView != null) {
10746                 visibleRect.offset(-offset.x, -offset.y);
10747                 return boundInView.intersect(visibleRect);
10748             }
10749             return true;
10750         }
10751         return false;
10752     }
10753 
10754     /**
10755      * Returns the delegate for implementing accessibility support via
10756      * composition. For more details see {@link AccessibilityDelegate}.
10757      *
10758      * @return The delegate, or null if none set.
10759      */
getAccessibilityDelegate()10760     public AccessibilityDelegate getAccessibilityDelegate() {
10761         return mAccessibilityDelegate;
10762     }
10763 
10764     /**
10765      * Sets a delegate for implementing accessibility support via composition
10766      * (as opposed to inheritance). For more details, see
10767      * {@link AccessibilityDelegate}.
10768      * <p>
10769      * <strong>Note:</strong> On platform versions prior to
10770      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
10771      * views in the {@code android.widget.*} package are called <i>before</i>
10772      * host methods. This prevents certain properties such as class name from
10773      * being modified by overriding
10774      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
10775      * as any changes will be overwritten by the host class.
10776      * <p>
10777      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
10778      * methods are called <i>after</i> host methods, which all properties to be
10779      * modified without being overwritten by the host class.
10780      *
10781      * @param delegate the object to which accessibility method calls should be
10782      *                 delegated
10783      * @see AccessibilityDelegate
10784      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)10785     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
10786         mAccessibilityDelegate = delegate;
10787     }
10788 
10789     /**
10790      * Gets the provider for managing a virtual view hierarchy rooted at this View
10791      * and reported to {@link android.accessibilityservice.AccessibilityService}s
10792      * that explore the window content.
10793      * <p>
10794      * If this method returns an instance, this instance is responsible for managing
10795      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
10796      * View including the one representing the View itself. Similarly the returned
10797      * instance is responsible for performing accessibility actions on any virtual
10798      * view or the root view itself.
10799      * </p>
10800      * <p>
10801      * If an {@link AccessibilityDelegate} has been specified via calling
10802      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10803      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
10804      * is responsible for handling this call.
10805      * </p>
10806      *
10807      * @return The provider.
10808      *
10809      * @see AccessibilityNodeProvider
10810      */
getAccessibilityNodeProvider()10811     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
10812         if (mAccessibilityDelegate != null) {
10813             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
10814         } else {
10815             return null;
10816         }
10817     }
10818 
10819     /**
10820      * Gets the unique identifier of this view on the screen for accessibility purposes.
10821      *
10822      * @return The view accessibility id.
10823      *
10824      * @hide
10825      */
10826     @UnsupportedAppUsage
getAccessibilityViewId()10827     public int getAccessibilityViewId() {
10828         if (mAccessibilityViewId == NO_ID) {
10829             mAccessibilityViewId = sNextAccessibilityViewId++;
10830         }
10831         return mAccessibilityViewId;
10832     }
10833 
10834     /**
10835      * Gets the unique identifier of this view on the screen for autofill purposes.
10836      *
10837      * @return The view autofill id.
10838      *
10839      * @hide
10840      */
getAutofillViewId()10841     public int getAutofillViewId() {
10842         if (mAutofillViewId == NO_ID) {
10843             mAutofillViewId = mContext.getNextAutofillId();
10844         }
10845         return mAutofillViewId;
10846     }
10847 
10848     /**
10849      * Gets the unique identifier of the window in which this View resides.
10850      *
10851      * @return The window accessibility id.
10852      *
10853      * @hide
10854      */
getAccessibilityWindowId()10855     public int getAccessibilityWindowId() {
10856         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
10857                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
10858     }
10859 
10860     /**
10861      * Returns the {@link View}'s state description.
10862      * <p>
10863      * <strong>Note:</strong> Do not override this method, as it will have no
10864      * effect on the state description presented to accessibility services.
10865      * You must call {@link #setStateDescription(CharSequence)} to modify the
10866      * state description.
10867      *
10868      * @return the state description
10869      * @see #setStateDescription(CharSequence)
10870      */
10871     @ViewDebug.ExportedProperty(category = "accessibility")
getStateDescription()10872     public final @Nullable CharSequence getStateDescription() {
10873         return mStateDescription;
10874     }
10875 
10876     /**
10877      * Returns the {@link View}'s content description.
10878      * <p>
10879      * <strong>Note:</strong> Do not override this method, as it will have no
10880      * effect on the content description presented to accessibility services.
10881      * You must call {@link #setContentDescription(CharSequence)} to modify the
10882      * content description.
10883      *
10884      * @return the content description
10885      * @see #setContentDescription(CharSequence)
10886      * @attr ref android.R.styleable#View_contentDescription
10887      */
10888     @ViewDebug.ExportedProperty(category = "accessibility")
10889     @InspectableProperty
getContentDescription()10890     public CharSequence getContentDescription() {
10891         return mContentDescription;
10892     }
10893 
10894     /**
10895      * Sets the {@link View}'s state description.
10896      * <p>
10897      * A state description briefly describes the states of the view and is primarily used
10898      * for accessibility support to determine how the states of a view should be presented to
10899      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
10900      * it is used for customized state description (for example, "wifi, connected, three bars").
10901      * State description changes frequently while content description should change less often.
10902      * State description should be localized. For android widgets which have default state
10903      * descriptions, app developers can call this method to override the state descriptions.
10904      * Setting state description to null restores the default behavior.
10905      *
10906      * @param stateDescription The state description.
10907      * @see #getStateDescription()
10908      */
10909     @RemotableViewMethod
setStateDescription(@ullable CharSequence stateDescription)10910     public void setStateDescription(@Nullable CharSequence stateDescription) {
10911         if (mStateDescription == null) {
10912             if (stateDescription == null) {
10913                 return;
10914             }
10915         } else if (mStateDescription.equals(stateDescription)) {
10916             return;
10917         }
10918         mStateDescription = stateDescription;
10919         if (!TextUtils.isEmpty(stateDescription)
10920                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10921             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10922         }
10923         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10924             AccessibilityEvent event = AccessibilityEvent.obtain();
10925             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
10926             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
10927             sendAccessibilityEventUnchecked(event);
10928         }
10929     }
10930 
10931     /**
10932      * Sets the {@link View}'s content description.
10933      * <p>
10934      * A content description briefly describes the view and is primarily used
10935      * for accessibility support to determine how a view should be presented to
10936      * the user. In the case of a view with no textual representation, such as
10937      * {@link android.widget.ImageButton}, a useful content description
10938      * explains what the view does. For example, an image button with a phone
10939      * icon that is used to place a call may use "Call" as its content
10940      * description. An image of a floppy disk that is used to save a file may
10941      * use "Save".
10942      *
10943      * @param contentDescription The content description.
10944      * @see #getContentDescription()
10945      * @attr ref android.R.styleable#View_contentDescription
10946      */
10947     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)10948     public void setContentDescription(CharSequence contentDescription) {
10949         if (mContentDescription == null) {
10950             if (contentDescription == null) {
10951                 return;
10952             }
10953         } else if (mContentDescription.equals(contentDescription)) {
10954             return;
10955         }
10956         mContentDescription = contentDescription;
10957         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
10958         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10959             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10960             notifySubtreeAccessibilityStateChangedIfNeeded();
10961         } else {
10962             notifyViewAccessibilityStateChangedIfNeeded(
10963                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
10964         }
10965     }
10966 
10967     /**
10968      * Sets the id of a view before which this one is visited in accessibility traversal.
10969      * A screen-reader must visit the content of this view before the content of the one
10970      * it precedes. For example, if view B is set to be before view A, then a screen-reader
10971      * will traverse the entire content of B before traversing the entire content of A,
10972      * regardles of what traversal strategy it is using.
10973      * <p>
10974      * Views that do not have specified before/after relationships are traversed in order
10975      * determined by the screen-reader.
10976      * </p>
10977      * <p>
10978      * Setting that this view is before a view that is not important for accessibility
10979      * or if this view is not important for accessibility will have no effect as the
10980      * screen-reader is not aware of unimportant views.
10981      * </p>
10982      *
10983      * @param beforeId The id of a view this one precedes in accessibility traversal.
10984      *
10985      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
10986      *
10987      * @see #setImportantForAccessibility(int)
10988      */
10989     @RemotableViewMethod
setAccessibilityTraversalBefore(@dRes int beforeId)10990     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
10991         if (mAccessibilityTraversalBeforeId == beforeId) {
10992             return;
10993         }
10994         mAccessibilityTraversalBeforeId = beforeId;
10995         notifyViewAccessibilityStateChangedIfNeeded(
10996                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10997     }
10998 
10999     /**
11000      * Gets the id of a view before which this one is visited in accessibility traversal.
11001      *
11002      * @return The id of a view this one precedes in accessibility traversal if
11003      *         specified, otherwise {@link #NO_ID}.
11004      *
11005      * @see #setAccessibilityTraversalBefore(int)
11006      */
11007     @IdRes
11008     @InspectableProperty
getAccessibilityTraversalBefore()11009     public int getAccessibilityTraversalBefore() {
11010         return mAccessibilityTraversalBeforeId;
11011     }
11012 
11013     /**
11014      * Sets the id of a view after which this one is visited in accessibility traversal.
11015      * A screen-reader must visit the content of the other view before the content of this
11016      * one. For example, if view B is set to be after view A, then a screen-reader
11017      * will traverse the entire content of A before traversing the entire content of B,
11018      * regardles of what traversal strategy it is using.
11019      * <p>
11020      * Views that do not have specified before/after relationships are traversed in order
11021      * determined by the screen-reader.
11022      * </p>
11023      * <p>
11024      * Setting that this view is after a view that is not important for accessibility
11025      * or if this view is not important for accessibility will have no effect as the
11026      * screen-reader is not aware of unimportant views.
11027      * </p>
11028      *
11029      * @param afterId The id of a view this one succedees in accessibility traversal.
11030      *
11031      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
11032      *
11033      * @see #setImportantForAccessibility(int)
11034      */
11035     @RemotableViewMethod
setAccessibilityTraversalAfter(@dRes int afterId)11036     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
11037         if (mAccessibilityTraversalAfterId == afterId) {
11038             return;
11039         }
11040         mAccessibilityTraversalAfterId = afterId;
11041         notifyViewAccessibilityStateChangedIfNeeded(
11042                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11043     }
11044 
11045     /**
11046      * Gets the id of a view after which this one is visited in accessibility traversal.
11047      *
11048      * @return The id of a view this one succeedes in accessibility traversal if
11049      *         specified, otherwise {@link #NO_ID}.
11050      *
11051      * @see #setAccessibilityTraversalAfter(int)
11052      */
11053     @IdRes
11054     @InspectableProperty
getAccessibilityTraversalAfter()11055     public int getAccessibilityTraversalAfter() {
11056         return mAccessibilityTraversalAfterId;
11057     }
11058 
11059     /**
11060      * Gets the id of a view for which this view serves as a label for
11061      * accessibility purposes.
11062      *
11063      * @return The labeled view id.
11064      */
11065     @IdRes
11066     @ViewDebug.ExportedProperty(category = "accessibility")
11067     @InspectableProperty
getLabelFor()11068     public int getLabelFor() {
11069         return mLabelForId;
11070     }
11071 
11072     /**
11073      * Sets the id of a view for which this view serves as a label for
11074      * accessibility purposes.
11075      *
11076      * @param id The labeled view id.
11077      */
11078     @RemotableViewMethod
setLabelFor(@dRes int id)11079     public void setLabelFor(@IdRes int id) {
11080         if (mLabelForId == id) {
11081             return;
11082         }
11083         mLabelForId = id;
11084         if (mLabelForId != View.NO_ID
11085                 && mID == View.NO_ID) {
11086             mID = generateViewId();
11087         }
11088         notifyViewAccessibilityStateChangedIfNeeded(
11089                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11090     }
11091 
11092     /**
11093      * Invoked whenever this view loses focus, either by losing window focus or by losing
11094      * focus within its window. This method can be used to clear any state tied to the
11095      * focus. For instance, if a button is held pressed with the trackball and the window
11096      * loses focus, this method can be used to cancel the press.
11097      *
11098      * Subclasses of View overriding this method should always call super.onFocusLost().
11099      *
11100      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
11101      * @see #onWindowFocusChanged(boolean)
11102      *
11103      * @hide pending API council approval
11104      */
11105     @CallSuper
11106     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onFocusLost()11107     protected void onFocusLost() {
11108         resetPressedState();
11109     }
11110 
resetPressedState()11111     private void resetPressedState() {
11112         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11113             return;
11114         }
11115 
11116         if (isPressed()) {
11117             setPressed(false);
11118 
11119             if (!mHasPerformedLongPress) {
11120                 removeLongPressCallback();
11121             }
11122         }
11123     }
11124 
11125     /**
11126      * Returns true if this view has focus
11127      *
11128      * @return True if this view has focus, false otherwise.
11129      */
11130     @ViewDebug.ExportedProperty(category = "focus")
11131     @InspectableProperty(hasAttributeId = false)
isFocused()11132     public boolean isFocused() {
11133         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
11134     }
11135 
11136     /**
11137      * Find the view in the hierarchy rooted at this view that currently has
11138      * focus.
11139      *
11140      * @return The view that currently has focus, or null if no focused view can
11141      *         be found.
11142      */
findFocus()11143     public View findFocus() {
11144         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
11145     }
11146 
11147     /**
11148      * Indicates whether this view is one of the set of scrollable containers in
11149      * its window.
11150      *
11151      * @return whether this view is one of the set of scrollable containers in
11152      * its window
11153      *
11154      * @attr ref android.R.styleable#View_isScrollContainer
11155      */
11156     @InspectableProperty(name = "isScrollContainer")
isScrollContainer()11157     public boolean isScrollContainer() {
11158         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
11159     }
11160 
11161     /**
11162      * Change whether this view is one of the set of scrollable containers in
11163      * its window.  This will be used to determine whether the window can
11164      * resize or must pan when a soft input area is open -- scrollable
11165      * containers allow the window to use resize mode since the container
11166      * will appropriately shrink.
11167      *
11168      * @attr ref android.R.styleable#View_isScrollContainer
11169      */
setScrollContainer(boolean isScrollContainer)11170     public void setScrollContainer(boolean isScrollContainer) {
11171         if (isScrollContainer) {
11172             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
11173                 mAttachInfo.mScrollContainers.add(this);
11174                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
11175             }
11176             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
11177         } else {
11178             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
11179                 mAttachInfo.mScrollContainers.remove(this);
11180             }
11181             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
11182         }
11183     }
11184 
11185     /**
11186      * Returns the quality of the drawing cache.
11187      *
11188      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11189      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11190      *
11191      * @see #setDrawingCacheQuality(int)
11192      * @see #setDrawingCacheEnabled(boolean)
11193      * @see #isDrawingCacheEnabled()
11194      *
11195      * @attr ref android.R.styleable#View_drawingCacheQuality
11196      *
11197      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11198      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11199      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11200      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11201      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11202      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11203      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11204      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11205      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11206      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11207      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11208      * reports or unit testing the {@link PixelCopy} API is recommended.
11209      */
11210     @Deprecated
11211     @DrawingCacheQuality
11212     @InspectableProperty(enumMapping = {
11213             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
11214             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
11215             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
11216     })
getDrawingCacheQuality()11217     public int getDrawingCacheQuality() {
11218         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
11219     }
11220 
11221     /**
11222      * Set the drawing cache quality of this view. This value is used only when the
11223      * drawing cache is enabled
11224      *
11225      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11226      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11227      *
11228      * @see #getDrawingCacheQuality()
11229      * @see #setDrawingCacheEnabled(boolean)
11230      * @see #isDrawingCacheEnabled()
11231      *
11232      * @attr ref android.R.styleable#View_drawingCacheQuality
11233      *
11234      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11235      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11236      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11237      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11238      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11239      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11240      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11241      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11242      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11243      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11244      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11245      * reports or unit testing the {@link PixelCopy} API is recommended.
11246      */
11247     @Deprecated
setDrawingCacheQuality(@rawingCacheQuality int quality)11248     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
11249         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
11250     }
11251 
11252     /**
11253      * Returns whether the screen should remain on, corresponding to the current
11254      * value of {@link #KEEP_SCREEN_ON}.
11255      *
11256      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
11257      *
11258      * @see #setKeepScreenOn(boolean)
11259      *
11260      * @attr ref android.R.styleable#View_keepScreenOn
11261      */
11262     @InspectableProperty
getKeepScreenOn()11263     public boolean getKeepScreenOn() {
11264         return (mViewFlags & KEEP_SCREEN_ON) != 0;
11265     }
11266 
11267     /**
11268      * Controls whether the screen should remain on, modifying the
11269      * value of {@link #KEEP_SCREEN_ON}.
11270      *
11271      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
11272      *
11273      * @see #getKeepScreenOn()
11274      *
11275      * @attr ref android.R.styleable#View_keepScreenOn
11276      */
setKeepScreenOn(boolean keepScreenOn)11277     public void setKeepScreenOn(boolean keepScreenOn) {
11278         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
11279     }
11280 
11281     /**
11282      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11283      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11284      *
11285      * @attr ref android.R.styleable#View_nextFocusLeft
11286      */
11287     @IdRes
11288     @InspectableProperty(name = "nextFocusLeft")
getNextFocusLeftId()11289     public int getNextFocusLeftId() {
11290         return mNextFocusLeftId;
11291     }
11292 
11293     /**
11294      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11295      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
11296      * decide automatically.
11297      *
11298      * @attr ref android.R.styleable#View_nextFocusLeft
11299      */
setNextFocusLeftId(@dRes int nextFocusLeftId)11300     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
11301         mNextFocusLeftId = nextFocusLeftId;
11302     }
11303 
11304     /**
11305      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11306      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11307      *
11308      * @attr ref android.R.styleable#View_nextFocusRight
11309      */
11310     @IdRes
11311     @InspectableProperty(name = "nextFocusRight")
getNextFocusRightId()11312     public int getNextFocusRightId() {
11313         return mNextFocusRightId;
11314     }
11315 
11316     /**
11317      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11318      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
11319      * decide automatically.
11320      *
11321      * @attr ref android.R.styleable#View_nextFocusRight
11322      */
setNextFocusRightId(@dRes int nextFocusRightId)11323     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
11324         mNextFocusRightId = nextFocusRightId;
11325     }
11326 
11327     /**
11328      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11329      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11330      *
11331      * @attr ref android.R.styleable#View_nextFocusUp
11332      */
11333     @IdRes
11334     @InspectableProperty(name = "nextFocusUp")
getNextFocusUpId()11335     public int getNextFocusUpId() {
11336         return mNextFocusUpId;
11337     }
11338 
11339     /**
11340      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11341      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
11342      * decide automatically.
11343      *
11344      * @attr ref android.R.styleable#View_nextFocusUp
11345      */
setNextFocusUpId(@dRes int nextFocusUpId)11346     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
11347         mNextFocusUpId = nextFocusUpId;
11348     }
11349 
11350     /**
11351      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11352      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11353      *
11354      * @attr ref android.R.styleable#View_nextFocusDown
11355      */
11356     @IdRes
11357     @InspectableProperty(name = "nextFocusDown")
getNextFocusDownId()11358     public int getNextFocusDownId() {
11359         return mNextFocusDownId;
11360     }
11361 
11362     /**
11363      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11364      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
11365      * decide automatically.
11366      *
11367      * @attr ref android.R.styleable#View_nextFocusDown
11368      */
setNextFocusDownId(@dRes int nextFocusDownId)11369     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
11370         mNextFocusDownId = nextFocusDownId;
11371     }
11372 
11373     /**
11374      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11375      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11376      *
11377      * @attr ref android.R.styleable#View_nextFocusForward
11378      */
11379     @IdRes
11380     @InspectableProperty(name = "nextFocusForward")
getNextFocusForwardId()11381     public int getNextFocusForwardId() {
11382         return mNextFocusForwardId;
11383     }
11384 
11385     /**
11386      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11387      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
11388      * decide automatically.
11389      *
11390      * @attr ref android.R.styleable#View_nextFocusForward
11391      */
setNextFocusForwardId(@dRes int nextFocusForwardId)11392     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
11393         mNextFocusForwardId = nextFocusForwardId;
11394     }
11395 
11396     /**
11397      * Gets the id of the root of the next keyboard navigation cluster.
11398      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
11399      * decide automatically.
11400      *
11401      * @attr ref android.R.styleable#View_nextClusterForward
11402      */
11403     @IdRes
11404     @InspectableProperty(name = "nextClusterForward")
getNextClusterForwardId()11405     public int getNextClusterForwardId() {
11406         return mNextClusterForwardId;
11407     }
11408 
11409     /**
11410      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
11411      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
11412      * decide automatically.
11413      *
11414      * @attr ref android.R.styleable#View_nextClusterForward
11415      */
setNextClusterForwardId(@dRes int nextClusterForwardId)11416     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
11417         mNextClusterForwardId = nextClusterForwardId;
11418     }
11419 
11420     /**
11421      * Returns the visibility of this view and all of its ancestors
11422      *
11423      * @return True if this view and all of its ancestors are {@link #VISIBLE}
11424      */
isShown()11425     public boolean isShown() {
11426         View current = this;
11427         //noinspection ConstantConditions
11428         do {
11429             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
11430                 return false;
11431             }
11432             ViewParent parent = current.mParent;
11433             if (parent == null) {
11434                 return false; // We are not attached to the view root
11435             }
11436             if (!(parent instanceof View)) {
11437                 return true;
11438             }
11439             current = (View) parent;
11440         } while (current != null);
11441 
11442         return false;
11443     }
11444 
detached()11445     private boolean detached() {
11446         View current = this;
11447         //noinspection ConstantConditions
11448         do {
11449             if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
11450                 return true;
11451             }
11452             ViewParent parent = current.mParent;
11453             if (parent == null) {
11454                 return false;
11455             }
11456             if (!(parent instanceof View)) {
11457                 return false;
11458             }
11459             current = (View) parent;
11460         } while (current != null);
11461 
11462         return false;
11463     }
11464 
11465     /**
11466      * Called by the view hierarchy when the content insets for a window have
11467      * changed, to allow it to adjust its content to fit within those windows.
11468      * The content insets tell you the space that the status bar, input method,
11469      * and other system windows infringe on the application's window.
11470      *
11471      * <p>You do not normally need to deal with this function, since the default
11472      * window decoration given to applications takes care of applying it to the
11473      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
11474      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
11475      * and your content can be placed under those system elements.  You can then
11476      * use this method within your view hierarchy if you have parts of your UI
11477      * which you would like to ensure are not being covered.
11478      *
11479      * <p>The default implementation of this method simply applies the content
11480      * insets to the view's padding, consuming that content (modifying the
11481      * insets to be 0), and returning true.  This behavior is off by default, but can
11482      * be enabled through {@link #setFitsSystemWindows(boolean)}.
11483      *
11484      * <p>This function's traversal down the hierarchy is depth-first.  The same content
11485      * insets object is propagated down the hierarchy, so any changes made to it will
11486      * be seen by all following views (including potentially ones above in
11487      * the hierarchy since this is a depth-first traversal).  The first view
11488      * that returns true will abort the entire traversal.
11489      *
11490      * <p>The default implementation works well for a situation where it is
11491      * used with a container that covers the entire window, allowing it to
11492      * apply the appropriate insets to its content on all edges.  If you need
11493      * a more complicated layout (such as two different views fitting system
11494      * windows, one on the top of the window, and one on the bottom),
11495      * you can override the method and handle the insets however you would like.
11496      * Note that the insets provided by the framework are always relative to the
11497      * far edges of the window, not accounting for the location of the called view
11498      * within that window.  (In fact when this method is called you do not yet know
11499      * where the layout will place the view, as it is done before layout happens.)
11500      *
11501      * <p>Note: unlike many View methods, there is no dispatch phase to this
11502      * call.  If you are overriding it in a ViewGroup and want to allow the
11503      * call to continue to your children, you must be sure to call the super
11504      * implementation.
11505      *
11506      * <p>Here is a sample layout that makes use of fitting system windows
11507      * to have controls for a video view placed inside of the window decorations
11508      * that it hides and shows.  This can be used with code like the second
11509      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
11510      *
11511      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
11512      *
11513      * @param insets Current content insets of the window.  Prior to
11514      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
11515      * the insets or else you and Android will be unhappy.
11516      *
11517      * @return {@code true} if this view applied the insets and it should not
11518      * continue propagating further down the hierarchy, {@code false} otherwise.
11519      * @see #getFitsSystemWindows()
11520      * @see #setFitsSystemWindows(boolean)
11521      * @see #setSystemUiVisibility(int)
11522      *
11523      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
11524      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
11525      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
11526      * to implement handling their own insets.
11527      */
11528     @Deprecated
fitSystemWindows(Rect insets)11529     protected boolean fitSystemWindows(Rect insets) {
11530         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
11531             if (insets == null) {
11532                 // Null insets by definition have already been consumed.
11533                 // This call cannot apply insets since there are none to apply,
11534                 // so return false.
11535                 return false;
11536             }
11537             // If we're not in the process of dispatching the newer apply insets call,
11538             // that means we're not in the compatibility path. Dispatch into the newer
11539             // apply insets path and take things from there.
11540             try {
11541                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
11542                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
11543             } finally {
11544                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
11545             }
11546         } else {
11547             // We're being called from the newer apply insets path.
11548             // Perform the standard fallback behavior.
11549             return fitSystemWindowsInt(insets);
11550         }
11551     }
11552 
fitSystemWindowsInt(Rect insets)11553     private boolean fitSystemWindowsInt(Rect insets) {
11554         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
11555             Rect localInsets = sThreadLocal.get();
11556             boolean res = computeFitSystemWindows(insets, localInsets);
11557             applyInsets(localInsets);
11558             return res;
11559         }
11560         return false;
11561     }
11562 
applyInsets(Rect insets)11563     private void applyInsets(Rect insets) {
11564         mUserPaddingStart = UNDEFINED_PADDING;
11565         mUserPaddingEnd = UNDEFINED_PADDING;
11566         mUserPaddingLeftInitial = insets.left;
11567         mUserPaddingRightInitial = insets.right;
11568         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
11569     }
11570 
11571     /**
11572      * Called when the view should apply {@link WindowInsets} according to its internal policy.
11573      *
11574      * <p>This method should be overridden by views that wish to apply a policy different from or
11575      * in addition to the default behavior. Clients that wish to force a view subtree
11576      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
11577      *
11578      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
11579      * it will be called during dispatch instead of this method. The listener may optionally
11580      * call this method from its own implementation if it wishes to apply the view's default
11581      * insets policy in addition to its own.</p>
11582      *
11583      * <p>Implementations of this method should either return the insets parameter unchanged
11584      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
11585      * that this view applied itself. This allows new inset types added in future platform
11586      * versions to pass through existing implementations unchanged without being erroneously
11587      * consumed.</p>
11588      *
11589      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
11590      * property is set then the view will consume the system window insets and apply them
11591      * as padding for the view.</p>
11592      *
11593      * @param insets Insets to apply
11594      * @return The supplied insets with any applied insets consumed
11595      */
onApplyWindowInsets(WindowInsets insets)11596     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
11597         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11598                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
11599             return onApplyFrameworkOptionalFitSystemWindows(insets);
11600         }
11601         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
11602             // We weren't called from within a direct call to fitSystemWindows,
11603             // call into it as a fallback in case we're in a class that overrides it
11604             // and has logic to perform.
11605             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
11606                 return insets.consumeSystemWindowInsets();
11607             }
11608         } else {
11609             // We were called from within a direct call to fitSystemWindows.
11610             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
11611                 return insets.consumeSystemWindowInsets();
11612             }
11613         }
11614         return insets;
11615     }
11616 
onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets)11617     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
11618         Rect localInsets = sThreadLocal.get();
11619         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
11620         applyInsets(localInsets);
11621         return result;
11622     }
11623 
11624     /**
11625      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
11626      * window insets to this view. The listener's
11627      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
11628      * method will be called instead of the view's
11629      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
11630      *
11631      * @param listener Listener to set
11632      *
11633      * @see #onApplyWindowInsets(WindowInsets)
11634      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)11635     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
11636         getListenerInfo().mOnApplyWindowInsetsListener = listener;
11637     }
11638 
11639     /**
11640      * Request to apply the given window insets to this view or another view in its subtree.
11641      *
11642      * <p>This method should be called by clients wishing to apply insets corresponding to areas
11643      * obscured by window decorations or overlays. This can include the status and navigation bars,
11644      * action bars, input methods and more. New inset categories may be added in the future.
11645      * The method returns the insets provided minus any that were applied by this view or its
11646      * children.</p>
11647      *
11648      * <p>Clients wishing to provide custom behavior should override the
11649      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
11650      * {@link OnApplyWindowInsetsListener} via the
11651      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
11652      * method.</p>
11653      *
11654      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
11655      * </p>
11656      *
11657      * @param insets Insets to apply
11658      * @return The provided insets minus the insets that were consumed
11659      */
dispatchApplyWindowInsets(WindowInsets insets)11660     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
11661         try {
11662             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
11663             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
11664                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
11665             } else {
11666                 return onApplyWindowInsets(insets);
11667             }
11668         } finally {
11669             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
11670         }
11671     }
11672 
11673     /**
11674      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
11675      * cause insets.
11676      * <p>
11677      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
11678      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
11679      * this view.
11680      * </p>
11681      * @param callback The callback to set.
11682      */
setWindowInsetsAnimationCallback( @ullable WindowInsetsAnimation.Callback callback)11683     public void setWindowInsetsAnimationCallback(
11684             @Nullable WindowInsetsAnimation.Callback callback) {
11685         getListenerInfo().mWindowInsetsAnimationCallback = callback;
11686     }
11687 
11688     /**
11689      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
11690      *         or view tree of the sub-hierarchy {@code false} otherwise.
11691      * @hide
11692      */
hasWindowInsetsAnimationCallback()11693     public boolean hasWindowInsetsAnimationCallback() {
11694         return getListenerInfo().mWindowInsetsAnimationCallback != null;
11695     }
11696 
11697     /**
11698      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
11699      * when Window Insets animation is being prepared.
11700      * @param animation current animation
11701      *
11702      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
11703      */
dispatchWindowInsetsAnimationPrepare( @onNull WindowInsetsAnimation animation)11704     public void dispatchWindowInsetsAnimationPrepare(
11705             @NonNull WindowInsetsAnimation animation) {
11706         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11707             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
11708         }
11709     }
11710 
11711     /**
11712      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
11713      * when Window Insets animation is started.
11714      * @param animation current animation
11715      * @param bounds the upper and lower {@link Bounds} that provides range of
11716      *  {@link WindowInsetsAnimation}.
11717      * @return the upper and lower {@link Bounds}.
11718      */
11719     @NonNull
dispatchWindowInsetsAnimationStart( @onNull WindowInsetsAnimation animation, @NonNull Bounds bounds)11720     public Bounds dispatchWindowInsetsAnimationStart(
11721             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
11722         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11723             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
11724         }
11725         return bounds;
11726     }
11727 
11728     /**
11729      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
11730      * when Window Insets animation makes progress.
11731      * @param insets The current {@link WindowInsets}.
11732      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
11733      * @return current {@link WindowInsets}.
11734      */
11735     @NonNull
dispatchWindowInsetsAnimationProgress(@onNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations)11736     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
11737             @NonNull List<WindowInsetsAnimation> runningAnimations) {
11738         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11739             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
11740                     runningAnimations);
11741         } else {
11742             return insets;
11743         }
11744     }
11745 
11746     /**
11747      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
11748      * when Window Insets animation ends.
11749      * @param animation The current ongoing {@link WindowInsetsAnimation}.
11750      */
dispatchWindowInsetsAnimationEnd(@onNull WindowInsetsAnimation animation)11751     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
11752         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11753             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
11754         }
11755     }
11756 
11757     /**
11758      * Sets a list of areas within this view's post-layout coordinate space where the system
11759      * should not intercept touch or other pointing device gestures. <em>This method should
11760      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
11761      *
11762      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
11763      * input in order to function correctly in the presence of global system gestures that may
11764      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
11765      * to provide system-level navigation functionality, a view such as a navigation drawer
11766      * container can mark the left (or starting) edge of itself as requiring gesture capture
11767      * priority using this API. The system may then choose to relax its own gesture recognition
11768      * to allow the app to consume the user's gesture. It is not necessary for an app to register
11769      * exclusion rects for broadly spanning regions such as the entirety of a
11770      * <code>ScrollView</code> or for simple press and release click targets such as
11771      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
11772      * a precision touch gesture in a small area in either the X or Y dimension, such as
11773      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
11774      *
11775      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
11776      * exclusions it takes into account. The limit does not apply while the navigation
11777      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
11778      * {@link android.inputmethodservice.InputMethodService input method} and
11779      * {@link Intent#CATEGORY_HOME home activity}.
11780      * </p>
11781      *
11782      * @param rects A list of precision gesture regions that this view needs to function correctly
11783      */
setSystemGestureExclusionRects(@onNull List<Rect> rects)11784     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
11785         if (rects.isEmpty() && mListenerInfo == null) return;
11786 
11787         final ListenerInfo info = getListenerInfo();
11788         if (info.mSystemGestureExclusionRects != null) {
11789             info.mSystemGestureExclusionRects.clear();
11790             info.mSystemGestureExclusionRects.addAll(rects);
11791         } else {
11792             info.mSystemGestureExclusionRects = new ArrayList<>(rects);
11793         }
11794 
11795         updatePositionUpdateListener();
11796         postUpdate(this::updateSystemGestureExclusionRects);
11797     }
11798 
updatePositionUpdateListener()11799     private void updatePositionUpdateListener() {
11800         final ListenerInfo info = getListenerInfo();
11801         if (getSystemGestureExclusionRects().isEmpty()
11802                 && collectPreferKeepClearRects().isEmpty()
11803                 && collectUnrestrictedPreferKeepClearRects().isEmpty()
11804                 && (info.mHandwritingArea == null || !isAutoHandwritingEnabled())) {
11805             if (info.mPositionUpdateListener != null) {
11806                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
11807                 info.mPositionUpdateListener = null;
11808                 info.mPositionChangedUpdate = null;
11809             }
11810         } else {
11811             if (info.mPositionUpdateListener == null) {
11812                 info.mPositionChangedUpdate = () -> {
11813                     updateSystemGestureExclusionRects();
11814                     updateKeepClearRects();
11815                     updateHandwritingArea();
11816                 };
11817                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
11818                     @Override
11819                     public void positionChanged(long n, int l, int t, int r, int b) {
11820                         postUpdate(info.mPositionChangedUpdate);
11821                     }
11822 
11823                     @Override
11824                     public void positionLost(long frameNumber) {
11825                         postUpdate(info.mPositionChangedUpdate);
11826                     }
11827                 };
11828                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
11829             }
11830         }
11831     }
11832 
11833     /**
11834      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
11835      */
postUpdate(Runnable r)11836     private void postUpdate(Runnable r) {
11837         // Potentially racey from a background thread. It's ok if it's not perfect.
11838         final Handler h = getHandler();
11839         if (h != null) {
11840             h.postAtFrontOfQueue(r);
11841         }
11842     }
11843 
updateSystemGestureExclusionRects()11844     void updateSystemGestureExclusionRects() {
11845         final AttachInfo ai = mAttachInfo;
11846         if (ai != null) {
11847             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
11848         }
11849     }
11850 
11851     /**
11852      * Retrieve the list of areas within this view's post-layout coordinate space where the system
11853      * should not intercept touch or other pointing device gestures.
11854      *
11855      * <p>Do not modify the returned list.</p>
11856      *
11857      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
11858      */
11859     @NonNull
getSystemGestureExclusionRects()11860     public List<Rect> getSystemGestureExclusionRects() {
11861         final ListenerInfo info = mListenerInfo;
11862         if (info != null) {
11863             final List<Rect> list = info.mSystemGestureExclusionRects;
11864             if (list != null) {
11865                 return list;
11866             }
11867         }
11868         return Collections.emptyList();
11869     }
11870 
11871     /**
11872      * Set a preference to keep the bounds of this view clear from floating windows above this
11873      * view's window. This informs the system that the view is considered a vital area for the
11874      * user and that ideally it should not be covered. Setting this is only appropriate for UI
11875      * where the user would likely take action to uncover it.
11876      * <p>
11877      * The system will try to respect this preference, but when not possible will ignore it.
11878      * <p>
11879      * Note: This is independent from {@link #setPreferKeepClearRects}. If both are set, both will
11880      * be taken into account.
11881      * <p>
11882      * @see #setPreferKeepClearRects
11883      * @see #isPreferKeepClear
11884      * @attr ref android.R.styleable#View_preferKeepClear
11885      */
setPreferKeepClear(boolean preferKeepClear)11886     public final void setPreferKeepClear(boolean preferKeepClear) {
11887         getListenerInfo().mPreferKeepClear = preferKeepClear;
11888         updatePositionUpdateListener();
11889         postUpdate(this::updateKeepClearRects);
11890     }
11891 
11892     /**
11893      * Retrieve the preference for this view to be kept clear. This is set either by
11894      * {@link #setPreferKeepClear} or via the attribute android.R.styleable#View_preferKeepClear.
11895      * <p>
11896      * If this is {@code true}, the system will ignore the Rects set by
11897      * {@link #setPreferKeepClearRects} and try to keep the whole view clear.
11898      * <p>
11899      * @see #setPreferKeepClear
11900      * @attr ref android.R.styleable#View_preferKeepClear
11901      */
isPreferKeepClear()11902     public final boolean isPreferKeepClear() {
11903         return mListenerInfo != null && mListenerInfo.mPreferKeepClear;
11904     }
11905 
11906     /**
11907      * Set a preference to keep the provided rects clear from floating windows above this
11908      * view's window. This informs the system that these rects are considered vital areas for the
11909      * user and that ideally they should not be covered. Setting this is only appropriate for UI
11910      * where the user would likely take action to uncover it.
11911      * <p>
11912      * The system will try to respect this preference, but when not possible will ignore it.
11913      * <p>
11914      * Note: This is independent from {@link #setPreferKeepClear}. If both are set, both will be
11915      * taken into account.
11916      * <p>
11917      * @see #setPreferKeepClear
11918      * @see #getPreferKeepClearRects
11919      *
11920      * @param rects A list of rects in this view's local coordinate system
11921      */
setPreferKeepClearRects(@onNull List<Rect> rects)11922     public final void setPreferKeepClearRects(@NonNull List<Rect> rects) {
11923         final ListenerInfo info = getListenerInfo();
11924         if (info.mKeepClearRects != null) {
11925             info.mKeepClearRects.clear();
11926             info.mKeepClearRects.addAll(rects);
11927         } else {
11928             info.mKeepClearRects = new ArrayList<>(rects);
11929         }
11930         updatePositionUpdateListener();
11931         postUpdate(this::updateKeepClearRects);
11932     }
11933 
11934     /**
11935      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
11936      *
11937      * @see #setPreferKeepClearRects
11938      */
11939     @NonNull
getPreferKeepClearRects()11940     public final List<Rect> getPreferKeepClearRects() {
11941         final ListenerInfo info = mListenerInfo;
11942         if (info != null && info.mKeepClearRects != null) {
11943             return new ArrayList(info.mKeepClearRects);
11944         }
11945 
11946         return Collections.emptyList();
11947     }
11948 
11949     /**
11950      * Set a preference to keep the provided rects clear from floating windows above this
11951      * view's window. This informs the system that these rects are considered vital areas for the
11952      * user and that ideally they should not be covered. Setting this is only appropriate for UI
11953      * where the user would likely take action to uncover it.
11954      * <p>
11955      * Note: The difference with {@link #setPreferKeepClearRects} is that the system won't apply
11956      * restrictions to the rects set here.
11957      * <p>
11958      * @see #setPreferKeepClear
11959      * @see #getPreferKeepClearRects
11960      *
11961      * @param rects A list of rects in this view's local coordinate system
11962      *
11963      * @hide
11964      */
11965     @SystemApi
11966     @RequiresPermission(android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS)
setUnrestrictedPreferKeepClearRects(@onNull List<Rect> rects)11967     public final void setUnrestrictedPreferKeepClearRects(@NonNull List<Rect> rects) {
11968         final ListenerInfo info = getListenerInfo();
11969         if (info.mUnrestrictedKeepClearRects != null) {
11970             info.mUnrestrictedKeepClearRects.clear();
11971             info.mUnrestrictedKeepClearRects.addAll(rects);
11972         } else {
11973             info.mUnrestrictedKeepClearRects = new ArrayList<>(rects);
11974         }
11975         updatePositionUpdateListener();
11976         postUpdate(this::updateKeepClearRects);
11977     }
11978 
11979     /**
11980      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
11981      *
11982      * @see #setPreferKeepClearRects
11983      *
11984      * @hide
11985      */
11986     @SystemApi
11987     @NonNull
getUnrestrictedPreferKeepClearRects()11988     public final List<Rect> getUnrestrictedPreferKeepClearRects() {
11989         final ListenerInfo info = mListenerInfo;
11990         if (info != null && info.mUnrestrictedKeepClearRects != null) {
11991             return new ArrayList(info.mUnrestrictedKeepClearRects);
11992         }
11993 
11994         return Collections.emptyList();
11995     }
11996 
updateKeepClearRects()11997     void updateKeepClearRects() {
11998         final AttachInfo ai = mAttachInfo;
11999         if (ai != null) {
12000             ai.mViewRootImpl.updateKeepClearRectsForView(this);
12001         }
12002     }
12003 
12004     /**
12005      * Retrieve the list of areas within this view's post-layout coordinate space which the
12006      * system will try to not cover with other floating elements, like the pip window.
12007      */
12008     @NonNull
collectPreferKeepClearRects()12009     List<Rect> collectPreferKeepClearRects() {
12010         ListenerInfo info = mListenerInfo;
12011         boolean keepClearForFocus = isFocused()
12012                 && ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled();
12013         boolean keepBoundsClear = (info != null && info.mPreferKeepClear) || keepClearForFocus;
12014         boolean hasCustomKeepClearRects = info != null && info.mKeepClearRects != null;
12015 
12016         if (!keepBoundsClear && !hasCustomKeepClearRects) {
12017             return Collections.emptyList();
12018         } else if (keepBoundsClear && !hasCustomKeepClearRects) {
12019             return Collections.singletonList(new Rect(0, 0, getWidth(), getHeight()));
12020         }
12021 
12022         final List<Rect> list = new ArrayList<>();
12023         if (keepBoundsClear) {
12024             list.add(new Rect(0, 0, getWidth(), getHeight()));
12025         }
12026 
12027         if (hasCustomKeepClearRects) {
12028             list.addAll(info.mKeepClearRects);
12029         }
12030 
12031         return list;
12032     }
12033 
updatePreferKeepClearForFocus()12034     private void updatePreferKeepClearForFocus() {
12035         if (ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled()) {
12036             updatePositionUpdateListener();
12037             post(this::updateKeepClearRects);
12038         }
12039     }
12040 
12041     /**
12042      * Retrieve the list of unrestricted areas within this view's post-layout coordinate space
12043      * which the system will try to not cover with other floating elements, like the pip window.
12044      */
12045     @NonNull
collectUnrestrictedPreferKeepClearRects()12046     List<Rect> collectUnrestrictedPreferKeepClearRects() {
12047         final ListenerInfo info = mListenerInfo;
12048         if (info != null && info.mUnrestrictedKeepClearRects != null) {
12049             return info.mUnrestrictedKeepClearRects;
12050         }
12051 
12052         return Collections.emptyList();
12053     }
12054 
12055     /**
12056      * Set a list of handwriting areas in this view. If there is any stylus {@link MotionEvent}
12057      * occurs within those areas, it will trigger stylus handwriting mode. This can be disabled by
12058      * disabling the auto handwriting initiation by calling
12059      * {@link #setAutoHandwritingEnabled(boolean)} with false.
12060      *
12061      * @attr rects a list of handwriting area in the view's local coordiniates.
12062      *
12063      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
12064      * @see #setAutoHandwritingEnabled(boolean)
12065      *
12066      * @hide
12067      */
setHandwritingArea(@ullable Rect rect)12068     public void setHandwritingArea(@Nullable Rect rect) {
12069         final ListenerInfo info = getListenerInfo();
12070         info.mHandwritingArea = rect;
12071         updatePositionUpdateListener();
12072         postUpdate(this::updateHandwritingArea);
12073     }
12074 
12075     /**
12076      * Return the handwriting areas set on this view, in its local coordinates.
12077      * @see #setHandwritingArea(Rect)
12078      *
12079      * @hide
12080      */
12081     @Nullable
getHandwritingArea()12082     public Rect getHandwritingArea() {
12083         final ListenerInfo info = mListenerInfo;
12084         if (info != null && info.mHandwritingArea != null) {
12085             return new Rect(info.mHandwritingArea);
12086         }
12087         return null;
12088     }
12089 
updateHandwritingArea()12090     void updateHandwritingArea() {
12091         // If autoHandwritingArea is not enabled, do nothing.
12092         if (!isAutoHandwritingEnabled()) return;
12093         final AttachInfo ai = mAttachInfo;
12094         if (ai != null) {
12095             ai.mViewRootImpl.getHandwritingInitiator().updateHandwritingAreasForView(this);
12096         }
12097     }
12098 
12099     /**
12100      * Gets the coordinates of this view in the coordinate space of the
12101      * {@link Surface} that contains the view.
12102      *
12103      * <p>In multiple-screen scenarios, if the surface spans multiple screens,
12104      * the coordinate space of the surface also spans multiple screens.
12105      *
12106      * <p>After the method returns, the argument array contains the x and y
12107      * coordinates of the view relative to the view's left and top edges,
12108      * respectively.
12109      *
12110      * @param location A two-element integer array in which the view coordinates
12111      *      are stored. The x-coordinate is at index 0; the y-coordinate, at
12112      *      index 1.
12113      */
getLocationInSurface(@onNull @ize2) int[] location)12114     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
12115         getLocationInWindow(location);
12116         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
12117             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
12118             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
12119         }
12120     }
12121 
12122     /**
12123      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
12124      * only available if the view is attached.
12125      *
12126      * @return WindowInsets from the top of the view hierarchy or null if View is detached
12127      */
getRootWindowInsets()12128     public WindowInsets getRootWindowInsets() {
12129         if (mAttachInfo != null) {
12130             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
12131         }
12132         return null;
12133     }
12134 
12135     /**
12136      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
12137      *
12138      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
12139      *         a window nor a view tree with a decor.
12140      * @see Window#getInsetsController()
12141      */
getWindowInsetsController()12142     public @Nullable WindowInsetsController getWindowInsetsController() {
12143         if (mAttachInfo != null) {
12144             return mAttachInfo.mViewRootImpl.getInsetsController();
12145         }
12146         ViewParent parent = getParent();
12147         if (parent instanceof View) {
12148             return ((View) parent).getWindowInsetsController();
12149         } else if (parent instanceof ViewRootImpl) {
12150             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
12151             return ((ViewRootImpl) parent).getInsetsController();
12152         }
12153         return null;
12154     }
12155 
12156 
12157     /**
12158      * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}.
12159      *
12160      * @return The {@link OnBackInvokedDispatcher} from this or the nearest
12161      * ancestor, or null if this view is both not attached and have no ancestor providing an
12162      * {@link OnBackInvokedDispatcher}.
12163      */
12164     @Nullable
findOnBackInvokedDispatcher()12165     public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() {
12166         ViewParent parent = getParent();
12167         if (parent != null) {
12168             return parent.findOnBackInvokedDispatcherForChild(this, this);
12169         }
12170         return null;
12171     }
12172 
12173     /**
12174      * @hide Compute the insets that should be consumed by this view and the ones
12175      * that should propagate to those under it.
12176      *
12177      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
12178      *
12179      * @param inoutInsets the insets given to this view
12180      * @param outLocalInsets the insets that should be applied to this view
12181      * @deprecated use {@link #computeSystemWindowInsets}
12182      * @return
12183      */
12184     @Deprecated
12185     @UnsupportedAppUsage
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)12186     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
12187         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
12188                 outLocalInsets);
12189         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
12190         return innerInsets.isSystemWindowInsetsConsumed();
12191     }
12192 
12193     /**
12194      * Compute insets that should be consumed by this view and the ones that should propagate
12195      * to those under it.
12196      *
12197      * @param in Insets currently being processed by this View, likely received as a parameter
12198      *           to {@link #onApplyWindowInsets(WindowInsets)}.
12199      * @param outLocalInsets A Rect that will receive the insets that should be consumed
12200      *                       by this view
12201      * @return Insets that should be passed along to views under this one
12202      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)12203     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
12204         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
12205                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
12206         if (isOptionalFitSystemWindows && mAttachInfo != null) {
12207             OnContentApplyWindowInsetsListener listener =
12208                     mAttachInfo.mContentOnApplyWindowInsetsListener;
12209             if (listener == null) {
12210                 // The application wants to take care of fitting system window for
12211                 // the content.
12212                 outLocalInsets.setEmpty();
12213                 return in;
12214             }
12215             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
12216             outLocalInsets.set(result.first.toRect());
12217             return result.second;
12218         } else {
12219             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
12220             return in.consumeSystemWindowInsets().inset(outLocalInsets);
12221         }
12222     }
12223 
12224     /**
12225      * Sets whether or not this view should account for system screen decorations
12226      * such as the status bar and inset its content; that is, controlling whether
12227      * the default implementation of {@link #fitSystemWindows(Rect)} will be
12228      * executed.  See that method for more details.
12229      *
12230      * <p>Note that if you are providing your own implementation of
12231      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
12232      * flag to true -- your implementation will be overriding the default
12233      * implementation that checks this flag.
12234      *
12235      * @param fitSystemWindows If true, then the default implementation of
12236      * {@link #fitSystemWindows(Rect)} will be executed.
12237      *
12238      * @attr ref android.R.styleable#View_fitsSystemWindows
12239      * @see #getFitsSystemWindows()
12240      * @see #fitSystemWindows(Rect)
12241      * @see #setSystemUiVisibility(int)
12242      */
setFitsSystemWindows(boolean fitSystemWindows)12243     public void setFitsSystemWindows(boolean fitSystemWindows) {
12244         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
12245     }
12246 
12247     /**
12248      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
12249      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
12250      * will be executed.
12251      *
12252      * @return {@code true} if the default implementation of
12253      * {@link #fitSystemWindows(Rect)} will be executed.
12254      *
12255      * @attr ref android.R.styleable#View_fitsSystemWindows
12256      * @see #setFitsSystemWindows(boolean)
12257      * @see #fitSystemWindows(Rect)
12258      * @see #setSystemUiVisibility(int)
12259      */
12260     @ViewDebug.ExportedProperty
12261     @InspectableProperty
getFitsSystemWindows()12262     public boolean getFitsSystemWindows() {
12263         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
12264     }
12265 
12266     /** @hide */
12267     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
fitsSystemWindows()12268     public boolean fitsSystemWindows() {
12269         return getFitsSystemWindows();
12270     }
12271 
12272     /**
12273      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
12274      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
12275      */
12276     @Deprecated
requestFitSystemWindows()12277     public void requestFitSystemWindows() {
12278         if (mParent != null) {
12279             mParent.requestFitSystemWindows();
12280         }
12281     }
12282 
12283     /**
12284      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
12285      */
requestApplyInsets()12286     public void requestApplyInsets() {
12287         requestFitSystemWindows();
12288     }
12289 
12290     /**
12291      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
12292      * @hide
12293      */
12294     @UnsupportedAppUsage
makeOptionalFitsSystemWindows()12295     public void makeOptionalFitsSystemWindows() {
12296         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
12297     }
12298 
12299     /**
12300      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
12301      * @hide
12302      */
makeFrameworkOptionalFitsSystemWindows()12303     public void makeFrameworkOptionalFitsSystemWindows() {
12304         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
12305     }
12306 
12307     /**
12308      * @hide
12309      */
isFrameworkOptionalFitsSystemWindows()12310     public boolean isFrameworkOptionalFitsSystemWindows() {
12311         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
12312     }
12313 
12314     /**
12315      * Returns the visibility status for this view.
12316      *
12317      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
12318      * @attr ref android.R.styleable#View_visibility
12319      */
12320     @ViewDebug.ExportedProperty(mapping = {
12321         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
12322         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
12323         @ViewDebug.IntToString(from = GONE,      to = "GONE")
12324     })
12325     @InspectableProperty(enumMapping = {
12326             @EnumEntry(value = VISIBLE, name = "visible"),
12327             @EnumEntry(value = INVISIBLE, name = "invisible"),
12328             @EnumEntry(value = GONE, name = "gone")
12329     })
12330     @Visibility
getVisibility()12331     public int getVisibility() {
12332         return mViewFlags & VISIBILITY_MASK;
12333     }
12334 
12335     /**
12336      * Set the visibility state of this view.
12337      *
12338      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
12339      * @attr ref android.R.styleable#View_visibility
12340      */
12341     @RemotableViewMethod
setVisibility(@isibility int visibility)12342     public void setVisibility(@Visibility int visibility) {
12343         setFlags(visibility, VISIBILITY_MASK);
12344     }
12345 
12346     /**
12347      * Returns the enabled status for this view. The interpretation of the
12348      * enabled state varies by subclass.
12349      *
12350      * @return True if this view is enabled, false otherwise.
12351      */
12352     @ViewDebug.ExportedProperty
12353     @InspectableProperty
isEnabled()12354     public boolean isEnabled() {
12355         return (mViewFlags & ENABLED_MASK) == ENABLED;
12356     }
12357 
12358     /**
12359      * Set the enabled state of this view. The interpretation of the enabled
12360      * state varies by subclass.
12361      *
12362      * @param enabled True if this view is enabled, false otherwise.
12363      */
12364     @RemotableViewMethod
setEnabled(boolean enabled)12365     public void setEnabled(boolean enabled) {
12366         if (enabled == isEnabled()) return;
12367 
12368         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
12369 
12370         /*
12371          * The View most likely has to change its appearance, so refresh
12372          * the drawable state.
12373          */
12374         refreshDrawableState();
12375 
12376         // Invalidate too, since the default behavior for views is to be
12377         // be drawn at 50% alpha rather than to change the drawable.
12378         invalidate(true);
12379 
12380         if (!enabled) {
12381             cancelPendingInputEvents();
12382         }
12383     }
12384 
12385     /**
12386      * Set whether this view can receive the focus.
12387      * <p>
12388      * Setting this to false will also ensure that this view is not focusable
12389      * in touch mode.
12390      *
12391      * @param focusable If true, this view can receive the focus.
12392      *
12393      * @see #setFocusableInTouchMode(boolean)
12394      * @see #setFocusable(int)
12395      * @attr ref android.R.styleable#View_focusable
12396      */
12397     @RemotableViewMethod
setFocusable(boolean focusable)12398     public void setFocusable(boolean focusable) {
12399         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
12400     }
12401 
12402     /**
12403      * Sets whether this view can receive focus.
12404      * <p>
12405      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
12406      * automatically based on the view's interactivity. This is the default.
12407      * <p>
12408      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
12409      * in touch mode.
12410      *
12411      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
12412      *                  or {@link #FOCUSABLE_AUTO}.
12413      * @see #setFocusableInTouchMode(boolean)
12414      * @attr ref android.R.styleable#View_focusable
12415      */
12416     @RemotableViewMethod
setFocusable(@ocusable int focusable)12417     public void setFocusable(@Focusable int focusable) {
12418         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
12419             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
12420         }
12421         setFlags(focusable, FOCUSABLE_MASK);
12422     }
12423 
12424     /**
12425      * Set whether this view can receive focus while in touch mode.
12426      *
12427      * Setting this to true will also ensure that this view is focusable.
12428      *
12429      * @param focusableInTouchMode If true, this view can receive the focus while
12430      *   in touch mode.
12431      *
12432      * @see #setFocusable(boolean)
12433      * @attr ref android.R.styleable#View_focusableInTouchMode
12434      */
12435     @RemotableViewMethod
setFocusableInTouchMode(boolean focusableInTouchMode)12436     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
12437         // Focusable in touch mode should always be set before the focusable flag
12438         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
12439         // which, in touch mode, will not successfully request focus on this view
12440         // because the focusable in touch mode flag is not set
12441         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
12442 
12443         // Clear FOCUSABLE_AUTO if set.
12444         if (focusableInTouchMode) {
12445             // Clears FOCUSABLE_AUTO if set.
12446             setFlags(FOCUSABLE, FOCUSABLE_MASK);
12447         }
12448     }
12449 
12450     /**
12451      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
12452      * to autofill the view with the user's data.
12453      *
12454      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
12455      * For example, if the application accepts either an username or email address to identify
12456      * an user.
12457      *
12458      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
12459      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
12460      * constants such as:
12461      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
12462      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
12463      * {@link #AUTOFILL_HINT_NAME},
12464      * {@link #AUTOFILL_HINT_PHONE},
12465      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
12466      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
12467      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
12468      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
12469      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
12470      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
12471      *
12472      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
12473      * @attr ref android.R.styleable#View_autofillHints
12474      */
setAutofillHints(@ullable String... autofillHints)12475     public void setAutofillHints(@Nullable String... autofillHints) {
12476         if (autofillHints == null || autofillHints.length == 0) {
12477             mAutofillHints = null;
12478         } else {
12479             mAutofillHints = autofillHints;
12480         }
12481     }
12482 
12483     /**
12484      * @hide
12485      */
12486     @TestApi
setAutofilled(boolean isAutofilled, boolean hideHighlight)12487     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
12488         boolean wasChanged = isAutofilled != isAutofilled();
12489 
12490         if (wasChanged) {
12491             if (isAutofilled) {
12492                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
12493             } else {
12494                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
12495             }
12496 
12497             if (hideHighlight) {
12498                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
12499             } else {
12500                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
12501             }
12502 
12503             invalidate();
12504         }
12505     }
12506 
12507     /**
12508      * Set whether this view should have sound effects enabled for events such as
12509      * clicking and touching.
12510      *
12511      * <p>You may wish to disable sound effects for a view if you already play sounds,
12512      * for instance, a dial key that plays dtmf tones.
12513      *
12514      * @param soundEffectsEnabled whether sound effects are enabled for this view.
12515      * @see #isSoundEffectsEnabled()
12516      * @see #playSoundEffect(int)
12517      * @attr ref android.R.styleable#View_soundEffectsEnabled
12518      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)12519     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
12520         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
12521     }
12522 
12523     /**
12524      * @return whether this view should have sound effects enabled for events such as
12525      *     clicking and touching.
12526      *
12527      * @see #setSoundEffectsEnabled(boolean)
12528      * @see #playSoundEffect(int)
12529      * @attr ref android.R.styleable#View_soundEffectsEnabled
12530      */
12531     @ViewDebug.ExportedProperty
12532     @InspectableProperty
isSoundEffectsEnabled()12533     public boolean isSoundEffectsEnabled() {
12534         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
12535     }
12536 
12537     /**
12538      * Set whether this view should have haptic feedback for events such as
12539      * long presses.
12540      *
12541      * <p>You may wish to disable haptic feedback if your view already controls
12542      * its own haptic feedback.
12543      *
12544      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
12545      * @see #isHapticFeedbackEnabled()
12546      * @see #performHapticFeedback(int)
12547      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
12548      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)12549     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
12550         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
12551     }
12552 
12553     /**
12554      * @return whether this view should have haptic feedback enabled for events
12555      * such as long presses.
12556      *
12557      * @see #setHapticFeedbackEnabled(boolean)
12558      * @see #performHapticFeedback(int)
12559      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
12560      */
12561     @ViewDebug.ExportedProperty
12562     @InspectableProperty
isHapticFeedbackEnabled()12563     public boolean isHapticFeedbackEnabled() {
12564         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
12565     }
12566 
12567     /**
12568      * Returns the layout direction for this view.
12569      *
12570      * @return One of {@link #LAYOUT_DIRECTION_LTR},
12571      *   {@link #LAYOUT_DIRECTION_RTL},
12572      *   {@link #LAYOUT_DIRECTION_INHERIT} or
12573      *   {@link #LAYOUT_DIRECTION_LOCALE}.
12574      *
12575      * @attr ref android.R.styleable#View_layoutDirection
12576      *
12577      * @hide
12578      */
12579     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12580         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
12581         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
12582         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
12583         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
12584     })
12585     @InspectableProperty(hasAttributeId = false, enumMapping = {
12586             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12587             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
12588             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
12589             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
12590     })
12591     @LayoutDir
getRawLayoutDirection()12592     public int getRawLayoutDirection() {
12593         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
12594     }
12595 
12596     /**
12597      * Set the layout direction for this view. This will propagate a reset of layout direction
12598      * resolution to the view's children and resolve layout direction for this view.
12599      *
12600      * @param layoutDirection the layout direction to set. Should be one of:
12601      *
12602      * {@link #LAYOUT_DIRECTION_LTR},
12603      * {@link #LAYOUT_DIRECTION_RTL},
12604      * {@link #LAYOUT_DIRECTION_INHERIT},
12605      * {@link #LAYOUT_DIRECTION_LOCALE}.
12606      *
12607      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
12608      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
12609      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
12610      *
12611      * @attr ref android.R.styleable#View_layoutDirection
12612      */
12613     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)12614     public void setLayoutDirection(@LayoutDir int layoutDirection) {
12615         if (getRawLayoutDirection() != layoutDirection) {
12616             // Reset the current layout direction and the resolved one
12617             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
12618             resetRtlProperties();
12619             // Set the new layout direction (filtered)
12620             mPrivateFlags2 |=
12621                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
12622             // We need to resolve all RTL properties as they all depend on layout direction
12623             resolveRtlPropertiesIfNeeded();
12624             requestLayout();
12625             invalidate(true);
12626         }
12627     }
12628 
12629     /**
12630      * Returns the resolved layout direction for this view.
12631      *
12632      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
12633      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
12634      *
12635      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
12636      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
12637      *
12638      * @attr ref android.R.styleable#View_layoutDirection
12639      */
12640     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12641         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
12642         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
12643     })
12644     @InspectableProperty(enumMapping = {
12645             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12646             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
12647     })
12648     @ResolvedLayoutDir
getLayoutDirection()12649     public int getLayoutDirection() {
12650         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12651         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
12652             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12653             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
12654         }
12655         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
12656                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
12657     }
12658 
12659     /**
12660      * Indicates whether or not this view's layout is right-to-left. This is resolved from
12661      * layout attribute and/or the inherited value from the parent
12662      *
12663      * @return true if the layout is right-to-left.
12664      *
12665      * @hide
12666      */
12667     @ViewDebug.ExportedProperty(category = "layout")
12668     @UnsupportedAppUsage
isLayoutRtl()12669     public boolean isLayoutRtl() {
12670         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
12671     }
12672 
12673     /**
12674      * Indicates whether the view is currently tracking transient state that the
12675      * app should not need to concern itself with saving and restoring, but that
12676      * the framework should take special note to preserve when possible.
12677      *
12678      * <p>A view with transient state cannot be trivially rebound from an external
12679      * data source, such as an adapter binding item views in a list. This may be
12680      * because the view is performing an animation, tracking user selection
12681      * of content, or similar.</p>
12682      *
12683      * @return true if the view has transient state
12684      */
12685     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()12686     public boolean hasTransientState() {
12687         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
12688     }
12689 
12690     /**
12691      * Set whether this view is currently tracking transient state that the
12692      * framework should attempt to preserve when possible. This flag is reference counted,
12693      * so every call to setHasTransientState(true) should be paired with a later call
12694      * to setHasTransientState(false).
12695      *
12696      * <p>A view with transient state cannot be trivially rebound from an external
12697      * data source, such as an adapter binding item views in a list. This may be
12698      * because the view is performing an animation, tracking user selection
12699      * of content, or similar.</p>
12700      *
12701      * @param hasTransientState true if this view has transient state
12702      */
setHasTransientState(boolean hasTransientState)12703     public void setHasTransientState(boolean hasTransientState) {
12704         final boolean oldHasTransientState = hasTransientState();
12705         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
12706                 mTransientStateCount - 1;
12707         if (mTransientStateCount < 0) {
12708             mTransientStateCount = 0;
12709             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
12710                     "unmatched pair of setHasTransientState calls");
12711         } else if ((hasTransientState && mTransientStateCount == 1) ||
12712                 (!hasTransientState && mTransientStateCount == 0)) {
12713             // update flag if we've just incremented up from 0 or decremented down to 0
12714             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
12715                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
12716             final boolean newHasTransientState = hasTransientState();
12717             if (mParent != null && newHasTransientState != oldHasTransientState) {
12718                 try {
12719                     mParent.childHasTransientStateChanged(this, newHasTransientState);
12720                 } catch (AbstractMethodError e) {
12721                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12722                             " does not fully implement ViewParent", e);
12723                 }
12724             }
12725         }
12726     }
12727 
12728     /**
12729      * Set the view is tracking translation transient state. This flag is used to check if the view
12730      * need to call setHasTransientState(false) to reset transient state that set when starting
12731      * translation.
12732      *
12733      * @param hasTranslationTransientState true if this view has translation transient state
12734      * @hide
12735      */
setHasTranslationTransientState(boolean hasTranslationTransientState)12736     public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
12737         if (hasTranslationTransientState) {
12738             mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12739         } else {
12740             mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12741         }
12742     }
12743 
12744     /**
12745      * @hide
12746      */
hasTranslationTransientState()12747     public boolean hasTranslationTransientState() {
12748         return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
12749                 == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12750     }
12751 
12752     /**
12753      * @hide
12754      */
clearTranslationState()12755     public void clearTranslationState() {
12756         if (mViewTranslationCallback != null) {
12757             mViewTranslationCallback.onClearTranslation(this);
12758         }
12759         clearViewTranslationResponse();
12760         if (hasTranslationTransientState()) {
12761             setHasTransientState(false);
12762             setHasTranslationTransientState(false);
12763         }
12764     }
12765 
12766     /**
12767      * Returns true if this view is currently attached to a window.
12768      */
isAttachedToWindow()12769     public boolean isAttachedToWindow() {
12770         return mAttachInfo != null;
12771     }
12772 
12773     /**
12774      * Returns true if this view has been through at least one layout since it
12775      * was last attached to or detached from a window.
12776      */
isLaidOut()12777     public boolean isLaidOut() {
12778         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
12779     }
12780 
12781     /**
12782      * @return {@code true} if laid-out and not about to do another layout.
12783      */
isLayoutValid()12784     boolean isLayoutValid() {
12785         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
12786     }
12787 
12788     /**
12789      * If this view doesn't do any drawing on its own, set this flag to
12790      * allow further optimizations. By default, this flag is not set on
12791      * View, but could be set on some View subclasses such as ViewGroup.
12792      *
12793      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
12794      * you should clear this flag.
12795      *
12796      * @param willNotDraw whether or not this View draw on its own
12797      */
setWillNotDraw(boolean willNotDraw)12798     public void setWillNotDraw(boolean willNotDraw) {
12799         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
12800     }
12801 
12802     /**
12803      * Returns whether or not this View draws on its own.
12804      *
12805      * @return true if this view has nothing to draw, false otherwise
12806      */
12807     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()12808     public boolean willNotDraw() {
12809         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
12810     }
12811 
12812     /**
12813      * When a View's drawing cache is enabled, drawing is redirected to an
12814      * offscreen bitmap. Some views, like an ImageView, must be able to
12815      * bypass this mechanism if they already draw a single bitmap, to avoid
12816      * unnecessary usage of the memory.
12817      *
12818      * @param willNotCacheDrawing true if this view does not cache its
12819      *        drawing, false otherwise
12820      *
12821      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12822      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12823      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12824      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12825      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12826      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12827      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12828      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12829      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12830      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12831      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12832      * reports or unit testing the {@link PixelCopy} API is recommended.
12833      */
12834     @Deprecated
setWillNotCacheDrawing(boolean willNotCacheDrawing)12835     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
12836         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
12837     }
12838 
12839     /**
12840      * Returns whether or not this View can cache its drawing or not.
12841      *
12842      * @return true if this view does not cache its drawing, false otherwise
12843      *
12844      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12845      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12846      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12847      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12848      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12849      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12850      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12851      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12852      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12853      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12854      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12855      * reports or unit testing the {@link PixelCopy} API is recommended.
12856      */
12857     @ViewDebug.ExportedProperty(category = "drawing")
12858     @Deprecated
willNotCacheDrawing()12859     public boolean willNotCacheDrawing() {
12860         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
12861     }
12862 
12863     /**
12864      * Indicates whether this view reacts to click events or not.
12865      *
12866      * @return true if the view is clickable, false otherwise
12867      *
12868      * @see #setClickable(boolean)
12869      * @attr ref android.R.styleable#View_clickable
12870      */
12871     @ViewDebug.ExportedProperty
12872     @InspectableProperty
isClickable()12873     public boolean isClickable() {
12874         return (mViewFlags & CLICKABLE) == CLICKABLE;
12875     }
12876 
12877     /**
12878      * Enables or disables click events for this view. When a view
12879      * is clickable it will change its state to "pressed" on every click.
12880      * Subclasses should set the view clickable to visually react to
12881      * user's clicks.
12882      *
12883      * @param clickable true to make the view clickable, false otherwise
12884      *
12885      * @see #isClickable()
12886      * @attr ref android.R.styleable#View_clickable
12887      */
setClickable(boolean clickable)12888     public void setClickable(boolean clickable) {
12889         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
12890     }
12891 
12892     /**
12893      * Enables or disables click events for this view when disabled.
12894      *
12895      * @param clickableWhenDisabled true to make the view clickable, false otherwise
12896      *
12897      * @attr ref android.R.styleable#View_allowClickWhenDisabled
12898      */
setAllowClickWhenDisabled(boolean clickableWhenDisabled)12899     public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
12900         if (clickableWhenDisabled) {
12901             mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
12902         } else {
12903             mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
12904         }
12905     }
12906 
12907     /**
12908      * Indicates whether this view reacts to long click events or not.
12909      *
12910      * @return true if the view is long clickable, false otherwise
12911      *
12912      * @see #setLongClickable(boolean)
12913      * @attr ref android.R.styleable#View_longClickable
12914      */
12915     @InspectableProperty
isLongClickable()12916     public boolean isLongClickable() {
12917         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12918     }
12919 
12920     /**
12921      * Enables or disables long click events for this view. When a view is long
12922      * clickable it reacts to the user holding down the button for a longer
12923      * duration than a tap. This event can either launch the listener or a
12924      * context menu.
12925      *
12926      * @param longClickable true to make the view long clickable, false otherwise
12927      * @see #isLongClickable()
12928      * @attr ref android.R.styleable#View_longClickable
12929      */
setLongClickable(boolean longClickable)12930     public void setLongClickable(boolean longClickable) {
12931         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
12932     }
12933 
12934     /**
12935      * Indicates whether this view reacts to context clicks or not.
12936      *
12937      * @return true if the view is context clickable, false otherwise
12938      * @see #setContextClickable(boolean)
12939      * @attr ref android.R.styleable#View_contextClickable
12940      */
12941     @InspectableProperty
isContextClickable()12942     public boolean isContextClickable() {
12943         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12944     }
12945 
12946     /**
12947      * Enables or disables context clicking for this view. This event can launch the listener.
12948      *
12949      * @param contextClickable true to make the view react to a context click, false otherwise
12950      * @see #isContextClickable()
12951      * @attr ref android.R.styleable#View_contextClickable
12952      */
setContextClickable(boolean contextClickable)12953     public void setContextClickable(boolean contextClickable) {
12954         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
12955     }
12956 
12957     /**
12958      * Sets the pressed state for this view and provides a touch coordinate for
12959      * animation hinting.
12960      *
12961      * @param pressed Pass true to set the View's internal state to "pressed",
12962      *            or false to reverts the View's internal state from a
12963      *            previously set "pressed" state.
12964      * @param x The x coordinate of the touch that caused the press
12965      * @param y The y coordinate of the touch that caused the press
12966      */
setPressed(boolean pressed, float x, float y)12967     private void setPressed(boolean pressed, float x, float y) {
12968         if (pressed) {
12969             drawableHotspotChanged(x, y);
12970         }
12971 
12972         setPressed(pressed);
12973     }
12974 
12975     /**
12976      * Sets the pressed state for this view.
12977      *
12978      * @see #isClickable()
12979      * @see #setClickable(boolean)
12980      *
12981      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
12982      *        the View's internal state from a previously set "pressed" state.
12983      */
setPressed(boolean pressed)12984     public void setPressed(boolean pressed) {
12985         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
12986 
12987         if (pressed) {
12988             mPrivateFlags |= PFLAG_PRESSED;
12989         } else {
12990             mPrivateFlags &= ~PFLAG_PRESSED;
12991         }
12992 
12993         if (needsRefresh) {
12994             refreshDrawableState();
12995         }
12996         dispatchSetPressed(pressed);
12997     }
12998 
12999     /**
13000      * Dispatch setPressed to all of this View's children.
13001      *
13002      * @see #setPressed(boolean)
13003      *
13004      * @param pressed The new pressed state
13005      */
dispatchSetPressed(boolean pressed)13006     protected void dispatchSetPressed(boolean pressed) {
13007     }
13008 
13009     /**
13010      * Indicates whether the view is currently in pressed state. Unless
13011      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
13012      * the pressed state.
13013      *
13014      * @see #setPressed(boolean)
13015      * @see #isClickable()
13016      * @see #setClickable(boolean)
13017      *
13018      * @return true if the view is currently pressed, false otherwise
13019      */
13020     @ViewDebug.ExportedProperty
13021     @InspectableProperty(hasAttributeId = false)
isPressed()13022     public boolean isPressed() {
13023         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
13024     }
13025 
13026     /**
13027      * @hide
13028      * Indicates whether this view will participate in data collection through
13029      * {@link ViewStructure}.  If true, it will not provide any data
13030      * for itself or its children.  If false, the normal data collection will be allowed.
13031      *
13032      * @return Returns false if assist data collection is not blocked, else true.
13033      *
13034      * @see #setAssistBlocked(boolean)
13035      * @attr ref android.R.styleable#View_assistBlocked
13036      */
isAssistBlocked()13037     public boolean isAssistBlocked() {
13038         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
13039     }
13040 
13041     /**
13042      * @hide
13043      * Controls whether assist data collection from this view and its children is enabled
13044      * (that is, whether {@link #onProvideStructure} and
13045      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
13046      * allowing normal assist collection.  Setting this to false will disable assist collection.
13047      *
13048      * @param enabled Set to true to <em>disable</em> assist data collection, or false
13049      * (the default) to allow it.
13050      *
13051      * @see #isAssistBlocked()
13052      * @see #onProvideStructure
13053      * @see #onProvideVirtualStructure
13054      * @attr ref android.R.styleable#View_assistBlocked
13055      */
13056     @UnsupportedAppUsage
setAssistBlocked(boolean enabled)13057     public void setAssistBlocked(boolean enabled) {
13058         if (enabled) {
13059             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
13060         } else {
13061             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
13062         }
13063     }
13064 
13065     /**
13066      * Indicates whether this view will save its state (that is,
13067      * whether its {@link #onSaveInstanceState} method will be called).
13068      *
13069      * @return Returns true if the view state saving is enabled, else false.
13070      *
13071      * @see #setSaveEnabled(boolean)
13072      * @attr ref android.R.styleable#View_saveEnabled
13073      */
13074     @InspectableProperty
isSaveEnabled()13075     public boolean isSaveEnabled() {
13076         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
13077     }
13078 
13079     /**
13080      * Controls whether the saving of this view's state is
13081      * enabled (that is, whether its {@link #onSaveInstanceState} method
13082      * will be called).  Note that even if freezing is enabled, the
13083      * view still must have an id assigned to it (via {@link #setId(int)})
13084      * for its state to be saved.  This flag can only disable the
13085      * saving of this view; any child views may still have their state saved.
13086      *
13087      * @param enabled Set to false to <em>disable</em> state saving, or true
13088      * (the default) to allow it.
13089      *
13090      * @see #isSaveEnabled()
13091      * @see #setId(int)
13092      * @see #onSaveInstanceState()
13093      * @attr ref android.R.styleable#View_saveEnabled
13094      */
setSaveEnabled(boolean enabled)13095     public void setSaveEnabled(boolean enabled) {
13096         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
13097     }
13098 
13099     /**
13100      * Gets whether the framework should discard touches when the view's
13101      * window is obscured by another visible window at the touched location.
13102      * Refer to the {@link View} security documentation for more details.
13103      *
13104      * @return True if touch filtering is enabled.
13105      *
13106      * @see #setFilterTouchesWhenObscured(boolean)
13107      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
13108      */
13109     @ViewDebug.ExportedProperty
13110     @InspectableProperty
getFilterTouchesWhenObscured()13111     public boolean getFilterTouchesWhenObscured() {
13112         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
13113     }
13114 
13115     /**
13116      * Sets whether the framework should discard touches when the view's
13117      * window is obscured by another visible window at the touched location.
13118      * Refer to the {@link View} security documentation for more details.
13119      *
13120      * @param enabled True if touch filtering should be enabled.
13121      *
13122      * @see #getFilterTouchesWhenObscured
13123      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
13124      */
setFilterTouchesWhenObscured(boolean enabled)13125     public void setFilterTouchesWhenObscured(boolean enabled) {
13126         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
13127                 FILTER_TOUCHES_WHEN_OBSCURED);
13128     }
13129 
13130     /**
13131      * Indicates whether the entire hierarchy under this view will save its
13132      * state when a state saving traversal occurs from its parent.  The default
13133      * is true; if false, these views will not be saved unless
13134      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
13135      *
13136      * @return Returns true if the view state saving from parent is enabled, else false.
13137      *
13138      * @see #setSaveFromParentEnabled(boolean)
13139      */
isSaveFromParentEnabled()13140     public boolean isSaveFromParentEnabled() {
13141         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
13142     }
13143 
13144     /**
13145      * Controls whether the entire hierarchy under this view will save its
13146      * state when a state saving traversal occurs from its parent.  The default
13147      * is true; if false, these views will not be saved unless
13148      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
13149      *
13150      * @param enabled Set to false to <em>disable</em> state saving, or true
13151      * (the default) to allow it.
13152      *
13153      * @see #isSaveFromParentEnabled()
13154      * @see #setId(int)
13155      * @see #onSaveInstanceState()
13156      */
setSaveFromParentEnabled(boolean enabled)13157     public void setSaveFromParentEnabled(boolean enabled) {
13158         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
13159     }
13160 
13161 
13162     /**
13163      * Returns whether this View is currently able to take focus.
13164      *
13165      * @return True if this view can take focus, or false otherwise.
13166      */
13167     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()13168     public final boolean isFocusable() {
13169         return FOCUSABLE == (mViewFlags & FOCUSABLE);
13170     }
13171 
13172     /**
13173      * Returns the focusable setting for this view.
13174      *
13175      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
13176      * @attr ref android.R.styleable#View_focusable
13177      */
13178     @ViewDebug.ExportedProperty(mapping = {
13179             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
13180             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
13181             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
13182             }, category = "focus")
13183     @InspectableProperty(enumMapping = {
13184             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
13185             @EnumEntry(value = FOCUSABLE, name = "true"),
13186             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
13187     })
13188     @Focusable
getFocusable()13189     public int getFocusable() {
13190         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
13191     }
13192 
13193     /**
13194      * When a view is focusable, it may not want to take focus when in touch mode.
13195      * For example, a button would like focus when the user is navigating via a D-pad
13196      * so that the user can click on it, but once the user starts touching the screen,
13197      * the button shouldn't take focus
13198      * @return Whether the view is focusable in touch mode.
13199      * @attr ref android.R.styleable#View_focusableInTouchMode
13200      */
13201     @ViewDebug.ExportedProperty(category = "focus")
13202     @InspectableProperty
isFocusableInTouchMode()13203     public final boolean isFocusableInTouchMode() {
13204         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
13205     }
13206 
13207     /**
13208      * Returns whether the view should be treated as a focusable unit by screen reader
13209      * accessibility tools.
13210      * @see #setScreenReaderFocusable(boolean)
13211      *
13212      * @return Whether the view should be treated as a focusable unit by screen reader.
13213      *
13214      * @attr ref android.R.styleable#View_screenReaderFocusable
13215      */
13216     @InspectableProperty
isScreenReaderFocusable()13217     public boolean isScreenReaderFocusable() {
13218         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
13219     }
13220 
13221     /**
13222      * Sets whether this View should be a focusable element for screen readers
13223      * and include non-focusable Views from its subtree when providing feedback.
13224      * <p>
13225      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
13226      * but does not impact input focus behavior.
13227      *
13228      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
13229      *                              accessibility tools.
13230      *
13231      * @attr ref android.R.styleable#View_screenReaderFocusable
13232      */
setScreenReaderFocusable(boolean screenReaderFocusable)13233     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
13234         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
13235     }
13236 
13237     /**
13238      * Gets whether this view is a heading for accessibility purposes.
13239      *
13240      * @return {@code true} if the view is a heading, {@code false} otherwise.
13241      *
13242      * @attr ref android.R.styleable#View_accessibilityHeading
13243      */
13244     @InspectableProperty
isAccessibilityHeading()13245     public boolean isAccessibilityHeading() {
13246         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
13247     }
13248 
13249     /**
13250      * Set if view is a heading for a section of content for accessibility purposes.
13251      *
13252      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
13253      *
13254      * @attr ref android.R.styleable#View_accessibilityHeading
13255      */
setAccessibilityHeading(boolean isHeading)13256     public void setAccessibilityHeading(boolean isHeading) {
13257         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
13258     }
13259 
updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue)13260     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
13261         int pflags3 = mPrivateFlags3;
13262         if (newValue) {
13263             pflags3 |= mask;
13264         } else {
13265             pflags3 &= ~mask;
13266         }
13267 
13268         if (pflags3 != mPrivateFlags3) {
13269             mPrivateFlags3 = pflags3;
13270             notifyViewAccessibilityStateChangedIfNeeded(
13271                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13272         }
13273     }
13274 
13275     /**
13276      * Find the nearest view in the specified direction that can take focus.
13277      * This does not actually give focus to that view.
13278      *
13279      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13280      *
13281      * @return The nearest focusable in the specified direction, or null if none
13282      *         can be found.
13283      */
focusSearch(@ocusRealDirection int direction)13284     public View focusSearch(@FocusRealDirection int direction) {
13285         if (mParent != null) {
13286             return mParent.focusSearch(this, direction);
13287         } else {
13288             return null;
13289         }
13290     }
13291 
13292     /**
13293      * Returns whether this View is a root of a keyboard navigation cluster.
13294      *
13295      * @return True if this view is a root of a cluster, or false otherwise.
13296      * @attr ref android.R.styleable#View_keyboardNavigationCluster
13297      */
13298     @ViewDebug.ExportedProperty(category = "focus")
13299     @InspectableProperty
isKeyboardNavigationCluster()13300     public final boolean isKeyboardNavigationCluster() {
13301         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
13302     }
13303 
13304     /**
13305      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
13306      * will be ignored.
13307      *
13308      * @return the keyboard navigation cluster that this view is in (can be this view)
13309      *         or {@code null} if not in one
13310      */
findKeyboardNavigationCluster()13311     View findKeyboardNavigationCluster() {
13312         if (mParent instanceof View) {
13313             View cluster = ((View) mParent).findKeyboardNavigationCluster();
13314             if (cluster != null) {
13315                 return cluster;
13316             } else if (isKeyboardNavigationCluster()) {
13317                 return this;
13318             }
13319         }
13320         return null;
13321     }
13322 
13323     /**
13324      * Set whether this view is a root of a keyboard navigation cluster.
13325      *
13326      * @param isCluster If true, this view is a root of a cluster.
13327      *
13328      * @attr ref android.R.styleable#View_keyboardNavigationCluster
13329      */
setKeyboardNavigationCluster(boolean isCluster)13330     public void setKeyboardNavigationCluster(boolean isCluster) {
13331         if (isCluster) {
13332             mPrivateFlags3 |= PFLAG3_CLUSTER;
13333         } else {
13334             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
13335         }
13336     }
13337 
13338     /**
13339      * Sets this View as the one which receives focus the next time cluster navigation jumps
13340      * to the cluster containing this View. This does NOT change focus even if the cluster
13341      * containing this view is current.
13342      *
13343      * @hide
13344      */
13345     @TestApi
setFocusedInCluster()13346     public final void setFocusedInCluster() {
13347         setFocusedInCluster(findKeyboardNavigationCluster());
13348     }
13349 
setFocusedInCluster(View cluster)13350     private void setFocusedInCluster(View cluster) {
13351         if (this instanceof ViewGroup) {
13352             ((ViewGroup) this).mFocusedInCluster = null;
13353         }
13354         if (cluster == this) {
13355             return;
13356         }
13357         ViewParent parent = mParent;
13358         View child = this;
13359         while (parent instanceof ViewGroup) {
13360             ((ViewGroup) parent).mFocusedInCluster = child;
13361             if (parent == cluster) {
13362                 break;
13363             }
13364             child = (View) parent;
13365             parent = parent.getParent();
13366         }
13367     }
13368 
updateFocusedInCluster(View oldFocus, @FocusDirection int direction)13369     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
13370         if (oldFocus != null) {
13371             View oldCluster = oldFocus.findKeyboardNavigationCluster();
13372             View cluster = findKeyboardNavigationCluster();
13373             if (oldCluster != cluster) {
13374                 // Going from one cluster to another, so save last-focused.
13375                 // This covers cluster jumps because they are always FOCUS_DOWN
13376                 oldFocus.setFocusedInCluster(oldCluster);
13377                 if (!(oldFocus.mParent instanceof ViewGroup)) {
13378                     return;
13379                 }
13380                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
13381                     // This is a result of ordered navigation so consider navigation through
13382                     // the previous cluster "complete" and clear its last-focused memory.
13383                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
13384                 } else if (oldFocus instanceof ViewGroup
13385                         && ((ViewGroup) oldFocus).getDescendantFocusability()
13386                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
13387                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
13388                     // This means oldFocus is not focusable since it obviously has a focusable
13389                     // child (this). Don't restore focus to it in the future.
13390                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
13391                 }
13392             }
13393         }
13394     }
13395 
13396     /**
13397      * Returns whether this View should receive focus when the focus is restored for the view
13398      * hierarchy containing this view.
13399      * <p>
13400      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
13401      * window or serves as a target of cluster navigation.
13402      *
13403      * @see #restoreDefaultFocus()
13404      *
13405      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
13406      * @attr ref android.R.styleable#View_focusedByDefault
13407      */
13408     @ViewDebug.ExportedProperty(category = "focus")
13409     @InspectableProperty
isFocusedByDefault()13410     public final boolean isFocusedByDefault() {
13411         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
13412     }
13413 
13414     /**
13415      * Sets whether this View should receive focus when the focus is restored for the view
13416      * hierarchy containing this view.
13417      * <p>
13418      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
13419      * window or serves as a target of cluster navigation.
13420      *
13421      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
13422      *                           {@code false} otherwise.
13423      *
13424      * @see #restoreDefaultFocus()
13425      *
13426      * @attr ref android.R.styleable#View_focusedByDefault
13427      */
13428     @RemotableViewMethod
setFocusedByDefault(boolean isFocusedByDefault)13429     public void setFocusedByDefault(boolean isFocusedByDefault) {
13430         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
13431             return;
13432         }
13433 
13434         if (isFocusedByDefault) {
13435             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
13436         } else {
13437             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
13438         }
13439 
13440         if (mParent instanceof ViewGroup) {
13441             if (isFocusedByDefault) {
13442                 ((ViewGroup) mParent).setDefaultFocus(this);
13443             } else {
13444                 ((ViewGroup) mParent).clearDefaultFocus(this);
13445             }
13446         }
13447     }
13448 
13449     /**
13450      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
13451      *
13452      * @return {@code true} if this view has default focus, {@code false} otherwise
13453      */
hasDefaultFocus()13454     boolean hasDefaultFocus() {
13455         return isFocusedByDefault();
13456     }
13457 
13458     /**
13459      * Find the nearest keyboard navigation cluster in the specified direction.
13460      * This does not actually give focus to that cluster.
13461      *
13462      * @param currentCluster The starting point of the search. Null means the current cluster is not
13463      *                       found yet
13464      * @param direction Direction to look
13465      *
13466      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
13467      *         can be found
13468      */
keyboardNavigationClusterSearch(View currentCluster, @FocusDirection int direction)13469     public View keyboardNavigationClusterSearch(View currentCluster,
13470             @FocusDirection int direction) {
13471         if (isKeyboardNavigationCluster()) {
13472             currentCluster = this;
13473         }
13474         if (isRootNamespace()) {
13475             // Root namespace means we should consider ourselves the top of the
13476             // tree for group searching; otherwise we could be group searching
13477             // into other tabs.  see LocalActivityManager and TabHost for more info.
13478             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
13479                     this, currentCluster, direction);
13480         } else if (mParent != null) {
13481             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
13482         }
13483         return null;
13484     }
13485 
13486     /**
13487      * This method is the last chance for the focused view and its ancestors to
13488      * respond to an arrow key. This is called when the focused view did not
13489      * consume the key internally, nor could the view system find a new view in
13490      * the requested direction to give focus to.
13491      *
13492      * @param focused The currently focused view.
13493      * @param direction The direction focus wants to move. One of FOCUS_UP,
13494      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
13495      * @return True if the this view consumed this unhandled move.
13496      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)13497     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
13498         return false;
13499     }
13500 
13501     /**
13502      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
13503      * have {@link android.R.attr#state_focused} defined in its background.
13504      *
13505      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
13506      *                                      highlight, {@code false} otherwise.
13507      *
13508      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
13509      */
setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled)13510     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
13511         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
13512     }
13513 
13514     /**
13515      * Returns whether this View should use a default focus highlight when it gets focused but
13516      * doesn't have {@link android.R.attr#state_focused} defined in its background.
13517      *
13518      * @return True if this View should use a default focus highlight.
13519      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
13520      */
13521     @ViewDebug.ExportedProperty(category = "focus")
13522     @InspectableProperty
getDefaultFocusHighlightEnabled()13523     public final boolean getDefaultFocusHighlightEnabled() {
13524         return mDefaultFocusHighlightEnabled;
13525     }
13526 
13527     /**
13528      * If a user manually specified the next view id for a particular direction,
13529      * use the root to look up the view.
13530      * @param root The root view of the hierarchy containing this view.
13531      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
13532      * or FOCUS_BACKWARD.
13533      * @return The user specified next view, or null if there is none.
13534      */
findUserSetNextFocus(View root, @FocusDirection int direction)13535     View findUserSetNextFocus(View root, @FocusDirection int direction) {
13536         switch (direction) {
13537             case FOCUS_LEFT:
13538                 if (mNextFocusLeftId == View.NO_ID) return null;
13539                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
13540             case FOCUS_RIGHT:
13541                 if (mNextFocusRightId == View.NO_ID) return null;
13542                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
13543             case FOCUS_UP:
13544                 if (mNextFocusUpId == View.NO_ID) return null;
13545                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
13546             case FOCUS_DOWN:
13547                 if (mNextFocusDownId == View.NO_ID) return null;
13548                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
13549             case FOCUS_FORWARD:
13550                 if (mNextFocusForwardId == View.NO_ID) return null;
13551                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
13552             case FOCUS_BACKWARD: {
13553                 if (mID == View.NO_ID) return null;
13554                 final View rootView = root;
13555                 final View startView = this;
13556                 // Since we have forward links but no backward links, we need to find the view that
13557                 // forward links to this view. We can't just find the view with the specified ID
13558                 // because view IDs need not be unique throughout the tree.
13559                 return root.findViewByPredicateInsideOut(startView,
13560                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
13561                             == startView);
13562             }
13563         }
13564         return null;
13565     }
13566 
13567     /**
13568      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
13569      * use the root to look up the view.
13570      *
13571      * @param root the root view of the hierarchy containing this view
13572      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
13573      * @return the user-specified next cluster, or {@code null} if there is none
13574      */
findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction)13575     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
13576         switch (direction) {
13577             case FOCUS_FORWARD:
13578                 if (mNextClusterForwardId == View.NO_ID) return null;
13579                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
13580             case FOCUS_BACKWARD: {
13581                 if (mID == View.NO_ID) return null;
13582                 final int id = mID;
13583                 return root.findViewByPredicateInsideOut(this,
13584                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
13585             }
13586         }
13587         return null;
13588     }
13589 
findViewInsideOutShouldExist(View root, int id)13590     private View findViewInsideOutShouldExist(View root, int id) {
13591         return findViewInsideOutShouldExist(root, this, id);
13592     }
13593 
findViewInsideOutShouldExist(View root, View start, int id)13594     private View findViewInsideOutShouldExist(View root, View start, int id) {
13595         if (mMatchIdPredicate == null) {
13596             mMatchIdPredicate = new MatchIdPredicate();
13597         }
13598         mMatchIdPredicate.mId = id;
13599         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
13600         if (result == null) {
13601             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
13602         }
13603         return result;
13604     }
13605 
13606     /**
13607      * Find and return all focusable views that are descendants of this view,
13608      * possibly including this view if it is focusable itself.
13609      *
13610      * @param direction The direction of the focus
13611      * @return A list of focusable views
13612      */
getFocusables(@ocusDirection int direction)13613     public ArrayList<View> getFocusables(@FocusDirection int direction) {
13614         ArrayList<View> result = new ArrayList<View>(24);
13615         addFocusables(result, direction);
13616         return result;
13617     }
13618 
13619     /**
13620      * Add any focusable views that are descendants of this view (possibly
13621      * including this view if it is focusable itself) to views.  If we are in touch mode,
13622      * only add views that are also focusable in touch mode.
13623      *
13624      * @param views Focusable views found so far
13625      * @param direction The direction of the focus
13626      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)13627     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
13628         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
13629     }
13630 
13631     /**
13632      * Adds any focusable views that are descendants of this view (possibly
13633      * including this view if it is focusable itself) to views. This method
13634      * adds all focusable views regardless if we are in touch mode or
13635      * only views focusable in touch mode if we are in touch mode or
13636      * only views that can take accessibility focus if accessibility is enabled
13637      * depending on the focusable mode parameter.
13638      *
13639      * @param views Focusable views found so far or null if all we are interested is
13640      *        the number of focusables.
13641      * @param direction The direction of the focus.
13642      * @param focusableMode The type of focusables to be added.
13643      *
13644      * @see #FOCUSABLES_ALL
13645      * @see #FOCUSABLES_TOUCH_MODE
13646      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)13647     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
13648             @FocusableMode int focusableMode) {
13649         if (views == null) {
13650             return;
13651         }
13652         if (!canTakeFocus()) {
13653             return;
13654         }
13655         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
13656                 && !isFocusableInTouchMode()) {
13657             return;
13658         }
13659         views.add(this);
13660     }
13661 
13662     /**
13663      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
13664      * including this view if it is a cluster root itself) to views.
13665      *
13666      * @param views Keyboard navigation cluster roots found so far
13667      * @param direction Direction to look
13668      */
addKeyboardNavigationClusters( @onNull Collection<View> views, int direction)13669     public void addKeyboardNavigationClusters(
13670             @NonNull Collection<View> views,
13671             int direction) {
13672         if (!isKeyboardNavigationCluster()) {
13673             return;
13674         }
13675         if (!hasFocusable()) {
13676             return;
13677         }
13678         views.add(this);
13679     }
13680 
13681     /**
13682      * Finds the Views that contain given text. The containment is case insensitive.
13683      * The search is performed by either the text that the View renders or the content
13684      * description that describes the view for accessibility purposes and the view does
13685      * not render or both. Clients can specify how the search is to be performed via
13686      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
13687      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
13688      *
13689      * @param outViews The output list of matching Views.
13690      * @param searched The text to match against.
13691      *
13692      * @see #FIND_VIEWS_WITH_TEXT
13693      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
13694      * @see #setContentDescription(CharSequence)
13695      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)13696     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
13697             @FindViewFlags int flags) {
13698         if (getAccessibilityNodeProvider() != null) {
13699             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
13700                 outViews.add(this);
13701             }
13702         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
13703                 && (searched != null && searched.length() > 0)
13704                 && (mContentDescription != null && mContentDescription.length() > 0)) {
13705             String searchedLowerCase = searched.toString().toLowerCase();
13706             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
13707             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
13708                 outViews.add(this);
13709             }
13710         }
13711     }
13712 
13713     /**
13714      * Find and return all touchable views that are descendants of this view,
13715      * possibly including this view if it is touchable itself.
13716      *
13717      * @return A list of touchable views
13718      */
getTouchables()13719     public ArrayList<View> getTouchables() {
13720         ArrayList<View> result = new ArrayList<View>();
13721         addTouchables(result);
13722         return result;
13723     }
13724 
13725     /**
13726      * Add any touchable views that are descendants of this view (possibly
13727      * including this view if it is touchable itself) to views.
13728      *
13729      * @param views Touchable views found so far
13730      */
addTouchables(ArrayList<View> views)13731     public void addTouchables(ArrayList<View> views) {
13732         final int viewFlags = mViewFlags;
13733 
13734         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
13735                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
13736                 && (viewFlags & ENABLED_MASK) == ENABLED) {
13737             views.add(this);
13738         }
13739     }
13740 
13741     /**
13742      * Returns whether this View is accessibility focused.
13743      *
13744      * @return True if this View is accessibility focused.
13745      */
13746     @InspectableProperty(hasAttributeId = false)
isAccessibilityFocused()13747     public boolean isAccessibilityFocused() {
13748         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
13749     }
13750 
13751     /**
13752      * Call this to try to give accessibility focus to this view.
13753      *
13754      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
13755      * returns false or the view is no visible or the view already has accessibility
13756      * focus.
13757      *
13758      * See also {@link #focusSearch(int)}, which is what you call to say that you
13759      * have focus, and you want your parent to look for the next one.
13760      *
13761      * @return Whether this view actually took accessibility focus.
13762      *
13763      * @hide
13764      */
13765     @UnsupportedAppUsage
requestAccessibilityFocus()13766     public boolean requestAccessibilityFocus() {
13767         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
13768         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
13769             return false;
13770         }
13771         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
13772             return false;
13773         }
13774         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
13775             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
13776             ViewRootImpl viewRootImpl = getViewRootImpl();
13777             if (viewRootImpl != null) {
13778                 viewRootImpl.setAccessibilityFocus(this, null);
13779             }
13780             invalidate();
13781             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
13782             return true;
13783         }
13784         return false;
13785     }
13786 
13787     /**
13788      * Call this to try to clear accessibility focus of this view.
13789      *
13790      * See also {@link #focusSearch(int)}, which is what you call to say that you
13791      * have focus, and you want your parent to look for the next one.
13792      *
13793      * @hide
13794      */
13795     @UnsupportedAppUsage
clearAccessibilityFocus()13796     public void clearAccessibilityFocus() {
13797         clearAccessibilityFocusNoCallbacks(0);
13798 
13799         // Clear the global reference of accessibility focus if this view or
13800         // any of its descendants had accessibility focus. This will NOT send
13801         // an event or update internal state if focus is cleared from a
13802         // descendant view, which may leave views in inconsistent states.
13803         final ViewRootImpl viewRootImpl = getViewRootImpl();
13804         if (viewRootImpl != null) {
13805             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
13806             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13807                 viewRootImpl.setAccessibilityFocus(null, null);
13808             }
13809         }
13810     }
13811 
sendAccessibilityHoverEvent(int eventType)13812     private void sendAccessibilityHoverEvent(int eventType) {
13813         // Since we are not delivering to a client accessibility events from not
13814         // important views (unless the clinet request that) we need to fire the
13815         // event from the deepest view exposed to the client. As a consequence if
13816         // the user crosses a not exposed view the client will see enter and exit
13817         // of the exposed predecessor followed by and enter and exit of that same
13818         // predecessor when entering and exiting the not exposed descendant. This
13819         // is fine since the client has a clear idea which view is hovered at the
13820         // price of a couple more events being sent. This is a simple and
13821         // working solution.
13822         View source = this;
13823         while (true) {
13824             if (source.includeForAccessibility()) {
13825                 source.sendAccessibilityEvent(eventType);
13826                 return;
13827             }
13828             ViewParent parent = source.getParent();
13829             if (parent instanceof View) {
13830                 source = (View) parent;
13831             } else {
13832                 return;
13833             }
13834         }
13835     }
13836 
13837     /**
13838      * Clears accessibility focus without calling any callback methods
13839      * normally invoked in {@link #clearAccessibilityFocus()}. This method
13840      * is used separately from that one for clearing accessibility focus when
13841      * giving this focus to another view.
13842      *
13843      * @param action The action, if any, that led to focus being cleared. Set to
13844      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
13845      * the window.
13846      */
clearAccessibilityFocusNoCallbacks(int action)13847     void clearAccessibilityFocusNoCallbacks(int action) {
13848         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
13849             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
13850             invalidate();
13851             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13852                 AccessibilityEvent event = AccessibilityEvent.obtain(
13853                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
13854                 event.setAction(action);
13855                 if (mAccessibilityDelegate != null) {
13856                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
13857                 } else {
13858                     sendAccessibilityEventUnchecked(event);
13859                 }
13860             }
13861 
13862             updatePreferKeepClearForFocus();
13863         }
13864     }
13865 
13866     /**
13867      * Call this to try to give focus to a specific view or to one of its
13868      * descendants.
13869      *
13870      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13871      * false), or if it can't be focused due to other conditions (not focusable in touch mode
13872      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
13873      * enabled, or has no size).
13874      *
13875      * See also {@link #focusSearch(int)}, which is what you call to say that you
13876      * have focus, and you want your parent to look for the next one.
13877      *
13878      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
13879      * {@link #FOCUS_DOWN} and <code>null</code>.
13880      *
13881      * @return Whether this view or one of its descendants actually took focus.
13882      */
requestFocus()13883     public final boolean requestFocus() {
13884         return requestFocus(View.FOCUS_DOWN);
13885     }
13886 
13887     /**
13888      * This will request focus for whichever View was last focused within this
13889      * cluster before a focus-jump out of it.
13890      *
13891      * @hide
13892      */
13893     @TestApi
restoreFocusInCluster(@ocusRealDirection int direction)13894     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
13895         // Prioritize focusableByDefault over algorithmic focus selection.
13896         if (restoreDefaultFocus()) {
13897             return true;
13898         }
13899         return requestFocus(direction);
13900     }
13901 
13902     /**
13903      * This will request focus for whichever View not in a cluster was last focused before a
13904      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
13905      * the "first" focusable view it finds.
13906      *
13907      * @hide
13908      */
13909     @TestApi
restoreFocusNotInCluster()13910     public boolean restoreFocusNotInCluster() {
13911         return requestFocus(View.FOCUS_DOWN);
13912     }
13913 
13914     /**
13915      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
13916      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
13917      *
13918      * @return Whether this view or one of its descendants actually took focus
13919      */
restoreDefaultFocus()13920     public boolean restoreDefaultFocus() {
13921         return requestFocus(View.FOCUS_DOWN);
13922     }
13923 
13924     /**
13925      * Call this to try to give focus to a specific view or to one of its
13926      * descendants and give it a hint about what direction focus is heading.
13927      *
13928      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13929      * false), or if it is focusable and it is not focusable in touch mode
13930      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13931      *
13932      * See also {@link #focusSearch(int)}, which is what you call to say that you
13933      * have focus, and you want your parent to look for the next one.
13934      *
13935      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
13936      * <code>null</code> set for the previously focused rectangle.
13937      *
13938      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13939      * @return Whether this view or one of its descendants actually took focus.
13940      */
requestFocus(int direction)13941     public final boolean requestFocus(int direction) {
13942         return requestFocus(direction, null);
13943     }
13944 
13945     /**
13946      * Call this to try to give focus to a specific view or to one of its descendants
13947      * and give it hints about the direction and a specific rectangle that the focus
13948      * is coming from.  The rectangle can help give larger views a finer grained hint
13949      * about where focus is coming from, and therefore, where to show selection, or
13950      * forward focus change internally.
13951      *
13952      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13953      * false), or if it is focusable and it is not focusable in touch mode
13954      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13955      *
13956      * A View will not take focus if it is not visible.
13957      *
13958      * A View will not take focus if one of its parents has
13959      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
13960      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
13961      *
13962      * See also {@link #focusSearch(int)}, which is what you call to say that you
13963      * have focus, and you want your parent to look for the next one.
13964      *
13965      * You may wish to override this method if your custom {@link View} has an internal
13966      * {@link View} that it wishes to forward the request to.
13967      *
13968      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13969      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
13970      *        to give a finer grained hint about where focus is coming from.  May be null
13971      *        if there is no hint.
13972      * @return Whether this view or one of its descendants actually took focus.
13973      */
requestFocus(int direction, Rect previouslyFocusedRect)13974     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
13975         return requestFocusNoSearch(direction, previouslyFocusedRect);
13976     }
13977 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)13978     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
13979         // need to be focusable
13980         if (!canTakeFocus()) {
13981             return false;
13982         }
13983 
13984         // need to be focusable in touch mode if in touch mode
13985         if (isInTouchMode() &&
13986             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
13987                return false;
13988         }
13989 
13990         // need to not have any parents blocking us
13991         if (hasAncestorThatBlocksDescendantFocus()) {
13992             return false;
13993         }
13994 
13995         if (!isLayoutValid()) {
13996             mPrivateFlags |= PFLAG_WANTS_FOCUS;
13997         } else {
13998             clearParentsWantFocus();
13999         }
14000 
14001         handleFocusGainInternal(direction, previouslyFocusedRect);
14002         return true;
14003     }
14004 
clearParentsWantFocus()14005     void clearParentsWantFocus() {
14006         if (mParent instanceof View) {
14007             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
14008             ((View) mParent).clearParentsWantFocus();
14009         }
14010     }
14011 
14012     /**
14013      * Call this to try to give focus to a specific view or to one of its descendants. This is a
14014      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
14015      * touch mode to request focus when they are touched.
14016      *
14017      * @return Whether this view or one of its descendants actually took focus.
14018      *
14019      * @see #isInTouchMode()
14020      *
14021      */
requestFocusFromTouch()14022     public final boolean requestFocusFromTouch() {
14023         // Leave touch mode if we need to
14024         if (isInTouchMode()) {
14025             ViewRootImpl viewRoot = getViewRootImpl();
14026             if (viewRoot != null) {
14027                 viewRoot.ensureTouchMode(false);
14028             }
14029         }
14030         return requestFocus(View.FOCUS_DOWN);
14031     }
14032 
14033     /**
14034      * @return Whether any ancestor of this view blocks descendant focus.
14035      */
hasAncestorThatBlocksDescendantFocus()14036     private boolean hasAncestorThatBlocksDescendantFocus() {
14037         final boolean focusableInTouchMode = isFocusableInTouchMode();
14038         ViewParent ancestor = mParent;
14039         while (ancestor instanceof ViewGroup) {
14040             final ViewGroup vgAncestor = (ViewGroup) ancestor;
14041             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
14042                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
14043                 return true;
14044             } else {
14045                 ancestor = vgAncestor.getParent();
14046             }
14047         }
14048         return false;
14049     }
14050 
14051     /**
14052      * Gets the mode for determining whether this View is important for accessibility.
14053      * A view is important for accessibility if it fires accessibility events and if it
14054      * is reported to accessibility services that query the screen.
14055      *
14056      * @return The mode for determining whether a view is important for accessibility, one
14057      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
14058      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
14059      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
14060      *
14061      * @attr ref android.R.styleable#View_importantForAccessibility
14062      *
14063      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
14064      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
14065      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
14066      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
14067      */
14068     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
14069             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
14070             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
14071             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
14072             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
14073                     to = "noHideDescendants")
14074         })
14075     @InspectableProperty(enumMapping = {
14076             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
14077             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
14078             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
14079             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
14080                     name = "noHideDescendants"),
14081     })
getImportantForAccessibility()14082     public int getImportantForAccessibility() {
14083         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
14084                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
14085     }
14086 
14087     /**
14088      * Sets the live region mode for this view. This indicates to accessibility
14089      * services whether they should automatically notify the user about changes
14090      * to the view's content description or text, or to the content descriptions
14091      * or text of the view's children (where applicable).
14092      * <p>
14093      * For example, in a login screen with a TextView that displays an "incorrect
14094      * password" notification, that view should be marked as a live region with
14095      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
14096      * <p>
14097      * To disable change notifications for this view, use
14098      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
14099      * mode for most views.
14100      * <p>
14101      * To indicate that the user should be notified of changes, use
14102      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
14103      * <p>
14104      * If the view's changes should interrupt ongoing speech and notify the user
14105      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
14106      *
14107      * @param mode The live region mode for this view, one of:
14108      *        <ul>
14109      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
14110      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
14111      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
14112      *        </ul>
14113      * @attr ref android.R.styleable#View_accessibilityLiveRegion
14114      */
setAccessibilityLiveRegion(int mode)14115     public void setAccessibilityLiveRegion(int mode) {
14116         if (mode != getAccessibilityLiveRegion()) {
14117             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
14118             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
14119                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
14120             notifyViewAccessibilityStateChangedIfNeeded(
14121                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14122         }
14123     }
14124 
14125     /**
14126      * Gets the live region mode for this View.
14127      *
14128      * @return The live region mode for the view.
14129      *
14130      * @attr ref android.R.styleable#View_accessibilityLiveRegion
14131      *
14132      * @see #setAccessibilityLiveRegion(int)
14133      */
14134     @InspectableProperty(enumMapping = {
14135             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
14136             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
14137             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
14138     })
getAccessibilityLiveRegion()14139     public int getAccessibilityLiveRegion() {
14140         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
14141                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
14142     }
14143 
14144     /**
14145      * Sets how to determine whether this view is important for accessibility
14146      * which is if it fires accessibility events and if it is reported to
14147      * accessibility services that query the screen.
14148      *
14149      * @param mode How to determine whether this view is important for accessibility.
14150      *
14151      * @attr ref android.R.styleable#View_importantForAccessibility
14152      *
14153      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
14154      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
14155      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
14156      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
14157      */
setImportantForAccessibility(int mode)14158     public void setImportantForAccessibility(int mode) {
14159         final int oldMode = getImportantForAccessibility();
14160         if (mode != oldMode) {
14161             final boolean hideDescendants =
14162                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
14163 
14164             // If this node or its descendants are no longer important, try to
14165             // clear accessibility focus.
14166             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
14167                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
14168                 if (focusHost != null) {
14169                     focusHost.clearAccessibilityFocus();
14170                 }
14171             }
14172 
14173             // If we're moving between AUTO and another state, we might not need
14174             // to send a subtree changed notification. We'll store the computed
14175             // importance, since we'll need to check it later to make sure.
14176             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
14177                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
14178             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
14179             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
14180             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
14181                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
14182             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
14183                 notifySubtreeAccessibilityStateChangedIfNeeded();
14184             } else {
14185                 notifyViewAccessibilityStateChangedIfNeeded(
14186                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14187             }
14188         }
14189     }
14190 
14191     /**
14192      * Returns the view within this view's hierarchy that is hosting
14193      * accessibility focus.
14194      *
14195      * @param searchDescendants whether to search for focus in descendant views
14196      * @return the view hosting accessibility focus, or {@code null}
14197      */
findAccessibilityFocusHost(boolean searchDescendants)14198     private View findAccessibilityFocusHost(boolean searchDescendants) {
14199         if (isAccessibilityFocusedViewOrHost()) {
14200             return this;
14201         }
14202 
14203         if (searchDescendants) {
14204             final ViewRootImpl viewRoot = getViewRootImpl();
14205             if (viewRoot != null) {
14206                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
14207                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
14208                     return focusHost;
14209                 }
14210             }
14211         }
14212 
14213         return null;
14214     }
14215 
14216     /**
14217      * Computes whether this view should be exposed for accessibility. In
14218      * general, views that are interactive or provide information are exposed
14219      * while views that serve only as containers are hidden.
14220      * <p>
14221      * If an ancestor of this view has importance
14222      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
14223      * returns <code>false</code>.
14224      * <p>
14225      * Otherwise, the value is computed according to the view's
14226      * {@link #getImportantForAccessibility()} value:
14227      * <ol>
14228      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
14229      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
14230      * </code>
14231      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
14232      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
14233      * view satisfies any of the following:
14234      * <ul>
14235      * <li>Is actionable, e.g. {@link #isClickable()},
14236      * {@link #isLongClickable()}, or {@link #isFocusable()}
14237      * <li>Has an {@link AccessibilityDelegate}
14238      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
14239      * {@link OnKeyListener}, etc.
14240      * <li>Is an accessibility live region, e.g.
14241      * {@link #getAccessibilityLiveRegion()} is not
14242      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
14243      * </ul>
14244      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
14245      * </ol>
14246      *
14247      * @return Whether the view is exposed for accessibility.
14248      * @see #setImportantForAccessibility(int)
14249      * @see #getImportantForAccessibility()
14250      */
isImportantForAccessibility()14251     public boolean isImportantForAccessibility() {
14252         final int mode = getImportantForAccessibility();
14253         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
14254                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
14255             return false;
14256         }
14257 
14258         // Check parent mode to ensure we're not hidden.
14259         ViewParent parent = mParent;
14260         while (parent instanceof View) {
14261             if (((View) parent).getImportantForAccessibility()
14262                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
14263                 return false;
14264             }
14265             parent = parent.getParent();
14266         }
14267 
14268         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
14269                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
14270                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
14271                 || isAccessibilityPane();
14272     }
14273 
14274     /**
14275      * Gets the parent for accessibility purposes. Note that the parent for
14276      * accessibility is not necessary the immediate parent. It is the first
14277      * predecessor that is important for accessibility.
14278      *
14279      * @return The parent for accessibility purposes.
14280      */
getParentForAccessibility()14281     public ViewParent getParentForAccessibility() {
14282         if (mParent instanceof View) {
14283             View parentView = (View) mParent;
14284             if (parentView.includeForAccessibility()) {
14285                 return mParent;
14286             } else {
14287                 return mParent.getParentForAccessibility();
14288             }
14289         }
14290         return null;
14291     }
14292 
14293     /** @hide */
getSelfOrParentImportantForA11y()14294     View getSelfOrParentImportantForA11y() {
14295         if (isImportantForAccessibility()) return this;
14296         ViewParent parent = getParentForAccessibility();
14297         if (parent instanceof View) return (View) parent;
14298         return null;
14299     }
14300 
14301     /**
14302      * Adds the children of this View relevant for accessibility to the given list
14303      * as output. Since some Views are not important for accessibility the added
14304      * child views are not necessarily direct children of this view, rather they are
14305      * the first level of descendants important for accessibility.
14306      *
14307      * @param outChildren The output list that will receive children for accessibility.
14308      */
addChildrenForAccessibility(ArrayList<View> outChildren)14309     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
14310 
14311     }
14312 
14313     /**
14314      * Whether to regard this view for accessibility. A view is regarded for
14315      * accessibility if it is important for accessibility or the querying
14316      * accessibility service has explicitly requested that view not
14317      * important for accessibility are regarded.
14318      *
14319      * @return Whether to regard the view for accessibility.
14320      *
14321      * @hide
14322      */
14323     @UnsupportedAppUsage
includeForAccessibility()14324     public boolean includeForAccessibility() {
14325         if (mAttachInfo != null) {
14326             return (mAttachInfo.mAccessibilityFetchFlags
14327                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
14328                     || isImportantForAccessibility();
14329         }
14330         return false;
14331     }
14332 
14333     /**
14334      * Returns whether the View is considered actionable from
14335      * accessibility perspective. Such view are important for
14336      * accessibility.
14337      *
14338      * @return True if the view is actionable for accessibility.
14339      *
14340      * @hide
14341      */
isActionableForAccessibility()14342     public boolean isActionableForAccessibility() {
14343         return (isClickable() || isLongClickable() || isFocusable());
14344     }
14345 
14346     /**
14347      * Returns whether the View has registered callbacks which makes it
14348      * important for accessibility.
14349      *
14350      * @return True if the view is actionable for accessibility.
14351      */
hasListenersForAccessibility()14352     private boolean hasListenersForAccessibility() {
14353         ListenerInfo info = getListenerInfo();
14354         return mTouchDelegate != null || info.mOnKeyListener != null
14355                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
14356                 || info.mOnHoverListener != null || info.mOnDragListener != null;
14357     }
14358 
14359     /**
14360      * Notifies that the accessibility state of this view changed. The change
14361      * is local to this view and does not represent structural changes such
14362      * as children and parent. For example, the view became focusable. The
14363      * notification is at at most once every
14364      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
14365      * to avoid unnecessary load to the system. Also once a view has a pending
14366      * notification this method is a NOP until the notification has been sent.
14367      *
14368      * @hide
14369      */
14370     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyViewAccessibilityStateChangedIfNeeded(int changeType)14371     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
14372         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
14373             return;
14374         }
14375 
14376         // Changes to views with a pane title count as window state changes, as the pane title
14377         // marks them as significant parts of the UI. A visible view with a nulled title may send
14378         // a disappeared event.
14379         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
14380                 && (isAccessibilityPane()
14381                 || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)
14382                 && isAggregatedVisible())) {
14383             // If the pane isn't visible, content changed events are sufficient unless we're
14384             // reporting that the view just disappeared
14385             if ((isAggregatedVisible())
14386                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
14387                 final AccessibilityEvent event = AccessibilityEvent.obtain();
14388                 onInitializeAccessibilityEvent(event);
14389                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
14390                 event.setContentChangeTypes(changeType);
14391                 event.setSource(this);
14392                 onPopulateAccessibilityEvent(event);
14393                 if (mParent != null) {
14394                     try {
14395                         mParent.requestSendAccessibilityEvent(this, event);
14396                     } catch (AbstractMethodError e) {
14397                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
14398                                 + " does not fully implement ViewParent", e);
14399                     }
14400                 }
14401                 return;
14402             }
14403         }
14404 
14405         // If this is a live region, we should send a subtree change event
14406         // from this view immediately. Otherwise, we can let it propagate up.
14407         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
14408             final AccessibilityEvent event = AccessibilityEvent.obtain();
14409             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
14410             event.setContentChangeTypes(changeType);
14411             sendAccessibilityEventUnchecked(event);
14412         } else if (mParent != null) {
14413             try {
14414                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
14415             } catch (AbstractMethodError e) {
14416                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14417                         " does not fully implement ViewParent", e);
14418             }
14419         }
14420     }
14421 
14422     /**
14423      * Notifies that the accessibility state of this view changed. The change
14424      * is *not* local to this view and does represent structural changes such
14425      * as children and parent. For example, the view size changed. The
14426      * notification is at at most once every
14427      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
14428      * to avoid unnecessary load to the system. Also once a view has a pending
14429      * notification this method is a NOP until the notification has been sent.
14430      *
14431      * @hide
14432      */
14433     @UnsupportedAppUsage
notifySubtreeAccessibilityStateChangedIfNeeded()14434     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
14435         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
14436             return;
14437         }
14438 
14439         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
14440             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
14441             if (mParent != null) {
14442                 try {
14443                     mParent.notifySubtreeAccessibilityStateChanged(
14444                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
14445                 } catch (AbstractMethodError e) {
14446                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14447                             " does not fully implement ViewParent", e);
14448                 }
14449             }
14450         }
14451     }
14452 
notifySubtreeAccessibilityStateChangedByParentIfNeeded()14453     private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
14454         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
14455             return;
14456         }
14457 
14458         final View sendA11yEventView = (View) getParentForAccessibility();
14459         if (sendA11yEventView != null && sendA11yEventView.isShown()) {
14460             sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
14461         }
14462     }
14463 
14464     /**
14465      * Changes the visibility of this View without triggering any other changes. This should only
14466      * be used by animation frameworks, such as {@link android.transition.Transition}, where
14467      * visibility changes should not adjust focus or trigger a new layout. Application developers
14468      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
14469      *
14470      * <p>Only call this method when a temporary visibility must be applied during an
14471      * animation and the original visibility value is guaranteed to be reset after the
14472      * animation completes. Use {@link #setVisibility} in all other cases.</p>
14473      *
14474      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
14475      * @see #setVisibility(int)
14476      */
setTransitionVisibility(@isibility int visibility)14477     public void setTransitionVisibility(@Visibility int visibility) {
14478         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
14479     }
14480 
14481     /**
14482      * Reset the flag indicating the accessibility state of the subtree rooted
14483      * at this view changed.
14484      */
resetSubtreeAccessibilityStateChanged()14485     void resetSubtreeAccessibilityStateChanged() {
14486         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
14487     }
14488 
14489     /**
14490      * Report an accessibility action to this view's parents for delegated processing.
14491      *
14492      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
14493      * call this method to delegate an accessibility action to a supporting parent. If the parent
14494      * returns true from its
14495      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
14496      * method this method will return true to signify that the action was consumed.</p>
14497      *
14498      * <p>This method is useful for implementing nested scrolling child views. If
14499      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
14500      * a custom view implementation may invoke this method to allow a parent to consume the
14501      * scroll first. If this method returns true the custom view should skip its own scrolling
14502      * behavior.</p>
14503      *
14504      * @param action Accessibility action to delegate
14505      * @param arguments Optional action arguments
14506      * @return true if the action was consumed by a parent
14507      */
dispatchNestedPrePerformAccessibilityAction(int action, @Nullable Bundle arguments)14508     public boolean dispatchNestedPrePerformAccessibilityAction(int action,
14509             @Nullable Bundle arguments) {
14510         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
14511             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
14512                 return true;
14513             }
14514         }
14515         return false;
14516     }
14517 
14518     /**
14519      * Performs the specified accessibility action on the view. For
14520      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
14521      * <p>
14522      * If an {@link AccessibilityDelegate} has been specified via calling
14523      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
14524      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
14525      * is responsible for handling this call.
14526      * </p>
14527      *
14528      * <p>The default implementation will delegate
14529      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
14530      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
14531      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
14532      *
14533      * @param action The action to perform.
14534      * @param arguments Optional action arguments.
14535      * @return Whether the action was performed.
14536      */
performAccessibilityAction(int action, @Nullable Bundle arguments)14537     public boolean performAccessibilityAction(int action, @Nullable Bundle arguments) {
14538       if (mAccessibilityDelegate != null) {
14539           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
14540       } else {
14541           return performAccessibilityActionInternal(action, arguments);
14542       }
14543     }
14544 
14545    /**
14546     * @see #performAccessibilityAction(int, Bundle)
14547     *
14548     * Note: Called from the default {@link AccessibilityDelegate}.
14549     *
14550     * @hide
14551     */
14552     @UnsupportedAppUsage
performAccessibilityActionInternal(int action, @Nullable Bundle arguments)14553     public boolean performAccessibilityActionInternal(int action, @Nullable Bundle arguments) {
14554         if (isNestedScrollingEnabled()
14555                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
14556                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
14557                 || action == R.id.accessibilityActionScrollUp
14558                 || action == R.id.accessibilityActionScrollLeft
14559                 || action == R.id.accessibilityActionScrollDown
14560                 || action == R.id.accessibilityActionScrollRight)) {
14561             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
14562                 return true;
14563             }
14564         }
14565 
14566         switch (action) {
14567             case AccessibilityNodeInfo.ACTION_CLICK: {
14568                 if (isClickable()) {
14569                     performClickInternal();
14570                     return true;
14571                 }
14572             } break;
14573             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
14574                 if (isLongClickable()) {
14575                     performLongClick();
14576                     return true;
14577                 }
14578             } break;
14579             case AccessibilityNodeInfo.ACTION_FOCUS: {
14580                 if (!hasFocus()) {
14581                     // Get out of touch mode since accessibility
14582                     // wants to move focus around.
14583                     getViewRootImpl().ensureTouchMode(false);
14584                     return requestFocus();
14585                 }
14586             } break;
14587             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
14588                 if (hasFocus()) {
14589                     clearFocus();
14590                     return !isFocused();
14591                 }
14592             } break;
14593             case AccessibilityNodeInfo.ACTION_SELECT: {
14594                 if (!isSelected()) {
14595                     setSelected(true);
14596                     return isSelected();
14597                 }
14598             } break;
14599             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
14600                 if (isSelected()) {
14601                     setSelected(false);
14602                     return !isSelected();
14603                 }
14604             } break;
14605             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
14606                 if (!isAccessibilityFocused()) {
14607                     return requestAccessibilityFocus();
14608                 }
14609             } break;
14610             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
14611                 if (isAccessibilityFocused()) {
14612                     clearAccessibilityFocus();
14613                     return true;
14614                 }
14615             } break;
14616             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
14617                 if (arguments != null) {
14618                     final int granularity = arguments.getInt(
14619                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
14620                     final boolean extendSelection = arguments.getBoolean(
14621                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
14622                     return traverseAtGranularity(granularity, true, extendSelection);
14623                 }
14624             } break;
14625             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
14626                 if (arguments != null) {
14627                     final int granularity = arguments.getInt(
14628                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
14629                     final boolean extendSelection = arguments.getBoolean(
14630                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
14631                     return traverseAtGranularity(granularity, false, extendSelection);
14632                 }
14633             } break;
14634             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
14635                 CharSequence text = getIterableTextForAccessibility();
14636                 if (text == null) {
14637                     return false;
14638                 }
14639                 final int start = (arguments != null) ? arguments.getInt(
14640                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
14641                 final int end = (arguments != null) ? arguments.getInt(
14642                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
14643                 // Only cursor position can be specified (selection length == 0)
14644                 if ((getAccessibilitySelectionStart() != start
14645                         || getAccessibilitySelectionEnd() != end)
14646                         && (start == end)) {
14647                     setAccessibilitySelection(start, end);
14648                     notifyViewAccessibilityStateChangedIfNeeded(
14649                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14650                     return true;
14651                 }
14652             } break;
14653             case R.id.accessibilityActionShowOnScreen: {
14654                 if (mAttachInfo != null) {
14655                     final Rect r = mAttachInfo.mTmpInvalRect;
14656                     getDrawingRect(r);
14657                     return requestRectangleOnScreen(r, true);
14658                 }
14659             } break;
14660             case R.id.accessibilityActionContextClick: {
14661                 if (isContextClickable()) {
14662                     performContextClick();
14663                     return true;
14664                 }
14665             } break;
14666             case R.id.accessibilityActionShowTooltip: {
14667                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
14668                     // Tooltip already showing
14669                     return false;
14670                 }
14671                 return showLongClickTooltip(0, 0);
14672             }
14673             case R.id.accessibilityActionHideTooltip: {
14674                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
14675                     // No tooltip showing
14676                     return false;
14677                 }
14678                 hideTooltip();
14679                 return true;
14680             }
14681             case R.id.accessibilityActionDragDrop: {
14682                 if (!canAcceptAccessibilityDrop()) {
14683                     return false;
14684                 }
14685                 try {
14686                     if (mAttachInfo != null && mAttachInfo.mSession != null) {
14687                         final int[] location = new int[2];
14688                         getLocationInWindow(location);
14689                         final int centerX = location[0] + getWidth() / 2;
14690                         final int centerY = location[1] + getHeight() / 2;
14691                         return mAttachInfo.mSession.dropForAccessibility(mAttachInfo.mWindow,
14692                                 centerX, centerY);
14693                     }
14694                 } catch (RemoteException e) {
14695                     Log.e(VIEW_LOG_TAG, "Unable to drop for accessibility", e);
14696                 }
14697                 return false;
14698             }
14699             case R.id.accessibilityActionDragCancel: {
14700                 if (!startedSystemDragForAccessibility()) {
14701                     return false;
14702                 }
14703                 if (mAttachInfo != null && mAttachInfo.mDragToken != null) {
14704                     cancelDragAndDrop();
14705                     return true;
14706                 }
14707                 return false;
14708             }
14709         }
14710         return false;
14711     }
14712 
canAcceptAccessibilityDrop()14713     private boolean canAcceptAccessibilityDrop() {
14714         if (!canAcceptDrag()) {
14715             return false;
14716         }
14717         ListenerInfo li = mListenerInfo;
14718         return (li != null) && (li.mOnDragListener != null || li.mOnReceiveContentListener != null);
14719     }
14720 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)14721     private boolean traverseAtGranularity(int granularity, boolean forward,
14722             boolean extendSelection) {
14723         CharSequence text = getIterableTextForAccessibility();
14724         if (text == null || text.length() == 0) {
14725             return false;
14726         }
14727         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
14728         if (iterator == null) {
14729             return false;
14730         }
14731         int current = getAccessibilitySelectionEnd();
14732         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14733             current = forward ? 0 : text.length();
14734         }
14735         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
14736         if (range == null) {
14737             return false;
14738         }
14739         final int segmentStart = range[0];
14740         final int segmentEnd = range[1];
14741         int selectionStart;
14742         int selectionEnd;
14743         if (extendSelection && isAccessibilitySelectionExtendable()) {
14744             prepareForExtendedAccessibilitySelection();
14745             selectionStart = getAccessibilitySelectionStart();
14746             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14747                 selectionStart = forward ? segmentStart : segmentEnd;
14748             }
14749             selectionEnd = forward ? segmentEnd : segmentStart;
14750         } else {
14751             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
14752         }
14753         setAccessibilitySelection(selectionStart, selectionEnd);
14754         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
14755                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
14756         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
14757         return true;
14758     }
14759 
14760     /**
14761      * Gets the text reported for accessibility purposes.
14762      *
14763      * @return The accessibility text.
14764      *
14765      * @hide
14766      */
14767     @UnsupportedAppUsage
getIterableTextForAccessibility()14768     public CharSequence getIterableTextForAccessibility() {
14769         return getContentDescription();
14770     }
14771 
14772     /**
14773      * Gets whether accessibility selection can be extended.
14774      *
14775      * @return If selection is extensible.
14776      *
14777      * @hide
14778      */
isAccessibilitySelectionExtendable()14779     public boolean isAccessibilitySelectionExtendable() {
14780         return false;
14781     }
14782 
14783     /**
14784      * Prepare for extended selection.
14785      * @hide
14786      */
prepareForExtendedAccessibilitySelection()14787     public void prepareForExtendedAccessibilitySelection() {
14788         return;
14789     }
14790 
14791     /**
14792      * @hide
14793      */
getAccessibilitySelectionStart()14794     public int getAccessibilitySelectionStart() {
14795         return mAccessibilityCursorPosition;
14796     }
14797 
14798     /**
14799      * @hide
14800      */
getAccessibilitySelectionEnd()14801     public int getAccessibilitySelectionEnd() {
14802         return getAccessibilitySelectionStart();
14803     }
14804 
14805     /**
14806      * @hide
14807      */
setAccessibilitySelection(int start, int end)14808     public void setAccessibilitySelection(int start, int end) {
14809         if (start ==  end && end == mAccessibilityCursorPosition) {
14810             return;
14811         }
14812         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
14813             mAccessibilityCursorPosition = start;
14814         } else {
14815             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
14816         }
14817         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
14818     }
14819 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)14820     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
14821             int fromIndex, int toIndex) {
14822         if (mParent == null) {
14823             return;
14824         }
14825         AccessibilityEvent event = AccessibilityEvent.obtain(
14826                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
14827         onInitializeAccessibilityEvent(event);
14828         onPopulateAccessibilityEvent(event);
14829         event.setFromIndex(fromIndex);
14830         event.setToIndex(toIndex);
14831         event.setAction(action);
14832         event.setMovementGranularity(granularity);
14833         mParent.requestSendAccessibilityEvent(this, event);
14834     }
14835 
14836     /**
14837      * @hide
14838      */
14839     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getIteratorForGranularity(int granularity)14840     public TextSegmentIterator getIteratorForGranularity(int granularity) {
14841         switch (granularity) {
14842             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
14843                 CharSequence text = getIterableTextForAccessibility();
14844                 if (text != null && text.length() > 0) {
14845                     CharacterTextSegmentIterator iterator =
14846                         CharacterTextSegmentIterator.getInstance(
14847                                 mContext.getResources().getConfiguration().locale);
14848                     iterator.initialize(text.toString());
14849                     return iterator;
14850                 }
14851             } break;
14852             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
14853                 CharSequence text = getIterableTextForAccessibility();
14854                 if (text != null && text.length() > 0) {
14855                     WordTextSegmentIterator iterator =
14856                         WordTextSegmentIterator.getInstance(
14857                                 mContext.getResources().getConfiguration().locale);
14858                     iterator.initialize(text.toString());
14859                     return iterator;
14860                 }
14861             } break;
14862             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
14863                 CharSequence text = getIterableTextForAccessibility();
14864                 if (text != null && text.length() > 0) {
14865                     ParagraphTextSegmentIterator iterator =
14866                         ParagraphTextSegmentIterator.getInstance();
14867                     iterator.initialize(text.toString());
14868                     return iterator;
14869                 }
14870             } break;
14871         }
14872         return null;
14873     }
14874 
14875     /**
14876      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
14877      * and {@link #onFinishTemporaryDetach()}.
14878      *
14879      * <p>This method always returns {@code true} when called directly or indirectly from
14880      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
14881      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
14882      * <ul>
14883      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
14884      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
14885      * </ul>
14886      * </p>
14887      *
14888      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
14889      * and {@link #onFinishTemporaryDetach()}.
14890      */
isTemporarilyDetached()14891     public final boolean isTemporarilyDetached() {
14892         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
14893     }
14894 
14895     /**
14896      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
14897      * a container View.
14898      */
14899     @CallSuper
dispatchStartTemporaryDetach()14900     public void dispatchStartTemporaryDetach() {
14901         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
14902         notifyEnterOrExitForAutoFillIfNeeded(false);
14903         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
14904         onStartTemporaryDetach();
14905     }
14906 
14907     /**
14908      * This is called when a container is going to temporarily detach a child, with
14909      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
14910      * It will either be followed by {@link #onFinishTemporaryDetach()} or
14911      * {@link #onDetachedFromWindow()} when the container is done.
14912      */
onStartTemporaryDetach()14913     public void onStartTemporaryDetach() {
14914         removeUnsetPressCallback();
14915         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
14916     }
14917 
14918     /**
14919      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
14920      * a container View.
14921      */
14922     @CallSuper
dispatchFinishTemporaryDetach()14923     public void dispatchFinishTemporaryDetach() {
14924         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
14925         onFinishTemporaryDetach();
14926         if (hasWindowFocus() && hasFocus()) {
14927             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14928         }
14929         notifyEnterOrExitForAutoFillIfNeeded(true);
14930         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
14931     }
14932 
14933     /**
14934      * Called after {@link #onStartTemporaryDetach} when the container is done
14935      * changing the view.
14936      */
onFinishTemporaryDetach()14937     public void onFinishTemporaryDetach() {
14938     }
14939 
14940     /**
14941      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
14942      * for this view's window.  Returns null if the view is not currently attached
14943      * to the window.  Normally you will not need to use this directly, but
14944      * just use the standard high-level event callbacks like
14945      * {@link #onKeyDown(int, KeyEvent)}.
14946      */
getKeyDispatcherState()14947     public KeyEvent.DispatcherState getKeyDispatcherState() {
14948         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
14949     }
14950 
14951     /**
14952      * Dispatch a key event before it is processed by any input method
14953      * associated with the view hierarchy.  This can be used to intercept
14954      * key events in special situations before the IME consumes them; a
14955      * typical example would be handling the BACK key to update the application's
14956      * UI instead of allowing the IME to see it and close itself.
14957      *
14958      * @param event The key event to be dispatched.
14959      * @return True if the event was handled, false otherwise.
14960      */
dispatchKeyEventPreIme(KeyEvent event)14961     public boolean dispatchKeyEventPreIme(KeyEvent event) {
14962         return onKeyPreIme(event.getKeyCode(), event);
14963     }
14964 
14965     /**
14966      * Dispatch a key event to the next view on the focus path. This path runs
14967      * from the top of the view tree down to the currently focused view. If this
14968      * view has focus, it will dispatch to itself. Otherwise it will dispatch
14969      * the next node down the focus path. This method also fires any key
14970      * listeners.
14971      *
14972      * @param event The key event to be dispatched.
14973      * @return True if the event was handled, false otherwise.
14974      */
dispatchKeyEvent(KeyEvent event)14975     public boolean dispatchKeyEvent(KeyEvent event) {
14976         if (mInputEventConsistencyVerifier != null) {
14977             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
14978         }
14979 
14980         // Give any attached key listener a first crack at the event.
14981         //noinspection SimplifiableIfStatement
14982         ListenerInfo li = mListenerInfo;
14983         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
14984                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
14985             return true;
14986         }
14987 
14988         if (event.dispatch(this, mAttachInfo != null
14989                 ? mAttachInfo.mKeyDispatchState : null, this)) {
14990             return true;
14991         }
14992 
14993         if (mInputEventConsistencyVerifier != null) {
14994             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14995         }
14996         return false;
14997     }
14998 
14999     /**
15000      * Dispatches a key shortcut event.
15001      *
15002      * @param event The key event to be dispatched.
15003      * @return True if the event was handled by the view, false otherwise.
15004      */
dispatchKeyShortcutEvent(KeyEvent event)15005     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
15006         return onKeyShortcut(event.getKeyCode(), event);
15007     }
15008 
15009     /**
15010      * Pass the touch screen motion event down to the target view, or this
15011      * view if it is the target.
15012      *
15013      * @param event The motion event to be dispatched.
15014      * @return True if the event was handled by the view, false otherwise.
15015      */
dispatchTouchEvent(MotionEvent event)15016     public boolean dispatchTouchEvent(MotionEvent event) {
15017         // If the event should be handled by accessibility focus first.
15018         if (event.isTargetAccessibilityFocus()) {
15019             // We don't have focus or no virtual descendant has it, do not handle the event.
15020             if (!isAccessibilityFocusedViewOrHost()) {
15021                 return false;
15022             }
15023             // We have focus and got the event, then use normal event dispatch.
15024             event.setTargetAccessibilityFocus(false);
15025         }
15026         boolean result = false;
15027 
15028         if (mInputEventConsistencyVerifier != null) {
15029             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
15030         }
15031 
15032         final int actionMasked = event.getActionMasked();
15033         if (actionMasked == MotionEvent.ACTION_DOWN) {
15034             // Defensive cleanup for new gesture
15035             stopNestedScroll();
15036         }
15037 
15038         if (onFilterTouchEventForSecurity(event)) {
15039             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
15040                 result = true;
15041             }
15042             //noinspection SimplifiableIfStatement
15043             ListenerInfo li = mListenerInfo;
15044             if (li != null && li.mOnTouchListener != null
15045                     && (mViewFlags & ENABLED_MASK) == ENABLED
15046                     && li.mOnTouchListener.onTouch(this, event)) {
15047                 result = true;
15048             }
15049 
15050             if (!result && onTouchEvent(event)) {
15051                 result = true;
15052             }
15053         }
15054 
15055         if (!result && mInputEventConsistencyVerifier != null) {
15056             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15057         }
15058 
15059         // Clean up after nested scrolls if this is the end of a gesture;
15060         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
15061         // of the gesture.
15062         if (actionMasked == MotionEvent.ACTION_UP ||
15063                 actionMasked == MotionEvent.ACTION_CANCEL ||
15064                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
15065             stopNestedScroll();
15066         }
15067 
15068         return result;
15069     }
15070 
isAccessibilityFocusedViewOrHost()15071     boolean isAccessibilityFocusedViewOrHost() {
15072         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
15073                 .getAccessibilityFocusedHost() == this);
15074     }
15075 
15076     /**
15077      * Returns whether this view can receive pointer events.
15078      *
15079      * @return {@code true} if this view can receive pointer events.
15080      * @hide
15081      */
canReceivePointerEvents()15082     protected boolean canReceivePointerEvents() {
15083         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
15084     }
15085 
15086     /**
15087      * Filter the touch event to apply security policies.
15088      *
15089      * @param event The motion event to be filtered.
15090      * @return True if the event should be dispatched, false if the event should be dropped.
15091      *
15092      * @see #getFilterTouchesWhenObscured
15093      */
onFilterTouchEventForSecurity(MotionEvent event)15094     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
15095         //noinspection RedundantIfStatement
15096         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
15097                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
15098             // Window is obscured, drop this touch.
15099             return false;
15100         }
15101         return true;
15102     }
15103 
15104     /**
15105      * Pass a trackball motion event down to the focused view.
15106      *
15107      * @param event The motion event to be dispatched.
15108      * @return True if the event was handled by the view, false otherwise.
15109      */
dispatchTrackballEvent(MotionEvent event)15110     public boolean dispatchTrackballEvent(MotionEvent event) {
15111         if (mInputEventConsistencyVerifier != null) {
15112             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
15113         }
15114 
15115         return onTrackballEvent(event);
15116     }
15117 
15118     /**
15119      * Pass a captured pointer event down to the focused view.
15120      *
15121      * @param event The motion event to be dispatched.
15122      * @return True if the event was handled by the view, false otherwise.
15123      */
dispatchCapturedPointerEvent(MotionEvent event)15124     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
15125         if (!hasPointerCapture()) {
15126             return false;
15127         }
15128         //noinspection SimplifiableIfStatement
15129         ListenerInfo li = mListenerInfo;
15130         if (li != null && li.mOnCapturedPointerListener != null
15131                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
15132             return true;
15133         }
15134         return onCapturedPointerEvent(event);
15135     }
15136 
15137     /**
15138      * Dispatch a generic motion event.
15139      * <p>
15140      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
15141      * are delivered to the view under the pointer.  All other generic motion events are
15142      * delivered to the focused view.  Hover events are handled specially and are delivered
15143      * to {@link #onHoverEvent(MotionEvent)}.
15144      * </p>
15145      *
15146      * @param event The motion event to be dispatched.
15147      * @return True if the event was handled by the view, false otherwise.
15148      */
dispatchGenericMotionEvent(MotionEvent event)15149     public boolean dispatchGenericMotionEvent(MotionEvent event) {
15150         if (mInputEventConsistencyVerifier != null) {
15151             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
15152         }
15153 
15154         final int source = event.getSource();
15155         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
15156             final int action = event.getAction();
15157             if (action == MotionEvent.ACTION_HOVER_ENTER
15158                     || action == MotionEvent.ACTION_HOVER_MOVE
15159                     || action == MotionEvent.ACTION_HOVER_EXIT) {
15160                 if (dispatchHoverEvent(event)) {
15161                     return true;
15162                 }
15163             } else if (dispatchGenericPointerEvent(event)) {
15164                 return true;
15165             }
15166         } else if (dispatchGenericFocusedEvent(event)) {
15167             return true;
15168         }
15169 
15170         if (dispatchGenericMotionEventInternal(event)) {
15171             return true;
15172         }
15173 
15174         if (mInputEventConsistencyVerifier != null) {
15175             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15176         }
15177         return false;
15178     }
15179 
dispatchGenericMotionEventInternal(MotionEvent event)15180     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
15181         //noinspection SimplifiableIfStatement
15182         ListenerInfo li = mListenerInfo;
15183         if (li != null && li.mOnGenericMotionListener != null
15184                 && (mViewFlags & ENABLED_MASK) == ENABLED
15185                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
15186             return true;
15187         }
15188 
15189         if (onGenericMotionEvent(event)) {
15190             return true;
15191         }
15192 
15193         final int actionButton = event.getActionButton();
15194         switch (event.getActionMasked()) {
15195             case MotionEvent.ACTION_BUTTON_PRESS:
15196                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
15197                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
15198                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
15199                     if (performContextClick(event.getX(), event.getY())) {
15200                         mInContextButtonPress = true;
15201                         setPressed(true, event.getX(), event.getY());
15202                         removeTapCallback();
15203                         removeLongPressCallback();
15204                         return true;
15205                     }
15206                 }
15207                 break;
15208 
15209             case MotionEvent.ACTION_BUTTON_RELEASE:
15210                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
15211                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
15212                     mInContextButtonPress = false;
15213                     mIgnoreNextUpEvent = true;
15214                 }
15215                 break;
15216         }
15217 
15218         if (mInputEventConsistencyVerifier != null) {
15219             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15220         }
15221         return false;
15222     }
15223 
15224     /**
15225      * Dispatch a hover event.
15226      * <p>
15227      * Do not call this method directly.
15228      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
15229      * </p>
15230      *
15231      * @param event The motion event to be dispatched.
15232      * @return True if the event was handled by the view, false otherwise.
15233      */
dispatchHoverEvent(MotionEvent event)15234     protected boolean dispatchHoverEvent(MotionEvent event) {
15235         ListenerInfo li = mListenerInfo;
15236         //noinspection SimplifiableIfStatement
15237         if (li != null && li.mOnHoverListener != null
15238                 && (mViewFlags & ENABLED_MASK) == ENABLED
15239                 && li.mOnHoverListener.onHover(this, event)) {
15240             return true;
15241         }
15242 
15243         return onHoverEvent(event);
15244     }
15245 
15246     /**
15247      * Returns true if the view has a child to which it has recently sent
15248      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
15249      * it does not have a hovered child, then it must be the innermost hovered view.
15250      * @hide
15251      */
hasHoveredChild()15252     protected boolean hasHoveredChild() {
15253         return false;
15254     }
15255 
15256     /**
15257      * Returns true if the given point, in local coordinates, is inside the hovered child.
15258      *
15259      * @hide
15260      */
pointInHoveredChild(MotionEvent event)15261     protected boolean pointInHoveredChild(MotionEvent event) {
15262         return false;
15263     }
15264 
15265     /**
15266      * Dispatch a generic motion event to the view under the first pointer.
15267      * <p>
15268      * Do not call this method directly.
15269      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
15270      * </p>
15271      *
15272      * @param event The motion event to be dispatched.
15273      * @return True if the event was handled by the view, false otherwise.
15274      */
dispatchGenericPointerEvent(MotionEvent event)15275     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
15276         return false;
15277     }
15278 
15279     /**
15280      * Dispatch a generic motion event to the currently focused view.
15281      * <p>
15282      * Do not call this method directly.
15283      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
15284      * </p>
15285      *
15286      * @param event The motion event to be dispatched.
15287      * @return True if the event was handled by the view, false otherwise.
15288      */
dispatchGenericFocusedEvent(MotionEvent event)15289     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
15290         return false;
15291     }
15292 
15293     /**
15294      * Dispatch a pointer event.
15295      * <p>
15296      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
15297      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
15298      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
15299      * and should not be expected to handle other pointing device features.
15300      * </p>
15301      *
15302      * @param event The motion event to be dispatched.
15303      * @return True if the event was handled by the view, false otherwise.
15304      * @hide
15305      */
15306     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchPointerEvent(MotionEvent event)15307     public final boolean dispatchPointerEvent(MotionEvent event) {
15308         if (event.isTouchEvent()) {
15309             return dispatchTouchEvent(event);
15310         } else {
15311             return dispatchGenericMotionEvent(event);
15312         }
15313     }
15314 
15315     /**
15316      * Called when the window containing this view gains or loses window focus.
15317      * ViewGroups should override to route to their children.
15318      *
15319      * @param hasFocus True if the window containing this view now has focus,
15320      *        false otherwise.
15321      */
dispatchWindowFocusChanged(boolean hasFocus)15322     public void dispatchWindowFocusChanged(boolean hasFocus) {
15323         onWindowFocusChanged(hasFocus);
15324     }
15325 
15326     /**
15327      * Called when the window containing this view gains or loses focus.  Note
15328      * that this is separate from view focus: to receive key events, both
15329      * your view and its window must have focus.  If a window is displayed
15330      * on top of yours that takes input focus, then your own window will lose
15331      * focus but the view focus will remain unchanged.
15332      *
15333      * @param hasWindowFocus True if the window containing this view now has
15334      *        focus, false otherwise.
15335      */
onWindowFocusChanged(boolean hasWindowFocus)15336     public void onWindowFocusChanged(boolean hasWindowFocus) {
15337         if (!hasWindowFocus) {
15338             if (isPressed()) {
15339                 setPressed(false);
15340             }
15341             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15342             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15343                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
15344             }
15345             removeLongPressCallback();
15346             removeTapCallback();
15347             onFocusLost();
15348         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15349             notifyFocusChangeToImeFocusController(true /* hasFocus */);
15350         }
15351 
15352         refreshDrawableState();
15353     }
15354 
15355     /**
15356      * Returns true if this view is in a window that currently has window focus.
15357      * Note that this is not the same as the view itself having focus.
15358      *
15359      * @return True if this view is in a window that currently has window focus.
15360      */
hasWindowFocus()15361     public boolean hasWindowFocus() {
15362         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
15363     }
15364 
15365     /**
15366      * @return {@code true} if this view is in a window that currently has IME focusable state.
15367      * @hide
15368      */
hasImeFocus()15369     public boolean hasImeFocus() {
15370         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
15371     }
15372 
15373     /**
15374      * Dispatch a view visibility change down the view hierarchy.
15375      * ViewGroups should override to route to their children.
15376      * @param changedView The view whose visibility changed. Could be 'this' or
15377      * an ancestor view.
15378      * @param visibility The new visibility of changedView: {@link #VISIBLE},
15379      * {@link #INVISIBLE} or {@link #GONE}.
15380      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)15381     protected void dispatchVisibilityChanged(@NonNull View changedView,
15382             @Visibility int visibility) {
15383         onVisibilityChanged(changedView, visibility);
15384     }
15385 
15386     /**
15387      * Called when the visibility of the view or an ancestor of the view has
15388      * changed.
15389      *
15390      * @param changedView The view whose visibility changed. May be
15391      *                    {@code this} or an ancestor view.
15392      * @param visibility The new visibility, one of {@link #VISIBLE},
15393      *                   {@link #INVISIBLE} or {@link #GONE}.
15394      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)15395     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
15396     }
15397 
15398     /**
15399      * Dispatch a hint about whether this view is displayed. For instance, when
15400      * a View moves out of the screen, it might receives a display hint indicating
15401      * the view is not displayed. Applications should not <em>rely</em> on this hint
15402      * as there is no guarantee that they will receive one.
15403      *
15404      * @param hint A hint about whether or not this view is displayed:
15405      * {@link #VISIBLE} or {@link #INVISIBLE}.
15406      */
dispatchDisplayHint(@isibility int hint)15407     public void dispatchDisplayHint(@Visibility int hint) {
15408         onDisplayHint(hint);
15409     }
15410 
15411     /**
15412      * Gives this view a hint about whether is displayed or not. For instance, when
15413      * a View moves out of the screen, it might receives a display hint indicating
15414      * the view is not displayed. Applications should not <em>rely</em> on this hint
15415      * as there is no guarantee that they will receive one.
15416      *
15417      * @param hint A hint about whether or not this view is displayed:
15418      * {@link #VISIBLE} or {@link #INVISIBLE}.
15419      */
onDisplayHint(@isibility int hint)15420     protected void onDisplayHint(@Visibility int hint) {
15421     }
15422 
15423     /**
15424      * Dispatch a window visibility change down the view hierarchy.
15425      * ViewGroups should override to route to their children.
15426      *
15427      * @param visibility The new visibility of the window.
15428      *
15429      * @see #onWindowVisibilityChanged(int)
15430      */
dispatchWindowVisibilityChanged(@isibility int visibility)15431     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
15432         onWindowVisibilityChanged(visibility);
15433     }
15434 
15435     /**
15436      * Called when the window containing has change its visibility
15437      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
15438      * that this tells you whether or not your window is being made visible
15439      * to the window manager; this does <em>not</em> tell you whether or not
15440      * your window is obscured by other windows on the screen, even if it
15441      * is itself visible.
15442      *
15443      * @param visibility The new visibility of the window.
15444      */
onWindowVisibilityChanged(@isibility int visibility)15445     protected void onWindowVisibilityChanged(@Visibility int visibility) {
15446         if (visibility == VISIBLE) {
15447             initialAwakenScrollBars();
15448         }
15449     }
15450 
15451     /**
15452      * @return true if this view and all ancestors are visible as of the last
15453      * {@link #onVisibilityAggregated(boolean)} call.
15454      *
15455      * @hide
15456      */
isAggregatedVisible()15457     public boolean isAggregatedVisible() {
15458         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
15459     }
15460 
15461     /**
15462      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
15463      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
15464      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
15465      *
15466      * @param isVisible true if this view's visibility to the user is uninterrupted by its
15467      *                  ancestors or by window visibility
15468      * @return true if this view is visible to the user, not counting clipping or overlapping
15469      */
dispatchVisibilityAggregated(boolean isVisible)15470     boolean dispatchVisibilityAggregated(boolean isVisible) {
15471         final boolean thisVisible = getVisibility() == VISIBLE;
15472         // If we're not visible but something is telling us we are, ignore it.
15473         if (thisVisible || !isVisible) {
15474             onVisibilityAggregated(isVisible);
15475         }
15476         return thisVisible && isVisible;
15477     }
15478 
15479     /**
15480      * Called when the user-visibility of this View is potentially affected by a change
15481      * to this view itself, an ancestor view or the window this view is attached to.
15482      *
15483      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
15484      *                  and this view's window is also visible
15485      */
15486     @CallSuper
onVisibilityAggregated(boolean isVisible)15487     public void onVisibilityAggregated(boolean isVisible) {
15488         // Update our internal visibility tracking so we can detect changes
15489         boolean oldVisible = isAggregatedVisible();
15490         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
15491                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
15492         if (isVisible && mAttachInfo != null) {
15493             initialAwakenScrollBars();
15494         }
15495 
15496         final Drawable dr = mBackground;
15497         if (dr != null && isVisible != dr.isVisible()) {
15498             dr.setVisible(isVisible, false);
15499         }
15500         final Drawable hl = mDefaultFocusHighlight;
15501         if (hl != null && isVisible != hl.isVisible()) {
15502             hl.setVisible(isVisible, false);
15503         }
15504         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
15505         if (fg != null && isVisible != fg.isVisible()) {
15506             fg.setVisible(isVisible, false);
15507         }
15508 
15509         if (isAutofillable()) {
15510             AutofillManager afm = getAutofillManager();
15511 
15512             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
15513                 if (mVisibilityChangeForAutofillHandler != null) {
15514                     mVisibilityChangeForAutofillHandler.removeMessages(0);
15515                 }
15516 
15517                 // If the view is in the background but still part of the hierarchy this is called
15518                 // with isVisible=false. Hence visibility==false requires further checks
15519                 if (isVisible) {
15520                     afm.notifyViewVisibilityChanged(this, true);
15521                 } else {
15522                     if (mVisibilityChangeForAutofillHandler == null) {
15523                         mVisibilityChangeForAutofillHandler =
15524                                 new VisibilityChangeForAutofillHandler(afm, this);
15525                     }
15526                     // Let current operation (e.g. removal of the view from the hierarchy)
15527                     // finish before checking state
15528                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
15529                 }
15530             }
15531         }
15532 
15533         if (isVisible != oldVisible) {
15534             if (isAccessibilityPane()) {
15535                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
15536                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
15537                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
15538             }
15539 
15540             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
15541 
15542             if (!getSystemGestureExclusionRects().isEmpty()) {
15543                 postUpdate(this::updateSystemGestureExclusionRects);
15544             }
15545 
15546             if (!collectPreferKeepClearRects().isEmpty()) {
15547                 postUpdate(this::updateKeepClearRects);
15548             }
15549         }
15550     }
15551 
15552     /**
15553      * Returns the current visibility of the window this view is attached to
15554      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
15555      *
15556      * @return Returns the current visibility of the view's window.
15557      */
15558     @Visibility
getWindowVisibility()15559     public int getWindowVisibility() {
15560         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
15561     }
15562 
15563     /**
15564      * Retrieve the overall visible display size in which the window this view is
15565      * attached to has been positioned in.  This takes into account screen
15566      * decorations above the window, for both cases where the window itself
15567      * is being position inside of them or the window is being placed under
15568      * then and covered insets are used for the window to position its content
15569      * inside.  In effect, this tells you the available area where content can
15570      * be placed and remain visible to users.
15571      *
15572      * @param outRect Filled in with the visible display frame.  If the view
15573      * is not attached to a window, this is simply the raw display size.
15574      */
getWindowVisibleDisplayFrame(Rect outRect)15575     public void getWindowVisibleDisplayFrame(Rect outRect) {
15576         if (mAttachInfo != null) {
15577             mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
15578             return;
15579         }
15580         // The view is not attached to a display so we don't have a context.
15581         // Make a best guess about the display size.
15582         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
15583         d.getRectSize(outRect);
15584     }
15585 
15586     /**
15587      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
15588      * is currently in without any insets.
15589      *
15590      * @hide
15591      */
15592     @UnsupportedAppUsage
15593     @TestApi
getWindowDisplayFrame(@onNull Rect outRect)15594     public void getWindowDisplayFrame(@NonNull Rect outRect) {
15595         if (mAttachInfo != null) {
15596             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
15597             return;
15598         }
15599         // The view is not attached to a display so we don't have a context.
15600         // Make a best guess about the display size.
15601         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
15602         d.getRectSize(outRect);
15603     }
15604 
15605     /**
15606      * Dispatch a notification about a resource configuration change down
15607      * the view hierarchy.
15608      * ViewGroups should override to route to their children.
15609      *
15610      * @param newConfig The new resource configuration.
15611      *
15612      * @see #onConfigurationChanged(android.content.res.Configuration)
15613      */
dispatchConfigurationChanged(Configuration newConfig)15614     public void dispatchConfigurationChanged(Configuration newConfig) {
15615         onConfigurationChanged(newConfig);
15616     }
15617 
15618     /**
15619      * Called when the current configuration of the resources being used
15620      * by the application have changed.  You can use this to decide when
15621      * to reload resources that can changed based on orientation and other
15622      * configuration characteristics.  You only need to use this if you are
15623      * not relying on the normal {@link android.app.Activity} mechanism of
15624      * recreating the activity instance upon a configuration change.
15625      *
15626      * @param newConfig The new resource configuration.
15627      */
onConfigurationChanged(Configuration newConfig)15628     protected void onConfigurationChanged(Configuration newConfig) {
15629     }
15630 
15631     /**
15632      * Private function to aggregate all per-view attributes in to the view
15633      * root.
15634      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)15635     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
15636         performCollectViewAttributes(attachInfo, visibility);
15637     }
15638 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)15639     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
15640         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
15641             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
15642                 attachInfo.mKeepScreenOn = true;
15643             }
15644             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
15645             ListenerInfo li = mListenerInfo;
15646             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15647                 attachInfo.mHasSystemUiListeners = true;
15648             }
15649         }
15650     }
15651 
needGlobalAttributesUpdate(boolean force)15652     void needGlobalAttributesUpdate(boolean force) {
15653         final AttachInfo ai = mAttachInfo;
15654         if (ai != null && !ai.mRecomputeGlobalAttributes) {
15655             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
15656                     || ai.mHasSystemUiListeners) {
15657                 ai.mRecomputeGlobalAttributes = true;
15658             }
15659         }
15660     }
15661 
15662     /**
15663      * Returns whether the device is currently in touch mode.  Touch mode is entered
15664      * once the user begins interacting with the device by touch, and affects various
15665      * things like whether focus is always visible to the user.
15666      *
15667      * @return Whether the device is in touch mode.
15668      */
15669     @ViewDebug.ExportedProperty
isInTouchMode()15670     public boolean isInTouchMode() {
15671         if (mAttachInfo != null) {
15672             return mAttachInfo.mInTouchMode;
15673         } else {
15674             return ViewRootImpl.isInTouchMode();
15675         }
15676     }
15677 
15678     /**
15679      * Returns the context the view is running in, through which it can
15680      * access the current theme, resources, etc.
15681      *
15682      * @return The view's Context.
15683      */
15684     @ViewDebug.CapturedViewProperty
15685     @UiContext
getContext()15686     public final Context getContext() {
15687         return mContext;
15688     }
15689 
15690     /**
15691      * Handle a key event before it is processed by any input method
15692      * associated with the view hierarchy.  This can be used to intercept
15693      * key events in special situations before the IME consumes them; a
15694      * typical example would be handling the BACK key to update the application's
15695      * UI instead of allowing the IME to see it and close itself.
15696      *
15697      * @param keyCode The value in event.getKeyCode().
15698      * @param event Description of the key event.
15699      * @return If you handled the event, return true. If you want to allow the
15700      *         event to be handled by the next receiver, return false.
15701      */
onKeyPreIme(int keyCode, KeyEvent event)15702     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
15703         return false;
15704     }
15705 
15706     /**
15707      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
15708      * KeyEvent.Callback.onKeyDown()}: perform press of the view
15709      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
15710      * is released, if the view is enabled and clickable.
15711      * <p>
15712      * Key presses in software keyboards will generally NOT trigger this
15713      * listener, although some may elect to do so in some situations. Do not
15714      * rely on this to catch software key presses.
15715      *
15716      * @param keyCode a key code that represents the button pressed, from
15717      *                {@link android.view.KeyEvent}
15718      * @param event the KeyEvent object that defines the button action
15719      */
onKeyDown(int keyCode, KeyEvent event)15720     public boolean onKeyDown(int keyCode, KeyEvent event) {
15721         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
15722             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15723                 return true;
15724             }
15725 
15726             if (event.getRepeatCount() == 0) {
15727                 // Long clickable items don't necessarily have to be clickable.
15728                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
15729                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
15730                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
15731                     // For the purposes of menu anchoring and drawable hotspots,
15732                     // key events are considered to be at the center of the view.
15733                     final float x = getWidth() / 2f;
15734                     final float y = getHeight() / 2f;
15735                     if (clickable) {
15736                         setPressed(true, x, y);
15737                     }
15738                     checkForLongClick(
15739                             ViewConfiguration.getLongPressTimeout(),
15740                             x,
15741                             y,
15742                             // This is not a touch gesture -- do not classify it as one.
15743                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
15744                     return true;
15745                 }
15746             }
15747         }
15748 
15749         return false;
15750     }
15751 
15752     /**
15753      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
15754      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
15755      * the event).
15756      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15757      * although some may elect to do so in some situations. Do not rely on this to
15758      * catch software key presses.
15759      */
onKeyLongPress(int keyCode, KeyEvent event)15760     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
15761         return false;
15762     }
15763 
15764     /**
15765      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
15766      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
15767      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
15768      * or {@link KeyEvent#KEYCODE_SPACE} is released.
15769      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15770      * although some may elect to do so in some situations. Do not rely on this to
15771      * catch software key presses.
15772      *
15773      * @param keyCode A key code that represents the button pressed, from
15774      *                {@link android.view.KeyEvent}.
15775      * @param event   The KeyEvent object that defines the button action.
15776      */
onKeyUp(int keyCode, KeyEvent event)15777     public boolean onKeyUp(int keyCode, KeyEvent event) {
15778         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
15779             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15780                 return true;
15781             }
15782             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
15783                 setPressed(false);
15784 
15785                 if (!mHasPerformedLongPress) {
15786                     // This is a tap, so remove the longpress check
15787                     removeLongPressCallback();
15788                     if (!event.isCanceled()) {
15789                         return performClickInternal();
15790                     }
15791                 }
15792             }
15793         }
15794         return false;
15795     }
15796 
15797     /**
15798      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
15799      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
15800      * the event).
15801      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15802      * although some may elect to do so in some situations. Do not rely on this to
15803      * catch software key presses.
15804      *
15805      * @param keyCode     A key code that represents the button pressed, from
15806      *                    {@link android.view.KeyEvent}.
15807      * @param repeatCount The number of times the action was made.
15808      * @param event       The KeyEvent object that defines the button action.
15809      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)15810     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
15811         return false;
15812     }
15813 
15814     /**
15815      * Called on the focused view when a key shortcut event is not handled.
15816      * Override this method to implement local key shortcuts for the View.
15817      * Key shortcuts can also be implemented by setting the
15818      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
15819      *
15820      * @param keyCode The value in event.getKeyCode().
15821      * @param event Description of the key event.
15822      * @return If you handled the event, return true. If you want to allow the
15823      *         event to be handled by the next receiver, return false.
15824      */
onKeyShortcut(int keyCode, KeyEvent event)15825     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
15826         return false;
15827     }
15828 
15829     /**
15830      * Check whether the called view is a text editor, in which case it
15831      * would make sense to automatically display a soft input window for
15832      * it.  Subclasses should override this if they implement
15833      * {@link #onCreateInputConnection(EditorInfo)} to return true if
15834      * a call on that method would return a non-null InputConnection, and
15835      * they are really a first-class editor that the user would normally
15836      * start typing on when the go into a window containing your view.
15837      *
15838      * <p>The default implementation always returns false.  This does
15839      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
15840      * will not be called or the user can not otherwise perform edits on your
15841      * view; it is just a hint to the system that this is not the primary
15842      * purpose of this view.
15843      *
15844      * @return Returns true if this view is a text editor, else false.
15845      */
onCheckIsTextEditor()15846     public boolean onCheckIsTextEditor() {
15847         return false;
15848     }
15849 
15850     /**
15851      * Create a new InputConnection for an InputMethod to interact
15852      * with the view.  The default implementation returns null, since it doesn't
15853      * support input methods.  You can override this to implement such support.
15854      * This is only needed for views that take focus and text input.
15855      *
15856      * <p>When implementing this, you probably also want to implement
15857      * {@link #onCheckIsTextEditor()} to indicate you will return a
15858      * non-null InputConnection.</p>
15859      *
15860      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
15861      * object correctly and in its entirety, so that the connected IME can rely
15862      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
15863      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
15864      * must be filled in with the correct cursor position for IMEs to work correctly
15865      * with your application.</p>
15866      *
15867      * @param outAttrs Fill in with attribute information about the connection.
15868      */
onCreateInputConnection(EditorInfo outAttrs)15869     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
15870         return null;
15871     }
15872 
15873     /**
15874      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
15875      * that the system has successfully initialized an {@link InputConnection} and it is ready for
15876      * use.
15877      *
15878      * <p>The default implementation does nothing, since a view doesn't support input methods by
15879      * default (see {@link #onCreateInputConnection}).
15880      *
15881      * @param inputConnection The {@link InputConnection} from {@link #onCreateInputConnection},
15882      * after it's been fully initialized by the system.
15883      * @param editorInfo The {@link EditorInfo} that was used to create the {@link InputConnection}.
15884      * @param handler The dedicated {@link Handler} on which IPC method calls from input methods
15885      * will be dispatched. This is the handler returned by {@link InputConnection#getHandler()}. If
15886      * that method returns null, this parameter will be null also.
15887      *
15888      * @hide
15889      */
onInputConnectionOpenedInternal(@onNull InputConnection inputConnection, @NonNull EditorInfo editorInfo, @Nullable Handler handler)15890     public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
15891             @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
15892 
15893     /**
15894      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
15895      * that the {@link InputConnection} has been closed.
15896      *
15897      * <p>The default implementation does nothing, since a view doesn't support input methods by
15898      * default (see {@link #onCreateInputConnection}).
15899      *
15900      * <p><strong>Note:</strong> This callback is not invoked if the view is already detached when
15901      * the {@link InputConnection} is closed or the connection is not valid and managed by
15902      * {@link com.android.server.inputmethod.InputMethodManagerService}.
15903      * TODO(b/170645312): Before un-hiding this API, handle the detached view scenario.
15904      *
15905      * @hide
15906      */
onInputConnectionClosedInternal()15907     public void onInputConnectionClosedInternal() {}
15908 
15909     /**
15910      * Called by the {@link android.view.inputmethod.InputMethodManager}
15911      * when a view who is not the current
15912      * input connection target is trying to make a call on the manager.  The
15913      * default implementation returns false; you can override this to return
15914      * true for certain views if you are performing InputConnection proxying
15915      * to them.
15916      * @param view The View that is making the InputMethodManager call.
15917      * @return Return true to allow the call, false to reject.
15918      */
checkInputConnectionProxy(View view)15919     public boolean checkInputConnectionProxy(View view) {
15920         return false;
15921     }
15922 
15923     /**
15924      * Show the context menu for this view. It is not safe to hold on to the
15925      * menu after returning from this method.
15926      *
15927      * You should normally not overload this method. Overload
15928      * {@link #onCreateContextMenu(ContextMenu)} or define an
15929      * {@link OnCreateContextMenuListener} to add items to the context menu.
15930      *
15931      * @param menu The context menu to populate
15932      */
createContextMenu(ContextMenu menu)15933     public void createContextMenu(ContextMenu menu) {
15934         ContextMenuInfo menuInfo = getContextMenuInfo();
15935 
15936         // Sets the current menu info so all items added to menu will have
15937         // my extra info set.
15938         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
15939 
15940         onCreateContextMenu(menu);
15941         ListenerInfo li = mListenerInfo;
15942         if (li != null && li.mOnCreateContextMenuListener != null) {
15943             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
15944         }
15945 
15946         // Clear the extra information so subsequent items that aren't mine don't
15947         // have my extra info.
15948         ((MenuBuilder)menu).setCurrentMenuInfo(null);
15949 
15950         if (mParent != null) {
15951             mParent.createContextMenu(menu);
15952         }
15953     }
15954 
15955     /**
15956      * Views should implement this if they have extra information to associate
15957      * with the context menu. The return result is supplied as a parameter to
15958      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
15959      * callback.
15960      *
15961      * @return Extra information about the item for which the context menu
15962      *         should be shown. This information will vary across different
15963      *         subclasses of View.
15964      */
getContextMenuInfo()15965     protected ContextMenuInfo getContextMenuInfo() {
15966         return null;
15967     }
15968 
15969     /**
15970      * Views should implement this if the view itself is going to add items to
15971      * the context menu.
15972      *
15973      * @param menu the context menu to populate
15974      */
onCreateContextMenu(ContextMenu menu)15975     protected void onCreateContextMenu(ContextMenu menu) {
15976     }
15977 
15978     /**
15979      * Implement this method to handle trackball motion events.  The
15980      * <em>relative</em> movement of the trackball since the last event
15981      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
15982      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
15983      * that a movement of 1 corresponds to the user pressing one DPAD key (so
15984      * they will often be fractional values, representing the more fine-grained
15985      * movement information available from a trackball).
15986      *
15987      * @param event The motion event.
15988      * @return True if the event was handled, false otherwise.
15989      */
onTrackballEvent(MotionEvent event)15990     public boolean onTrackballEvent(MotionEvent event) {
15991         return false;
15992     }
15993 
15994     /**
15995      * Implement this method to handle generic motion events.
15996      * <p>
15997      * Generic motion events describe joystick movements, mouse hovers, track pad
15998      * touches, scroll wheel movements and other input events.  The
15999      * {@link MotionEvent#getSource() source} of the motion event specifies
16000      * the class of input that was received.  Implementations of this method
16001      * must examine the bits in the source before processing the event.
16002      * The following code example shows how this is done.
16003      * </p><p>
16004      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
16005      * are delivered to the view under the pointer.  All other generic motion events are
16006      * delivered to the focused view.
16007      * </p>
16008      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
16009      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
16010      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
16011      *             // process the joystick movement...
16012      *             return true;
16013      *         }
16014      *     }
16015      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
16016      *         switch (event.getAction()) {
16017      *             case MotionEvent.ACTION_HOVER_MOVE:
16018      *                 // process the mouse hover movement...
16019      *                 return true;
16020      *             case MotionEvent.ACTION_SCROLL:
16021      *                 // process the scroll wheel movement...
16022      *                 return true;
16023      *         }
16024      *     }
16025      *     return super.onGenericMotionEvent(event);
16026      * }</pre>
16027      *
16028      * @param event The generic motion event being processed.
16029      * @return True if the event was handled, false otherwise.
16030      */
onGenericMotionEvent(MotionEvent event)16031     public boolean onGenericMotionEvent(MotionEvent event) {
16032         return false;
16033     }
16034 
16035     /**
16036      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
16037      * <p>
16038      * This method is dispatching hover events to the delegate target to support explore by touch.
16039      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
16040      * the delegate target according to the pointer and the touch area of the delegate while touch
16041      * exploration enabled.
16042      * </p>
16043      *
16044      * @param event The motion event dispatch to the delegate target.
16045      * @return True if the event was handled, false otherwise.
16046      *
16047      * @see #onHoverEvent
16048      */
dispatchTouchExplorationHoverEvent(MotionEvent event)16049     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
16050         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
16051         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
16052             return false;
16053         }
16054 
16055         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
16056         final int action = event.getActionMasked();
16057         boolean pointInDelegateRegion = false;
16058         boolean handled = false;
16059 
16060         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
16061         for (int i = 0; i < info.getRegionCount(); i++) {
16062             Region r = info.getRegionAt(i);
16063             if (r.contains((int) event.getX(), (int) event.getY())) {
16064                 pointInDelegateRegion = true;
16065             }
16066         }
16067 
16068         // Explore by touch should dispatch events to children under the pointer first if any
16069         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
16070         // hover events but receive accessibility focus, it should also not delegate to these
16071         // views when hovered.
16072         if (!oldHoveringTouchDelegate) {
16073             if ((action == MotionEvent.ACTION_HOVER_ENTER
16074                     || action == MotionEvent.ACTION_HOVER_MOVE)
16075                     && !pointInHoveredChild(event)
16076                     && pointInDelegateRegion) {
16077                 mHoveringTouchDelegate = true;
16078             }
16079         } else {
16080             if (action == MotionEvent.ACTION_HOVER_EXIT
16081                     || (action == MotionEvent.ACTION_HOVER_MOVE
16082                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
16083                 mHoveringTouchDelegate = false;
16084             }
16085         }
16086         switch (action) {
16087             case MotionEvent.ACTION_HOVER_MOVE:
16088                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
16089                     // Inside bounds, dispatch as is.
16090                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
16091                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
16092                     // Moving inbound, synthesize hover enter.
16093                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
16094                             ? event : MotionEvent.obtainNoHistory(event);
16095                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
16096                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
16097                     eventNoHistory.setAction(action);
16098                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
16099                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
16100                     // Moving outbound, synthesize hover exit.
16101                     final boolean hoverExitPending = event.isHoverExitPending();
16102                     event.setHoverExitPending(true);
16103                     mTouchDelegate.onTouchExplorationHoverEvent(event);
16104                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
16105                             ? event : MotionEvent.obtainNoHistory(event);
16106                     eventNoHistory.setHoverExitPending(hoverExitPending);
16107                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
16108                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
16109                 }  // else: outside bounds, do nothing.
16110                 break;
16111             case MotionEvent.ACTION_HOVER_ENTER:
16112                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
16113                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
16114                 }
16115                 break;
16116             case MotionEvent.ACTION_HOVER_EXIT:
16117                 if (oldHoveringTouchDelegate) {
16118                     mTouchDelegate.onTouchExplorationHoverEvent(event);
16119                 }
16120                 break;
16121         }
16122         return handled;
16123     }
16124 
16125     /**
16126      * Implement this method to handle hover events.
16127      * <p>
16128      * This method is called whenever a pointer is hovering into, over, or out of the
16129      * bounds of a view and the view is not currently being touched.
16130      * Hover events are represented as pointer events with action
16131      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
16132      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
16133      * </p>
16134      * <ul>
16135      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
16136      * when the pointer enters the bounds of the view.</li>
16137      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
16138      * when the pointer has already entered the bounds of the view and has moved.</li>
16139      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
16140      * when the pointer has exited the bounds of the view or when the pointer is
16141      * about to go down due to a button click, tap, or similar user action that
16142      * causes the view to be touched.</li>
16143      * </ul>
16144      * <p>
16145      * The view should implement this method to return true to indicate that it is
16146      * handling the hover event, such as by changing its drawable state.
16147      * </p><p>
16148      * The default implementation calls {@link #setHovered} to update the hovered state
16149      * of the view when a hover enter or hover exit event is received, if the view
16150      * is enabled and is clickable.  The default implementation also sends hover
16151      * accessibility events.
16152      * </p>
16153      *
16154      * @param event The motion event that describes the hover.
16155      * @return True if the view handled the hover event.
16156      *
16157      * @see #isHovered
16158      * @see #setHovered
16159      * @see #onHoverChanged
16160      */
onHoverEvent(MotionEvent event)16161     public boolean onHoverEvent(MotionEvent event) {
16162         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
16163             return true;
16164         }
16165 
16166         // The root view may receive hover (or touch) events that are outside the bounds of
16167         // the window.  This code ensures that we only send accessibility events for
16168         // hovers that are actually within the bounds of the root view.
16169         final int action = event.getActionMasked();
16170         if (!mSendingHoverAccessibilityEvents) {
16171             if ((action == MotionEvent.ACTION_HOVER_ENTER
16172                     || action == MotionEvent.ACTION_HOVER_MOVE)
16173                     && !hasHoveredChild()
16174                     && pointInView(event.getX(), event.getY())) {
16175                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
16176                 mSendingHoverAccessibilityEvents = true;
16177             }
16178         } else {
16179             if (action == MotionEvent.ACTION_HOVER_EXIT
16180                     || (action == MotionEvent.ACTION_HOVER_MOVE
16181                             && !pointInView(event.getX(), event.getY()))) {
16182                 mSendingHoverAccessibilityEvents = false;
16183                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
16184             }
16185         }
16186 
16187         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
16188                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
16189                 && isOnScrollbar(event.getX(), event.getY())) {
16190             awakenScrollBars();
16191         }
16192 
16193         // If we consider ourself hoverable, or if we we're already hovered,
16194         // handle changing state in response to ENTER and EXIT events.
16195         if (isHoverable() || isHovered()) {
16196             switch (action) {
16197                 case MotionEvent.ACTION_HOVER_ENTER:
16198                     setHovered(true);
16199                     break;
16200                 case MotionEvent.ACTION_HOVER_EXIT:
16201                     setHovered(false);
16202                     break;
16203             }
16204 
16205             // Dispatch the event to onGenericMotionEvent before returning true.
16206             // This is to provide compatibility with existing applications that
16207             // handled HOVER_MOVE events in onGenericMotionEvent and that would
16208             // break because of the new default handling for hoverable views
16209             // in onHoverEvent.
16210             // Note that onGenericMotionEvent will be called by default when
16211             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
16212             dispatchGenericMotionEventInternal(event);
16213             // The event was already handled by calling setHovered(), so always
16214             // return true.
16215             return true;
16216         }
16217 
16218         return false;
16219     }
16220 
16221     /**
16222      * Returns true if the view should handle {@link #onHoverEvent}
16223      * by calling {@link #setHovered} to change its hovered state.
16224      *
16225      * @return True if the view is hoverable.
16226      */
isHoverable()16227     private boolean isHoverable() {
16228         final int viewFlags = mViewFlags;
16229         if ((viewFlags & ENABLED_MASK) == DISABLED) {
16230             return false;
16231         }
16232 
16233         return (viewFlags & CLICKABLE) == CLICKABLE
16234                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
16235                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
16236     }
16237 
16238     /**
16239      * Returns true if the view is currently hovered.
16240      *
16241      * @return True if the view is currently hovered.
16242      *
16243      * @see #setHovered
16244      * @see #onHoverChanged
16245      */
16246     @ViewDebug.ExportedProperty
isHovered()16247     public boolean isHovered() {
16248         return (mPrivateFlags & PFLAG_HOVERED) != 0;
16249     }
16250 
16251     /**
16252      * Sets whether the view is currently hovered.
16253      * <p>
16254      * Calling this method also changes the drawable state of the view.  This
16255      * enables the view to react to hover by using different drawable resources
16256      * to change its appearance.
16257      * </p><p>
16258      * The {@link #onHoverChanged} method is called when the hovered state changes.
16259      * </p>
16260      *
16261      * @param hovered True if the view is hovered.
16262      *
16263      * @see #isHovered
16264      * @see #onHoverChanged
16265      */
setHovered(boolean hovered)16266     public void setHovered(boolean hovered) {
16267         if (hovered) {
16268             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
16269                 mPrivateFlags |= PFLAG_HOVERED;
16270                 refreshDrawableState();
16271                 onHoverChanged(true);
16272             }
16273         } else {
16274             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
16275                 mPrivateFlags &= ~PFLAG_HOVERED;
16276                 refreshDrawableState();
16277                 onHoverChanged(false);
16278             }
16279         }
16280     }
16281 
16282     /**
16283      * Implement this method to handle hover state changes.
16284      * <p>
16285      * This method is called whenever the hover state changes as a result of a
16286      * call to {@link #setHovered}.
16287      * </p>
16288      *
16289      * @param hovered The current hover state, as returned by {@link #isHovered}.
16290      *
16291      * @see #isHovered
16292      * @see #setHovered
16293      */
onHoverChanged(boolean hovered)16294     public void onHoverChanged(boolean hovered) {
16295     }
16296 
16297     /**
16298      * Handles scroll bar dragging by mouse input.
16299      *
16300      * @hide
16301      * @param event The motion event.
16302      *
16303      * @return true if the event was handled as a scroll bar dragging, false otherwise.
16304      */
handleScrollBarDragging(MotionEvent event)16305     protected boolean handleScrollBarDragging(MotionEvent event) {
16306         if (mScrollCache == null) {
16307             return false;
16308         }
16309         final float x = event.getX();
16310         final float y = event.getY();
16311         final int action = event.getAction();
16312         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
16313                 && action != MotionEvent.ACTION_DOWN)
16314                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
16315                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
16316             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
16317             return false;
16318         }
16319 
16320         switch (action) {
16321             case MotionEvent.ACTION_MOVE:
16322                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
16323                     return false;
16324                 }
16325                 if (mScrollCache.mScrollBarDraggingState
16326                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
16327                     final Rect bounds = mScrollCache.mScrollBarBounds;
16328                     getVerticalScrollBarBounds(bounds, null);
16329                     final int range = computeVerticalScrollRange();
16330                     final int offset = computeVerticalScrollOffset();
16331                     final int extent = computeVerticalScrollExtent();
16332 
16333                     final int thumbLength = ScrollBarUtils.getThumbLength(
16334                             bounds.height(), bounds.width(), extent, range);
16335                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
16336                             bounds.height(), thumbLength, extent, range, offset);
16337 
16338                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
16339                     final float maxThumbOffset = bounds.height() - thumbLength;
16340                     final float newThumbOffset =
16341                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
16342                     final int height = getHeight();
16343                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
16344                             && height > 0 && extent > 0) {
16345                         final int newY = Math.round((range - extent)
16346                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
16347                         if (newY != getScrollY()) {
16348                             mScrollCache.mScrollBarDraggingPos = y;
16349                             setScrollY(newY);
16350                         }
16351                     }
16352                     return true;
16353                 }
16354                 if (mScrollCache.mScrollBarDraggingState
16355                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
16356                     final Rect bounds = mScrollCache.mScrollBarBounds;
16357                     getHorizontalScrollBarBounds(bounds, null);
16358                     final int range = computeHorizontalScrollRange();
16359                     final int offset = computeHorizontalScrollOffset();
16360                     final int extent = computeHorizontalScrollExtent();
16361 
16362                     final int thumbLength = ScrollBarUtils.getThumbLength(
16363                             bounds.width(), bounds.height(), extent, range);
16364                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
16365                             bounds.width(), thumbLength, extent, range, offset);
16366 
16367                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
16368                     final float maxThumbOffset = bounds.width() - thumbLength;
16369                     final float newThumbOffset =
16370                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
16371                     final int width = getWidth();
16372                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
16373                             && width > 0 && extent > 0) {
16374                         final int newX = Math.round((range - extent)
16375                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
16376                         if (newX != getScrollX()) {
16377                             mScrollCache.mScrollBarDraggingPos = x;
16378                             setScrollX(newX);
16379                         }
16380                     }
16381                     return true;
16382                 }
16383             case MotionEvent.ACTION_DOWN:
16384                 if (mScrollCache.state == ScrollabilityCache.OFF) {
16385                     return false;
16386                 }
16387                 if (isOnVerticalScrollbarThumb(x, y)) {
16388                     mScrollCache.mScrollBarDraggingState =
16389                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
16390                     mScrollCache.mScrollBarDraggingPos = y;
16391                     return true;
16392                 }
16393                 if (isOnHorizontalScrollbarThumb(x, y)) {
16394                     mScrollCache.mScrollBarDraggingState =
16395                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
16396                     mScrollCache.mScrollBarDraggingPos = x;
16397                     return true;
16398                 }
16399         }
16400         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
16401         return false;
16402     }
16403 
16404     /**
16405      * Implement this method to handle touch screen motion events.
16406      * <p>
16407      * If this method is used to detect click actions, it is recommended that
16408      * the actions be performed by implementing and calling
16409      * {@link #performClick()}. This will ensure consistent system behavior,
16410      * including:
16411      * <ul>
16412      * <li>obeying click sound preferences
16413      * <li>dispatching OnClickListener calls
16414      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
16415      * accessibility features are enabled
16416      * </ul>
16417      *
16418      * @param event The motion event.
16419      * @return True if the event was handled, false otherwise.
16420      */
onTouchEvent(MotionEvent event)16421     public boolean onTouchEvent(MotionEvent event) {
16422         final float x = event.getX();
16423         final float y = event.getY();
16424         final int viewFlags = mViewFlags;
16425         final int action = event.getAction();
16426 
16427         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
16428                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
16429                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
16430 
16431         if ((viewFlags & ENABLED_MASK) == DISABLED
16432                 && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
16433             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
16434                 setPressed(false);
16435             }
16436             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16437             // A disabled view that is clickable still consumes the touch
16438             // events, it just doesn't respond to them.
16439             return clickable;
16440         }
16441         if (mTouchDelegate != null) {
16442             if (mTouchDelegate.onTouchEvent(event)) {
16443                 return true;
16444             }
16445         }
16446 
16447         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
16448             switch (action) {
16449                 case MotionEvent.ACTION_UP:
16450                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16451                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
16452                         handleTooltipUp();
16453                     }
16454                     if (!clickable) {
16455                         removeTapCallback();
16456                         removeLongPressCallback();
16457                         mInContextButtonPress = false;
16458                         mHasPerformedLongPress = false;
16459                         mIgnoreNextUpEvent = false;
16460                         break;
16461                     }
16462                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
16463                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
16464                         // take focus if we don't have it already and we should in
16465                         // touch mode.
16466                         boolean focusTaken = false;
16467                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
16468                             focusTaken = requestFocus();
16469                         }
16470 
16471                         if (prepressed) {
16472                             // The button is being released before we actually
16473                             // showed it as pressed.  Make it show the pressed
16474                             // state now (before scheduling the click) to ensure
16475                             // the user sees it.
16476                             setPressed(true, x, y);
16477                         }
16478 
16479                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
16480                             // This is a tap, so remove the longpress check
16481                             removeLongPressCallback();
16482 
16483                             // Only perform take click actions if we were in the pressed state
16484                             if (!focusTaken) {
16485                                 // Use a Runnable and post this rather than calling
16486                                 // performClick directly. This lets other visual state
16487                                 // of the view update before click actions start.
16488                                 if (mPerformClick == null) {
16489                                     mPerformClick = new PerformClick();
16490                                 }
16491                                 if (!post(mPerformClick)) {
16492                                     performClickInternal();
16493                                 }
16494                             }
16495                         }
16496 
16497                         if (mUnsetPressedState == null) {
16498                             mUnsetPressedState = new UnsetPressedState();
16499                         }
16500 
16501                         if (prepressed) {
16502                             postDelayed(mUnsetPressedState,
16503                                     ViewConfiguration.getPressedStateDuration());
16504                         } else if (!post(mUnsetPressedState)) {
16505                             // If the post failed, unpress right now
16506                             mUnsetPressedState.run();
16507                         }
16508 
16509                         removeTapCallback();
16510                     }
16511                     mIgnoreNextUpEvent = false;
16512                     break;
16513 
16514                 case MotionEvent.ACTION_DOWN:
16515                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
16516                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
16517                     }
16518                     mHasPerformedLongPress = false;
16519 
16520                     if (!clickable) {
16521                         checkForLongClick(
16522                                 ViewConfiguration.getLongPressTimeout(),
16523                                 x,
16524                                 y,
16525                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16526                         break;
16527                     }
16528 
16529                     if (performButtonActionOnTouchDown(event)) {
16530                         break;
16531                     }
16532 
16533                     // Walk up the hierarchy to determine if we're inside a scrolling container.
16534                     boolean isInScrollingContainer = isInScrollingContainer();
16535 
16536                     // For views inside a scrolling container, delay the pressed feedback for
16537                     // a short period in case this is a scroll.
16538                     if (isInScrollingContainer) {
16539                         mPrivateFlags |= PFLAG_PREPRESSED;
16540                         if (mPendingCheckForTap == null) {
16541                             mPendingCheckForTap = new CheckForTap();
16542                         }
16543                         mPendingCheckForTap.x = event.getX();
16544                         mPendingCheckForTap.y = event.getY();
16545                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
16546                     } else {
16547                         // Not inside a scrolling container, so show the feedback right away
16548                         setPressed(true, x, y);
16549                         checkForLongClick(
16550                                 ViewConfiguration.getLongPressTimeout(),
16551                                 x,
16552                                 y,
16553                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16554                     }
16555                     break;
16556 
16557                 case MotionEvent.ACTION_CANCEL:
16558                     if (clickable) {
16559                         setPressed(false);
16560                     }
16561                     removeTapCallback();
16562                     removeLongPressCallback();
16563                     mInContextButtonPress = false;
16564                     mHasPerformedLongPress = false;
16565                     mIgnoreNextUpEvent = false;
16566                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16567                     break;
16568 
16569                 case MotionEvent.ACTION_MOVE:
16570                     if (clickable) {
16571                         drawableHotspotChanged(x, y);
16572                     }
16573 
16574                     final int motionClassification = event.getClassification();
16575                     final boolean ambiguousGesture =
16576                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
16577                     int touchSlop = mTouchSlop;
16578                     if (ambiguousGesture && hasPendingLongPressCallback()) {
16579                         if (!pointInView(x, y, touchSlop)) {
16580                             // The default action here is to cancel long press. But instead, we
16581                             // just extend the timeout here, in case the classification
16582                             // stays ambiguous.
16583                             removeLongPressCallback();
16584                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
16585                                     * mAmbiguousGestureMultiplier);
16586                             // Subtract the time already spent
16587                             delay -= event.getEventTime() - event.getDownTime();
16588                             checkForLongClick(
16589                                     delay,
16590                                     x,
16591                                     y,
16592                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16593                         }
16594                         touchSlop *= mAmbiguousGestureMultiplier;
16595                     }
16596 
16597                     // Be lenient about moving outside of buttons
16598                     if (!pointInView(x, y, touchSlop)) {
16599                         // Outside button
16600                         // Remove any future long press/tap checks
16601                         removeTapCallback();
16602                         removeLongPressCallback();
16603                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
16604                             setPressed(false);
16605                         }
16606                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16607                     }
16608 
16609                     final boolean deepPress =
16610                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
16611                     if (deepPress && hasPendingLongPressCallback()) {
16612                         // process the long click action immediately
16613                         removeLongPressCallback();
16614                         checkForLongClick(
16615                                 0 /* send immediately */,
16616                                 x,
16617                                 y,
16618                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
16619                     }
16620 
16621                     break;
16622             }
16623 
16624             return true;
16625         }
16626 
16627         return false;
16628     }
16629 
16630     /**
16631      * @hide
16632      */
16633     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInScrollingContainer()16634     public boolean isInScrollingContainer() {
16635         ViewParent p = getParent();
16636         while (p != null && p instanceof ViewGroup) {
16637             if (((ViewGroup) p).shouldDelayChildPressedState()) {
16638                 return true;
16639             }
16640             p = p.getParent();
16641         }
16642         return false;
16643     }
16644 
16645     /**
16646      * Remove the longpress detection timer.
16647      */
removeLongPressCallback()16648     private void removeLongPressCallback() {
16649         if (mPendingCheckForLongPress != null) {
16650             removeCallbacks(mPendingCheckForLongPress);
16651         }
16652     }
16653 
16654     /**
16655      * Return true if the long press callback is scheduled to run sometime in the future.
16656      * Return false if there is no scheduled long press callback at the moment.
16657      */
hasPendingLongPressCallback()16658     private boolean hasPendingLongPressCallback() {
16659         if (mPendingCheckForLongPress == null) {
16660             return false;
16661         }
16662         final AttachInfo attachInfo = mAttachInfo;
16663         if (attachInfo == null) {
16664             return false;
16665         }
16666         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
16667     }
16668 
16669    /**
16670      * Remove the pending click action
16671      */
16672     @UnsupportedAppUsage
removePerformClickCallback()16673     private void removePerformClickCallback() {
16674         if (mPerformClick != null) {
16675             removeCallbacks(mPerformClick);
16676         }
16677     }
16678 
16679     /**
16680      * Remove the prepress detection timer.
16681      */
removeUnsetPressCallback()16682     private void removeUnsetPressCallback() {
16683         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
16684             setPressed(false);
16685             removeCallbacks(mUnsetPressedState);
16686         }
16687     }
16688 
16689     /**
16690      * Remove the tap detection timer.
16691      */
removeTapCallback()16692     private void removeTapCallback() {
16693         if (mPendingCheckForTap != null) {
16694             mPrivateFlags &= ~PFLAG_PREPRESSED;
16695             removeCallbacks(mPendingCheckForTap);
16696         }
16697     }
16698 
16699     /**
16700      * Cancels a pending long press.  Your subclass can use this if you
16701      * want the context menu to come up if the user presses and holds
16702      * at the same place, but you don't want it to come up if they press
16703      * and then move around enough to cause scrolling.
16704      */
cancelLongPress()16705     public void cancelLongPress() {
16706         removeLongPressCallback();
16707 
16708         /*
16709          * The prepressed state handled by the tap callback is a display
16710          * construct, but the tap callback will post a long press callback
16711          * less its own timeout. Remove it here.
16712          */
16713         removeTapCallback();
16714     }
16715 
16716     /**
16717      * Sets the TouchDelegate for this View.
16718      */
setTouchDelegate(TouchDelegate delegate)16719     public void setTouchDelegate(TouchDelegate delegate) {
16720         mTouchDelegate = delegate;
16721     }
16722 
16723     /**
16724      * Gets the TouchDelegate for this View.
16725      */
getTouchDelegate()16726     public TouchDelegate getTouchDelegate() {
16727         return mTouchDelegate;
16728     }
16729 
16730     /**
16731      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
16732      *
16733      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
16734      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
16735      * available. This method should only be called for touch events.
16736      *
16737      * <p class="note">This API is not intended for most applications. Buffered dispatch
16738      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
16739      * streams will not improve your input latency. Side effects include: increased latency,
16740      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
16741      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
16742      * you.</p>
16743      *
16744      * To receive unbuffered events for arbitrary input device source classes, use
16745      * {@link #requestUnbufferedDispatch(int)},
16746      *
16747      * @see View#requestUnbufferedDispatch(int)
16748      */
requestUnbufferedDispatch(MotionEvent event)16749     public final void requestUnbufferedDispatch(MotionEvent event) {
16750         final int action = event.getAction();
16751         if (mAttachInfo == null
16752                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
16753                 || !event.isTouchEvent()) {
16754             return;
16755         }
16756         mAttachInfo.mUnbufferedDispatchRequested = true;
16757     }
16758 
16759     /**
16760      * Request unbuffered dispatch of the given event source class to this view.
16761      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
16762      * automatically terminate, and allows the specification of arbitrary input source classes.
16763      *
16764      * @param source The combined input source class to request unbuffered dispatch for. All
16765      *               events coming from these source classes will not be buffered. Set to
16766      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
16767      *
16768      * @see View#requestUnbufferedDispatch(MotionEvent)
16769      */
requestUnbufferedDispatch(@nputSourceClass int source)16770     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
16771         if (mUnbufferedInputSource == source) {
16772             return;
16773         }
16774         mUnbufferedInputSource = source;
16775         if (mParent != null) {
16776             mParent.onDescendantUnbufferedRequested();
16777         }
16778     }
16779 
hasSize()16780     private boolean hasSize() {
16781         return (mBottom > mTop) && (mRight > mLeft);
16782     }
16783 
canTakeFocus()16784     private boolean canTakeFocus() {
16785         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
16786                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
16787                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
16788                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
16789     }
16790 
16791     /**
16792      * Set flags controlling behavior of this view.
16793      *
16794      * @param flags Constant indicating the value which should be set
16795      * @param mask Constant indicating the bit range that should be changed
16796      */
16797     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)16798     void setFlags(int flags, int mask) {
16799         final boolean accessibilityEnabled =
16800                 AccessibilityManager.getInstance(mContext).isEnabled();
16801         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
16802 
16803         int old = mViewFlags;
16804         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
16805 
16806         int changed = mViewFlags ^ old;
16807         if (changed == 0) {
16808             return;
16809         }
16810         int privateFlags = mPrivateFlags;
16811         boolean shouldNotifyFocusableAvailable = false;
16812 
16813         // If focusable is auto, update the FOCUSABLE bit.
16814         int focusableChangedByAuto = 0;
16815         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
16816                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
16817             // Heuristic only takes into account whether view is clickable.
16818             final int newFocus;
16819             if ((mViewFlags & CLICKABLE) != 0) {
16820                 newFocus = FOCUSABLE;
16821             } else {
16822                 newFocus = NOT_FOCUSABLE;
16823             }
16824             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
16825             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
16826             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
16827         }
16828 
16829         /* Check if the FOCUSABLE bit has changed */
16830         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
16831             if (((old & FOCUSABLE) == FOCUSABLE)
16832                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
16833                 /* Give up focus if we are no longer focusable */
16834                 clearFocus();
16835                 if (mParent instanceof ViewGroup) {
16836                     ((ViewGroup) mParent).clearFocusedInCluster();
16837                 }
16838             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
16839                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
16840                 /*
16841                  * Tell the view system that we are now available to take focus
16842                  * if no one else already has it.
16843                  */
16844                 if (mParent != null) {
16845                     ViewRootImpl viewRootImpl = getViewRootImpl();
16846                     if (!sAutoFocusableOffUIThreadWontNotifyParents
16847                             || focusableChangedByAuto == 0
16848                             || viewRootImpl == null
16849                             || viewRootImpl.mThread == Thread.currentThread()) {
16850                         shouldNotifyFocusableAvailable = canTakeFocus();
16851                     }
16852                 }
16853             }
16854         }
16855 
16856         final int newVisibility = flags & VISIBILITY_MASK;
16857         if (newVisibility == VISIBLE) {
16858             if ((changed & VISIBILITY_MASK) != 0) {
16859                 /*
16860                  * If this view is becoming visible, invalidate it in case it changed while
16861                  * it was not visible. Marking it drawn ensures that the invalidation will
16862                  * go through.
16863                  */
16864                 mPrivateFlags |= PFLAG_DRAWN;
16865                 invalidate(true);
16866 
16867                 needGlobalAttributesUpdate(true);
16868 
16869                 // a view becoming visible is worth notifying the parent about in case nothing has
16870                 // focus. Even if this specific view isn't focusable, it may contain something that
16871                 // is, so let the root view try to give this focus if nothing else does.
16872                 shouldNotifyFocusableAvailable = hasSize();
16873             }
16874         }
16875 
16876         if ((changed & ENABLED_MASK) != 0) {
16877             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
16878                 // a view becoming enabled should notify the parent as long as the view is also
16879                 // visible and the parent wasn't already notified by becoming visible during this
16880                 // setFlags invocation.
16881                 shouldNotifyFocusableAvailable = canTakeFocus();
16882             } else {
16883                 if (isFocused()) clearFocus();
16884             }
16885         }
16886 
16887         if (shouldNotifyFocusableAvailable && mParent != null) {
16888             mParent.focusableViewAvailable(this);
16889         }
16890 
16891         /* Check if the GONE bit has changed */
16892         if ((changed & GONE) != 0) {
16893             needGlobalAttributesUpdate(false);
16894             requestLayout();
16895 
16896             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
16897                 if (hasFocus()) {
16898                     clearFocus();
16899                     if (mParent instanceof ViewGroup) {
16900                         ((ViewGroup) mParent).clearFocusedInCluster();
16901                     }
16902                 }
16903                 clearAccessibilityFocus();
16904                 destroyDrawingCache();
16905                 if (mParent instanceof View) {
16906                     // GONE views noop invalidation, so invalidate the parent
16907                     ((View) mParent).invalidate(true);
16908                 }
16909                 // Mark the view drawn to ensure that it gets invalidated properly the next
16910                 // time it is visible and gets invalidated
16911                 mPrivateFlags |= PFLAG_DRAWN;
16912             }
16913             if (mAttachInfo != null) {
16914                 mAttachInfo.mViewVisibilityChanged = true;
16915             }
16916         }
16917 
16918         /* Check if the VISIBLE bit has changed */
16919         if ((changed & INVISIBLE) != 0) {
16920             needGlobalAttributesUpdate(false);
16921             /*
16922              * If this view is becoming invisible, set the DRAWN flag so that
16923              * the next invalidate() will not be skipped.
16924              */
16925             mPrivateFlags |= PFLAG_DRAWN;
16926 
16927             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
16928                 // root view becoming invisible shouldn't clear focus and accessibility focus
16929                 if (getRootView() != this) {
16930                     if (hasFocus()) {
16931                         clearFocus();
16932                         if (mParent instanceof ViewGroup) {
16933                             ((ViewGroup) mParent).clearFocusedInCluster();
16934                         }
16935                     }
16936                     clearAccessibilityFocus();
16937                 }
16938             }
16939             if (mAttachInfo != null) {
16940                 mAttachInfo.mViewVisibilityChanged = true;
16941             }
16942         }
16943 
16944         if ((changed & VISIBILITY_MASK) != 0) {
16945             // If the view is invisible, cleanup its display list to free up resources
16946             if (newVisibility != VISIBLE && mAttachInfo != null) {
16947                 cleanupDraw();
16948             }
16949 
16950             if (mParent instanceof ViewGroup) {
16951                 ViewGroup parent = (ViewGroup) mParent;
16952                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
16953                         newVisibility);
16954                 parent.invalidate(true);
16955             } else if (mParent != null) {
16956                 mParent.invalidateChild(this, null);
16957             }
16958 
16959             if (mAttachInfo != null) {
16960                 dispatchVisibilityChanged(this, newVisibility);
16961 
16962                 // Aggregated visibility changes are dispatched to attached views
16963                 // in visible windows where the parent is currently shown/drawn
16964                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
16965                 // discounting clipping or overlapping. This makes it a good place
16966                 // to change animation states.
16967                 if (mParent != null && getWindowVisibility() == VISIBLE &&
16968                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
16969                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
16970                 }
16971                 // If this view is invisible from visible, then sending the A11y event by its
16972                 // parent which is shown and has the accessibility important.
16973                 if ((old & VISIBILITY_MASK) == VISIBLE) {
16974                     notifySubtreeAccessibilityStateChangedByParentIfNeeded();
16975                 } else {
16976                     notifySubtreeAccessibilityStateChangedIfNeeded();
16977                 }
16978             }
16979         }
16980 
16981         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
16982             destroyDrawingCache();
16983         }
16984 
16985         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
16986             destroyDrawingCache();
16987             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16988             invalidateParentCaches();
16989         }
16990 
16991         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
16992             destroyDrawingCache();
16993             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16994         }
16995 
16996         if ((changed & DRAW_MASK) != 0) {
16997             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
16998                 if (mBackground != null
16999                         || mDefaultFocusHighlight != null
17000                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
17001                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17002                 } else {
17003                     mPrivateFlags |= PFLAG_SKIP_DRAW;
17004                 }
17005             } else {
17006                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17007             }
17008             requestLayout();
17009             invalidate(true);
17010         }
17011 
17012         if ((changed & KEEP_SCREEN_ON) != 0) {
17013             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17014                 mParent.recomputeViewAttributes(this);
17015             }
17016         }
17017 
17018         if (accessibilityEnabled) {
17019             // If we're an accessibility pane and the visibility changed, we already have sent
17020             // a state change, so we really don't need to report other changes.
17021             if (isAccessibilityPane()) {
17022                 changed &= ~VISIBILITY_MASK;
17023             }
17024             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
17025                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
17026                     || (changed & CONTEXT_CLICKABLE) != 0) {
17027                 if (oldIncludeForAccessibility != includeForAccessibility()) {
17028                     notifySubtreeAccessibilityStateChangedIfNeeded();
17029                 } else {
17030                     notifyViewAccessibilityStateChangedIfNeeded(
17031                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17032                 }
17033             } else if ((changed & ENABLED_MASK) != 0) {
17034                 notifyViewAccessibilityStateChangedIfNeeded(
17035                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17036             }
17037         }
17038     }
17039 
17040     /**
17041      * Change the view's z order in the tree, so it's on top of other sibling
17042      * views. This ordering change may affect layout, if the parent container
17043      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
17044      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
17045      * method should be followed by calls to {@link #requestLayout()} and
17046      * {@link View#invalidate()} on the view's parent to force the parent to redraw
17047      * with the new child ordering.
17048      *
17049      * @see ViewGroup#bringChildToFront(View)
17050      */
bringToFront()17051     public void bringToFront() {
17052         if (mParent != null) {
17053             mParent.bringChildToFront(this);
17054         }
17055     }
17056 
17057     /**
17058      * This is called in response to an internal scroll in this view (i.e., the
17059      * view scrolled its own contents). This is typically as a result of
17060      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
17061      * called.
17062      *
17063      * @param l Current horizontal scroll origin.
17064      * @param t Current vertical scroll origin.
17065      * @param oldl Previous horizontal scroll origin.
17066      * @param oldt Previous vertical scroll origin.
17067      */
onScrollChanged(int l, int t, int oldl, int oldt)17068     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
17069         notifySubtreeAccessibilityStateChangedIfNeeded();
17070         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
17071 
17072         mBackgroundSizeChanged = true;
17073         mDefaultFocusHighlightSizeChanged = true;
17074         if (mForegroundInfo != null) {
17075             mForegroundInfo.mBoundsChanged = true;
17076         }
17077 
17078         final AttachInfo ai = mAttachInfo;
17079         if (ai != null) {
17080             ai.mViewScrollChanged = true;
17081         }
17082 
17083         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
17084             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
17085         }
17086     }
17087 
17088     /**
17089      * Interface definition for a callback to be invoked when the scroll
17090      * X or Y positions of a view change.
17091      * <p>
17092      * <b>Note:</b> Some views handle scrolling independently from View and may
17093      * have their own separate listeners for scroll-type events. For example,
17094      * {@link android.widget.ListView ListView} allows clients to register an
17095      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
17096      * to listen for changes in list scroll position.
17097      *
17098      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
17099      */
17100     public interface OnScrollChangeListener {
17101         /**
17102          * Called when the scroll position of a view changes.
17103          *
17104          * @param v The view whose scroll position has changed.
17105          * @param scrollX Current horizontal scroll origin.
17106          * @param scrollY Current vertical scroll origin.
17107          * @param oldScrollX Previous horizontal scroll origin.
17108          * @param oldScrollY Previous vertical scroll origin.
17109          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)17110         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
17111     }
17112 
17113     /**
17114      * Interface definition for a callback to be invoked when the layout bounds of a view
17115      * changes due to layout processing.
17116      */
17117     public interface OnLayoutChangeListener {
17118         /**
17119          * Called when the layout bounds of a view changes due to layout processing.
17120          *
17121          * @param v The view whose bounds have changed.
17122          * @param left The new value of the view's left property.
17123          * @param top The new value of the view's top property.
17124          * @param right The new value of the view's right property.
17125          * @param bottom The new value of the view's bottom property.
17126          * @param oldLeft The previous value of the view's left property.
17127          * @param oldTop The previous value of the view's top property.
17128          * @param oldRight The previous value of the view's right property.
17129          * @param oldBottom The previous value of the view's bottom property.
17130          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)17131         void onLayoutChange(View v, int left, int top, int right, int bottom,
17132             int oldLeft, int oldTop, int oldRight, int oldBottom);
17133     }
17134 
17135     /**
17136      * This is called during layout when the size of this view has changed. If
17137      * you were just added to the view hierarchy, you're called with the old
17138      * values of 0.
17139      *
17140      * @param w Current width of this view.
17141      * @param h Current height of this view.
17142      * @param oldw Old width of this view.
17143      * @param oldh Old height of this view.
17144      */
onSizeChanged(int w, int h, int oldw, int oldh)17145     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
17146     }
17147 
17148     /**
17149      * Called by draw to draw the child views. This may be overridden
17150      * by derived classes to gain control just before its children are drawn
17151      * (but after its own view has been drawn).
17152      * @param canvas the canvas on which to draw the view
17153      */
dispatchDraw(Canvas canvas)17154     protected void dispatchDraw(Canvas canvas) {
17155 
17156     }
17157 
17158     /**
17159      * Gets the parent of this view. Note that the parent is a
17160      * ViewParent and not necessarily a View.
17161      *
17162      * @return Parent of this view.
17163      */
getParent()17164     public final ViewParent getParent() {
17165         return mParent;
17166     }
17167 
17168     /**
17169      * Set the horizontal scrolled position of your view. This will cause a call to
17170      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17171      * invalidated.
17172      * @param value the x position to scroll to
17173      */
setScrollX(int value)17174     public void setScrollX(int value) {
17175         scrollTo(value, mScrollY);
17176     }
17177 
17178     /**
17179      * Set the vertical scrolled position of your view. This will cause a call to
17180      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17181      * invalidated.
17182      * @param value the y position to scroll to
17183      */
setScrollY(int value)17184     public void setScrollY(int value) {
17185         scrollTo(mScrollX, value);
17186     }
17187 
17188     /**
17189      * Return the scrolled left position of this view. This is the left edge of
17190      * the displayed part of your view. You do not need to draw any pixels
17191      * farther left, since those are outside of the frame of your view on
17192      * screen.
17193      *
17194      * @return The left edge of the displayed part of your view, in pixels.
17195      */
17196     @InspectableProperty
getScrollX()17197     public final int getScrollX() {
17198         return mScrollX;
17199     }
17200 
17201     /**
17202      * Return the scrolled top position of this view. This is the top edge of
17203      * the displayed part of your view. You do not need to draw any pixels above
17204      * it, since those are outside of the frame of your view on screen.
17205      *
17206      * @return The top edge of the displayed part of your view, in pixels.
17207      */
17208     @InspectableProperty
getScrollY()17209     public final int getScrollY() {
17210         return mScrollY;
17211     }
17212 
17213     /**
17214      * Return the width of your view.
17215      *
17216      * @return The width of your view, in pixels.
17217      */
17218     @ViewDebug.ExportedProperty(category = "layout")
getWidth()17219     public final int getWidth() {
17220         return mRight - mLeft;
17221     }
17222 
17223     /**
17224      * Return the height of your view.
17225      *
17226      * @return The height of your view, in pixels.
17227      */
17228     @ViewDebug.ExportedProperty(category = "layout")
getHeight()17229     public final int getHeight() {
17230         return mBottom - mTop;
17231     }
17232 
17233     /**
17234      * Return the visible drawing bounds of your view. Fills in the output
17235      * rectangle with the values from getScrollX(), getScrollY(),
17236      * getWidth(), and getHeight(). These bounds do not account for any
17237      * transformation properties currently set on the view, such as
17238      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
17239      *
17240      * @param outRect The (scrolled) drawing bounds of the view.
17241      */
getDrawingRect(Rect outRect)17242     public void getDrawingRect(Rect outRect) {
17243         outRect.left = mScrollX;
17244         outRect.top = mScrollY;
17245         outRect.right = mScrollX + (mRight - mLeft);
17246         outRect.bottom = mScrollY + (mBottom - mTop);
17247     }
17248 
17249     /**
17250      * Like {@link #getMeasuredWidthAndState()}, but only returns the
17251      * raw width component (that is the result is masked by
17252      * {@link #MEASURED_SIZE_MASK}).
17253      *
17254      * @return The raw measured width of this view.
17255      */
getMeasuredWidth()17256     public final int getMeasuredWidth() {
17257         return mMeasuredWidth & MEASURED_SIZE_MASK;
17258     }
17259 
17260     /**
17261      * Return the full width measurement information for this view as computed
17262      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
17263      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17264      * This should be used during measurement and layout calculations only. Use
17265      * {@link #getWidth()} to see how wide a view is after layout.
17266      *
17267      * @return The measured width of this view as a bit mask.
17268      */
17269     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
17270             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
17271                     name = "MEASURED_STATE_TOO_SMALL"),
17272     })
getMeasuredWidthAndState()17273     public final int getMeasuredWidthAndState() {
17274         return mMeasuredWidth;
17275     }
17276 
17277     /**
17278      * Like {@link #getMeasuredHeightAndState()}, but only returns the
17279      * raw height component (that is the result is masked by
17280      * {@link #MEASURED_SIZE_MASK}).
17281      *
17282      * @return The raw measured height of this view.
17283      */
getMeasuredHeight()17284     public final int getMeasuredHeight() {
17285         return mMeasuredHeight & MEASURED_SIZE_MASK;
17286     }
17287 
17288     /**
17289      * Return the full height measurement information for this view as computed
17290      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
17291      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17292      * This should be used during measurement and layout calculations only. Use
17293      * {@link #getHeight()} to see how high a view is after layout.
17294      *
17295      * @return The measured height of this view as a bit mask.
17296      */
17297     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
17298             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
17299                     name = "MEASURED_STATE_TOO_SMALL"),
17300     })
getMeasuredHeightAndState()17301     public final int getMeasuredHeightAndState() {
17302         return mMeasuredHeight;
17303     }
17304 
17305     /**
17306      * Return only the state bits of {@link #getMeasuredWidthAndState()}
17307      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
17308      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
17309      * and the height component is at the shifted bits
17310      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
17311      */
getMeasuredState()17312     public final int getMeasuredState() {
17313         return (mMeasuredWidth&MEASURED_STATE_MASK)
17314                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
17315                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
17316     }
17317 
17318     /**
17319      * The transform matrix of this view, which is calculated based on the current
17320      * rotation, scale, and pivot properties.
17321      *
17322      * @see #getRotation()
17323      * @see #getScaleX()
17324      * @see #getScaleY()
17325      * @see #getPivotX()
17326      * @see #getPivotY()
17327      * @return The current transform matrix for the view
17328      */
getMatrix()17329     public Matrix getMatrix() {
17330         ensureTransformationInfo();
17331         final Matrix matrix = mTransformationInfo.mMatrix;
17332         mRenderNode.getMatrix(matrix);
17333         return matrix;
17334     }
17335 
17336     /**
17337      * Returns true if the transform matrix is the identity matrix.
17338      * Recomputes the matrix if necessary.
17339      *
17340      * @return True if the transform matrix is the identity matrix, false otherwise.
17341      * @hide
17342      */
17343     @UnsupportedAppUsage
hasIdentityMatrix()17344     public final boolean hasIdentityMatrix() {
17345         return mRenderNode.hasIdentityMatrix();
17346     }
17347 
17348     @UnsupportedAppUsage
ensureTransformationInfo()17349     void ensureTransformationInfo() {
17350         if (mTransformationInfo == null) {
17351             mTransformationInfo = new TransformationInfo();
17352         }
17353     }
17354 
17355     /**
17356      * Utility method to retrieve the inverse of the current mMatrix property.
17357      * We cache the matrix to avoid recalculating it when transform properties
17358      * have not changed.
17359      *
17360      * @return The inverse of the current matrix of this view.
17361      * @hide
17362      */
17363     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getInverseMatrix()17364     public final Matrix getInverseMatrix() {
17365         ensureTransformationInfo();
17366         if (mTransformationInfo.mInverseMatrix == null) {
17367             mTransformationInfo.mInverseMatrix = new Matrix();
17368         }
17369         final Matrix matrix = mTransformationInfo.mInverseMatrix;
17370         mRenderNode.getInverseMatrix(matrix);
17371         return matrix;
17372     }
17373 
17374     /**
17375      * Gets the distance along the Z axis from the camera to this view.
17376      *
17377      * @see #setCameraDistance(float)
17378      *
17379      * @return The distance along the Z axis.
17380      */
getCameraDistance()17381     public float getCameraDistance() {
17382         final float dpi = mResources.getDisplayMetrics().densityDpi;
17383         return mRenderNode.getCameraDistance() * dpi;
17384     }
17385 
17386     /**
17387      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
17388      * views are drawn) from the camera to this view. The camera's distance
17389      * affects 3D transformations, for instance rotations around the X and Y
17390      * axis. If the rotationX or rotationY properties are changed and this view is
17391      * large (more than half the size of the screen), it is recommended to always
17392      * use a camera distance that's greater than the height (X axis rotation) or
17393      * the width (Y axis rotation) of this view.</p>
17394      *
17395      * <p>The distance of the camera from the view plane can have an affect on the
17396      * perspective distortion of the view when it is rotated around the x or y axis.
17397      * For example, a large distance will result in a large viewing angle, and there
17398      * will not be much perspective distortion of the view as it rotates. A short
17399      * distance may cause much more perspective distortion upon rotation, and can
17400      * also result in some drawing artifacts if the rotated view ends up partially
17401      * behind the camera (which is why the recommendation is to use a distance at
17402      * least as far as the size of the view, if the view is to be rotated.)</p>
17403      *
17404      * <p>The distance is expressed in "depth pixels." The default distance depends
17405      * on the screen density. For instance, on a medium density display, the
17406      * default distance is 1280. On a high density display, the default distance
17407      * is 1920.</p>
17408      *
17409      * <p>If you want to specify a distance that leads to visually consistent
17410      * results across various densities, use the following formula:</p>
17411      * <pre>
17412      * float scale = context.getResources().getDisplayMetrics().density;
17413      * view.setCameraDistance(distance * scale);
17414      * </pre>
17415      *
17416      * <p>The density scale factor of a high density display is 1.5,
17417      * and 1920 = 1280 * 1.5.</p>
17418      *
17419      * @param distance The distance in "depth pixels", if negative the opposite
17420      *        value is used
17421      *
17422      * @see #setRotationX(float)
17423      * @see #setRotationY(float)
17424      */
setCameraDistance(float distance)17425     public void setCameraDistance(float distance) {
17426         final float dpi = mResources.getDisplayMetrics().densityDpi;
17427 
17428         invalidateViewProperty(true, false);
17429         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
17430         invalidateViewProperty(false, false);
17431 
17432         invalidateParentIfNeededAndWasQuickRejected();
17433     }
17434 
17435     /**
17436      * The degrees that the view is rotated around the pivot point.
17437      *
17438      * @see #setRotation(float)
17439      * @see #getPivotX()
17440      * @see #getPivotY()
17441      *
17442      * @return The degrees of rotation.
17443      */
17444     @ViewDebug.ExportedProperty(category = "drawing")
17445     @InspectableProperty
getRotation()17446     public float getRotation() {
17447         return mRenderNode.getRotationZ();
17448     }
17449 
17450     /**
17451      * Sets the degrees that the view is rotated around the pivot point. Increasing values
17452      * result in clockwise rotation.
17453      *
17454      * @param rotation The degrees of rotation.
17455      *
17456      * @see #getRotation()
17457      * @see #getPivotX()
17458      * @see #getPivotY()
17459      * @see #setRotationX(float)
17460      * @see #setRotationY(float)
17461      *
17462      * @attr ref android.R.styleable#View_rotation
17463      */
17464     @RemotableViewMethod
setRotation(float rotation)17465     public void setRotation(float rotation) {
17466         if (rotation != getRotation()) {
17467             // Double-invalidation is necessary to capture view's old and new areas
17468             invalidateViewProperty(true, false);
17469             mRenderNode.setRotationZ(rotation);
17470             invalidateViewProperty(false, true);
17471 
17472             invalidateParentIfNeededAndWasQuickRejected();
17473             notifySubtreeAccessibilityStateChangedIfNeeded();
17474         }
17475     }
17476 
17477     /**
17478      * The degrees that the view is rotated around the vertical axis through the pivot point.
17479      *
17480      * @see #getPivotX()
17481      * @see #getPivotY()
17482      * @see #setRotationY(float)
17483      *
17484      * @return The degrees of Y rotation.
17485      */
17486     @ViewDebug.ExportedProperty(category = "drawing")
17487     @InspectableProperty
getRotationY()17488     public float getRotationY() {
17489         return mRenderNode.getRotationY();
17490     }
17491 
17492     /**
17493      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
17494      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
17495      * down the y axis.
17496      *
17497      * When rotating large views, it is recommended to adjust the camera distance
17498      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
17499      *
17500      * @param rotationY The degrees of Y rotation.
17501      *
17502      * @see #getRotationY()
17503      * @see #getPivotX()
17504      * @see #getPivotY()
17505      * @see #setRotation(float)
17506      * @see #setRotationX(float)
17507      * @see #setCameraDistance(float)
17508      *
17509      * @attr ref android.R.styleable#View_rotationY
17510      */
17511     @RemotableViewMethod
setRotationY(float rotationY)17512     public void setRotationY(float rotationY) {
17513         if (rotationY != getRotationY()) {
17514             invalidateViewProperty(true, false);
17515             mRenderNode.setRotationY(rotationY);
17516             invalidateViewProperty(false, true);
17517 
17518             invalidateParentIfNeededAndWasQuickRejected();
17519             notifySubtreeAccessibilityStateChangedIfNeeded();
17520         }
17521     }
17522 
17523     /**
17524      * The degrees that the view is rotated around the horizontal axis through the pivot point.
17525      *
17526      * @see #getPivotX()
17527      * @see #getPivotY()
17528      * @see #setRotationX(float)
17529      *
17530      * @return The degrees of X rotation.
17531      */
17532     @ViewDebug.ExportedProperty(category = "drawing")
17533     @InspectableProperty
getRotationX()17534     public float getRotationX() {
17535         return mRenderNode.getRotationX();
17536     }
17537 
17538     /**
17539      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
17540      * Increasing values result in clockwise rotation from the viewpoint of looking down the
17541      * x axis.
17542      *
17543      * When rotating large views, it is recommended to adjust the camera distance
17544      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
17545      *
17546      * @param rotationX The degrees of X rotation.
17547      *
17548      * @see #getRotationX()
17549      * @see #getPivotX()
17550      * @see #getPivotY()
17551      * @see #setRotation(float)
17552      * @see #setRotationY(float)
17553      * @see #setCameraDistance(float)
17554      *
17555      * @attr ref android.R.styleable#View_rotationX
17556      */
17557     @RemotableViewMethod
setRotationX(float rotationX)17558     public void setRotationX(float rotationX) {
17559         if (rotationX != getRotationX()) {
17560             invalidateViewProperty(true, false);
17561             mRenderNode.setRotationX(rotationX);
17562             invalidateViewProperty(false, true);
17563 
17564             invalidateParentIfNeededAndWasQuickRejected();
17565             notifySubtreeAccessibilityStateChangedIfNeeded();
17566         }
17567     }
17568 
17569     /**
17570      * The amount that the view is scaled in x around the pivot point, as a proportion of
17571      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
17572      *
17573      * <p>By default, this is 1.0f.
17574      *
17575      * @see #getPivotX()
17576      * @see #getPivotY()
17577      * @return The scaling factor.
17578      */
17579     @ViewDebug.ExportedProperty(category = "drawing")
17580     @InspectableProperty
getScaleX()17581     public float getScaleX() {
17582         return mRenderNode.getScaleX();
17583     }
17584 
17585     /**
17586      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
17587      * the view's unscaled width. A value of 1 means that no scaling is applied.
17588      *
17589      * @param scaleX The scaling factor.
17590      * @see #getPivotX()
17591      * @see #getPivotY()
17592      *
17593      * @attr ref android.R.styleable#View_scaleX
17594      */
17595     @RemotableViewMethod
setScaleX(float scaleX)17596     public void setScaleX(float scaleX) {
17597         if (scaleX != getScaleX()) {
17598             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
17599             invalidateViewProperty(true, false);
17600             mRenderNode.setScaleX(scaleX);
17601             invalidateViewProperty(false, true);
17602 
17603             invalidateParentIfNeededAndWasQuickRejected();
17604             notifySubtreeAccessibilityStateChangedIfNeeded();
17605         }
17606     }
17607 
17608     /**
17609      * The amount that the view is scaled in y around the pivot point, as a proportion of
17610      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
17611      *
17612      * <p>By default, this is 1.0f.
17613      *
17614      * @see #getPivotX()
17615      * @see #getPivotY()
17616      * @return The scaling factor.
17617      */
17618     @ViewDebug.ExportedProperty(category = "drawing")
17619     @InspectableProperty
getScaleY()17620     public float getScaleY() {
17621         return mRenderNode.getScaleY();
17622     }
17623 
17624     /**
17625      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
17626      * the view's unscaled width. A value of 1 means that no scaling is applied.
17627      *
17628      * @param scaleY The scaling factor.
17629      * @see #getPivotX()
17630      * @see #getPivotY()
17631      *
17632      * @attr ref android.R.styleable#View_scaleY
17633      */
17634     @RemotableViewMethod
setScaleY(float scaleY)17635     public void setScaleY(float scaleY) {
17636         if (scaleY != getScaleY()) {
17637             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
17638             invalidateViewProperty(true, false);
17639             mRenderNode.setScaleY(scaleY);
17640             invalidateViewProperty(false, true);
17641 
17642             invalidateParentIfNeededAndWasQuickRejected();
17643             notifySubtreeAccessibilityStateChangedIfNeeded();
17644         }
17645     }
17646 
17647     /**
17648      * The x location of the point around which the view is {@link #setRotation(float) rotated}
17649      * and {@link #setScaleX(float) scaled}.
17650      *
17651      * @see #getRotation()
17652      * @see #getScaleX()
17653      * @see #getScaleY()
17654      * @see #getPivotY()
17655      * @return The x location of the pivot point.
17656      *
17657      * @attr ref android.R.styleable#View_transformPivotX
17658      */
17659     @ViewDebug.ExportedProperty(category = "drawing")
17660     @InspectableProperty(name = "transformPivotX")
getPivotX()17661     public float getPivotX() {
17662         return mRenderNode.getPivotX();
17663     }
17664 
17665     /**
17666      * Sets the x location of the point around which the view is
17667      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
17668      * By default, the pivot point is centered on the object.
17669      * Setting this property disables this behavior and causes the view to use only the
17670      * explicitly set pivotX and pivotY values.
17671      *
17672      * @param pivotX The x location of the pivot point.
17673      * @see #getRotation()
17674      * @see #getScaleX()
17675      * @see #getScaleY()
17676      * @see #getPivotY()
17677      *
17678      * @attr ref android.R.styleable#View_transformPivotX
17679      */
17680     @RemotableViewMethod
setPivotX(float pivotX)17681     public void setPivotX(float pivotX) {
17682         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
17683             invalidateViewProperty(true, false);
17684             mRenderNode.setPivotX(pivotX);
17685             invalidateViewProperty(false, true);
17686 
17687             invalidateParentIfNeededAndWasQuickRejected();
17688         }
17689     }
17690 
17691     /**
17692      * The y location of the point around which the view is {@link #setRotation(float) rotated}
17693      * and {@link #setScaleY(float) scaled}.
17694      *
17695      * @see #getRotation()
17696      * @see #getScaleX()
17697      * @see #getScaleY()
17698      * @see #getPivotY()
17699      * @return The y location of the pivot point.
17700      *
17701      * @attr ref android.R.styleable#View_transformPivotY
17702      */
17703     @ViewDebug.ExportedProperty(category = "drawing")
17704     @InspectableProperty(name = "transformPivotY")
getPivotY()17705     public float getPivotY() {
17706         return mRenderNode.getPivotY();
17707     }
17708 
17709     /**
17710      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
17711      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
17712      * Setting this property disables this behavior and causes the view to use only the
17713      * explicitly set pivotX and pivotY values.
17714      *
17715      * @param pivotY The y location of the pivot point.
17716      * @see #getRotation()
17717      * @see #getScaleX()
17718      * @see #getScaleY()
17719      * @see #getPivotY()
17720      *
17721      * @attr ref android.R.styleable#View_transformPivotY
17722      */
17723     @RemotableViewMethod
setPivotY(float pivotY)17724     public void setPivotY(float pivotY) {
17725         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
17726             invalidateViewProperty(true, false);
17727             mRenderNode.setPivotY(pivotY);
17728             invalidateViewProperty(false, true);
17729 
17730             invalidateParentIfNeededAndWasQuickRejected();
17731         }
17732     }
17733 
17734     /**
17735      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
17736      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
17737      * of the view.
17738      *
17739      * @return True if a pivot has been set, false if the default pivot is being used
17740      */
isPivotSet()17741     public boolean isPivotSet() {
17742         return mRenderNode.isPivotExplicitlySet();
17743     }
17744 
17745     /**
17746      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
17747      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
17748      * and the pivot used for rotation will return to default of being centered on the view.
17749      */
resetPivot()17750     public void resetPivot() {
17751         if (mRenderNode.resetPivot()) {
17752             invalidateViewProperty(false, false);
17753         }
17754     }
17755 
17756     /**
17757      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
17758      * completely transparent and 1 means the view is completely opaque.
17759      *
17760      * <p>By default this is 1.0f.
17761      * @return The opacity of the view.
17762      */
17763     @ViewDebug.ExportedProperty(category = "drawing")
17764     @InspectableProperty
getAlpha()17765     public float getAlpha() {
17766         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
17767     }
17768 
17769     /**
17770      * Sets the behavior for overlapping rendering for this view (see {@link
17771      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
17772      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
17773      * providing the value which is then used internally. That is, when {@link
17774      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
17775      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
17776      * instead.
17777      *
17778      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
17779      * instead of that returned by {@link #hasOverlappingRendering()}.
17780      *
17781      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
17782      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)17783     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
17784         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
17785         if (hasOverlappingRendering) {
17786             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17787         } else {
17788             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17789         }
17790     }
17791 
17792     /**
17793      * Returns the value for overlapping rendering that is used internally. This is either
17794      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
17795      * the return value of {@link #hasOverlappingRendering()}, otherwise.
17796      *
17797      * @return The value for overlapping rendering being used internally.
17798      */
getHasOverlappingRendering()17799     public final boolean getHasOverlappingRendering() {
17800         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
17801                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
17802                 hasOverlappingRendering();
17803     }
17804 
17805     /**
17806      * Returns whether this View has content which overlaps.
17807      *
17808      * <p>This function, intended to be overridden by specific View types, is an optimization when
17809      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
17810      * an offscreen buffer and then composited into place, which can be expensive. If the view has
17811      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
17812      * directly. An example of overlapping rendering is a TextView with a background image, such as
17813      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
17814      * ImageView with only the foreground image. The default implementation returns true; subclasses
17815      * should override if they have cases which can be optimized.</p>
17816      *
17817      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
17818      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
17819      *
17820      * @return true if the content in this view might overlap, false otherwise.
17821      */
17822     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()17823     public boolean hasOverlappingRendering() {
17824         return true;
17825     }
17826 
17827     /**
17828      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
17829      * completely transparent and 1 means the view is completely opaque.
17830      *
17831      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
17832      * can have significant performance implications, especially for large views. It is best to use
17833      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
17834      *
17835      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
17836      * strongly recommended for performance reasons to either override
17837      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
17838      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
17839      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
17840      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
17841      * of rendering cost, even for simple or small views. Starting with
17842      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
17843      * applied to the view at the rendering level.</p>
17844      *
17845      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
17846      * responsible for applying the opacity itself.</p>
17847      *
17848      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
17849      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
17850      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
17851      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
17852      *
17853      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
17854      * value will clip a View to its bounds, unless the View returns <code>false</code> from
17855      * {@link #hasOverlappingRendering}.</p>
17856      *
17857      * @param alpha The opacity of the view.
17858      *
17859      * @see #hasOverlappingRendering()
17860      * @see #setLayerType(int, android.graphics.Paint)
17861      *
17862      * @attr ref android.R.styleable#View_alpha
17863      */
17864     @RemotableViewMethod
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)17865     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
17866         ensureTransformationInfo();
17867         if (mTransformationInfo.mAlpha != alpha) {
17868             setAlphaInternal(alpha);
17869             if (onSetAlpha((int) (alpha * 255))) {
17870                 mPrivateFlags |= PFLAG_ALPHA_SET;
17871                 // subclass is handling alpha - don't optimize rendering cache invalidation
17872                 invalidateParentCaches();
17873                 invalidate(true);
17874             } else {
17875                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17876                 invalidateViewProperty(true, false);
17877                 mRenderNode.setAlpha(getFinalAlpha());
17878             }
17879         }
17880     }
17881 
17882     /**
17883      * Faster version of setAlpha() which performs the same steps except there are
17884      * no calls to invalidate(). The caller of this function should perform proper invalidation
17885      * on the parent and this object. The return value indicates whether the subclass handles
17886      * alpha (the return value for onSetAlpha()).
17887      *
17888      * @param alpha The new value for the alpha property
17889      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
17890      *         the new value for the alpha property is different from the old value
17891      */
17892     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)17893     boolean setAlphaNoInvalidation(float alpha) {
17894         ensureTransformationInfo();
17895         if (mTransformationInfo.mAlpha != alpha) {
17896             setAlphaInternal(alpha);
17897             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
17898             if (subclassHandlesAlpha) {
17899                 mPrivateFlags |= PFLAG_ALPHA_SET;
17900                 return true;
17901             } else {
17902                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17903                 mRenderNode.setAlpha(getFinalAlpha());
17904             }
17905         }
17906         return false;
17907     }
17908 
setAlphaInternal(float alpha)17909     void setAlphaInternal(float alpha) {
17910         float oldAlpha = mTransformationInfo.mAlpha;
17911         mTransformationInfo.mAlpha = alpha;
17912         // Report visibility changes, which can affect children, to accessibility
17913         if ((alpha == 0) ^ (oldAlpha == 0)) {
17914             notifySubtreeAccessibilityStateChangedIfNeeded();
17915         }
17916     }
17917 
17918     /**
17919      * This property is intended only for use by the Fade transition, which animates it
17920      * to produce a visual translucency that does not side-effect (or get affected by)
17921      * the real alpha property. This value is composited with the other alpha value
17922      * (and the AlphaAnimation value, when that is present) to produce a final visual
17923      * translucency result, which is what is passed into the DisplayList.
17924      */
setTransitionAlpha(float alpha)17925     public void setTransitionAlpha(float alpha) {
17926         ensureTransformationInfo();
17927         if (mTransformationInfo.mTransitionAlpha != alpha) {
17928             mTransformationInfo.mTransitionAlpha = alpha;
17929             mPrivateFlags &= ~PFLAG_ALPHA_SET;
17930             invalidateViewProperty(true, false);
17931             mRenderNode.setAlpha(getFinalAlpha());
17932         }
17933     }
17934 
17935     /**
17936      * Calculates the visual alpha of this view, which is a combination of the actual
17937      * alpha value and the transitionAlpha value (if set).
17938      */
getFinalAlpha()17939     private float getFinalAlpha() {
17940         if (mTransformationInfo != null) {
17941             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
17942         }
17943         return 1;
17944     }
17945 
17946     /**
17947      * This property is intended only for use by the Fade transition, which animates
17948      * it to produce a visual translucency that does not side-effect (or get affected
17949      * by) the real alpha property. This value is composited with the other alpha
17950      * value (and the AlphaAnimation value, when that is present) to produce a final
17951      * visual translucency result, which is what is passed into the DisplayList.
17952      */
17953     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()17954     public float getTransitionAlpha() {
17955         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
17956     }
17957 
17958     /**
17959      * Sets whether or not to allow force dark to apply to this view.
17960      *
17961      * Setting this to false will disable the auto-dark feature on everything this view
17962      * draws, including any descendants.
17963      *
17964      * Setting this to true will allow this view to be automatically made dark, however
17965      * a value of 'true' will not override any 'false' value in its parent chain nor will
17966      * it prevent any 'false' in any of its children.
17967      *
17968      * The default behavior of force dark is also influenced by the Theme's
17969      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
17970      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
17971      *
17972      * @param allow Whether or not to allow force dark.
17973      */
setForceDarkAllowed(boolean allow)17974     public void setForceDarkAllowed(boolean allow) {
17975         if (mRenderNode.setForceDarkAllowed(allow)) {
17976             // Currently toggling force-dark requires a new display list push to apply
17977             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
17978             invalidate();
17979         }
17980     }
17981 
17982     /**
17983      * See {@link #setForceDarkAllowed(boolean)}
17984      *
17985      * @return true if force dark is allowed (default), false if it is disabled
17986      */
17987     @ViewDebug.ExportedProperty(category = "drawing")
17988     @InspectableProperty
isForceDarkAllowed()17989     public boolean isForceDarkAllowed() {
17990         return mRenderNode.isForceDarkAllowed();
17991     }
17992 
17993     /**
17994      * Top position of this view relative to its parent.
17995      *
17996      * @return The top of this view, in pixels.
17997      */
17998     @ViewDebug.CapturedViewProperty
getTop()17999     public final int getTop() {
18000         return mTop;
18001     }
18002 
18003     /**
18004      * Sets the top position of this view relative to its parent. This method is meant to be called
18005      * by the layout system and should not generally be called otherwise, because the property
18006      * may be changed at any time by the layout.
18007      *
18008      * @param top The top of this view, in pixels.
18009      */
setTop(int top)18010     public final void setTop(int top) {
18011         if (top != mTop) {
18012             final boolean matrixIsIdentity = hasIdentityMatrix();
18013             if (matrixIsIdentity) {
18014                 if (mAttachInfo != null) {
18015                     int minTop;
18016                     int yLoc;
18017                     if (top < mTop) {
18018                         minTop = top;
18019                         yLoc = top - mTop;
18020                     } else {
18021                         minTop = mTop;
18022                         yLoc = 0;
18023                     }
18024                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
18025                 }
18026             } else {
18027                 // Double-invalidation is necessary to capture view's old and new areas
18028                 invalidate(true);
18029             }
18030 
18031             int width = mRight - mLeft;
18032             int oldHeight = mBottom - mTop;
18033 
18034             mTop = top;
18035             mRenderNode.setTop(mTop);
18036 
18037             sizeChange(width, mBottom - mTop, width, oldHeight);
18038 
18039             if (!matrixIsIdentity) {
18040                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18041                 invalidate(true);
18042             }
18043             mBackgroundSizeChanged = true;
18044             mDefaultFocusHighlightSizeChanged = true;
18045             if (mForegroundInfo != null) {
18046                 mForegroundInfo.mBoundsChanged = true;
18047             }
18048             invalidateParentIfNeeded();
18049         }
18050     }
18051 
18052     /**
18053      * Bottom position of this view relative to its parent.
18054      *
18055      * @return The bottom of this view, in pixels.
18056      */
18057     @ViewDebug.CapturedViewProperty
getBottom()18058     public final int getBottom() {
18059         return mBottom;
18060     }
18061 
18062     /**
18063      * True if this view has changed since the last time being drawn.
18064      *
18065      * @return The dirty state of this view.
18066      */
isDirty()18067     public boolean isDirty() {
18068         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
18069     }
18070 
18071     /**
18072      * Sets the bottom position of this view relative to its parent. This method is meant to be
18073      * called by the layout system and should not generally be called otherwise, because the
18074      * property may be changed at any time by the layout.
18075      *
18076      * @param bottom The bottom of this view, in pixels.
18077      */
setBottom(int bottom)18078     public final void setBottom(int bottom) {
18079         if (bottom != mBottom) {
18080             final boolean matrixIsIdentity = hasIdentityMatrix();
18081             if (matrixIsIdentity) {
18082                 if (mAttachInfo != null) {
18083                     int maxBottom;
18084                     if (bottom < mBottom) {
18085                         maxBottom = mBottom;
18086                     } else {
18087                         maxBottom = bottom;
18088                     }
18089                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
18090                 }
18091             } else {
18092                 // Double-invalidation is necessary to capture view's old and new areas
18093                 invalidate(true);
18094             }
18095 
18096             int width = mRight - mLeft;
18097             int oldHeight = mBottom - mTop;
18098 
18099             mBottom = bottom;
18100             mRenderNode.setBottom(mBottom);
18101 
18102             sizeChange(width, mBottom - mTop, width, oldHeight);
18103 
18104             if (!matrixIsIdentity) {
18105                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18106                 invalidate(true);
18107             }
18108             mBackgroundSizeChanged = true;
18109             mDefaultFocusHighlightSizeChanged = true;
18110             if (mForegroundInfo != null) {
18111                 mForegroundInfo.mBoundsChanged = true;
18112             }
18113             invalidateParentIfNeeded();
18114         }
18115     }
18116 
18117     /**
18118      * Left position of this view relative to its parent.
18119      *
18120      * @return The left edge of this view, in pixels.
18121      */
18122     @ViewDebug.CapturedViewProperty
getLeft()18123     public final int getLeft() {
18124         return mLeft;
18125     }
18126 
18127     /**
18128      * Sets the left position of this view relative to its parent. This method is meant to be called
18129      * by the layout system and should not generally be called otherwise, because the property
18130      * may be changed at any time by the layout.
18131      *
18132      * @param left The left of this view, in pixels.
18133      */
setLeft(int left)18134     public final void setLeft(int left) {
18135         if (left != mLeft) {
18136             final boolean matrixIsIdentity = hasIdentityMatrix();
18137             if (matrixIsIdentity) {
18138                 if (mAttachInfo != null) {
18139                     int minLeft;
18140                     int xLoc;
18141                     if (left < mLeft) {
18142                         minLeft = left;
18143                         xLoc = left - mLeft;
18144                     } else {
18145                         minLeft = mLeft;
18146                         xLoc = 0;
18147                     }
18148                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
18149                 }
18150             } else {
18151                 // Double-invalidation is necessary to capture view's old and new areas
18152                 invalidate(true);
18153             }
18154 
18155             int oldWidth = mRight - mLeft;
18156             int height = mBottom - mTop;
18157 
18158             mLeft = left;
18159             mRenderNode.setLeft(left);
18160 
18161             sizeChange(mRight - mLeft, height, oldWidth, height);
18162 
18163             if (!matrixIsIdentity) {
18164                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18165                 invalidate(true);
18166             }
18167             mBackgroundSizeChanged = true;
18168             mDefaultFocusHighlightSizeChanged = true;
18169             if (mForegroundInfo != null) {
18170                 mForegroundInfo.mBoundsChanged = true;
18171             }
18172             invalidateParentIfNeeded();
18173         }
18174     }
18175 
18176     /**
18177      * Right position of this view relative to its parent.
18178      *
18179      * @return The right edge of this view, in pixels.
18180      */
18181     @ViewDebug.CapturedViewProperty
getRight()18182     public final int getRight() {
18183         return mRight;
18184     }
18185 
18186     /**
18187      * Sets the right position of this view relative to its parent. This method is meant to be called
18188      * by the layout system and should not generally be called otherwise, because the property
18189      * may be changed at any time by the layout.
18190      *
18191      * @param right The right of this view, in pixels.
18192      */
setRight(int right)18193     public final void setRight(int right) {
18194         if (right != mRight) {
18195             final boolean matrixIsIdentity = hasIdentityMatrix();
18196             if (matrixIsIdentity) {
18197                 if (mAttachInfo != null) {
18198                     int maxRight;
18199                     if (right < mRight) {
18200                         maxRight = mRight;
18201                     } else {
18202                         maxRight = right;
18203                     }
18204                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
18205                 }
18206             } else {
18207                 // Double-invalidation is necessary to capture view's old and new areas
18208                 invalidate(true);
18209             }
18210 
18211             int oldWidth = mRight - mLeft;
18212             int height = mBottom - mTop;
18213 
18214             mRight = right;
18215             mRenderNode.setRight(mRight);
18216 
18217             sizeChange(mRight - mLeft, height, oldWidth, height);
18218 
18219             if (!matrixIsIdentity) {
18220                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18221                 invalidate(true);
18222             }
18223             mBackgroundSizeChanged = true;
18224             mDefaultFocusHighlightSizeChanged = true;
18225             if (mForegroundInfo != null) {
18226                 mForegroundInfo.mBoundsChanged = true;
18227             }
18228             invalidateParentIfNeeded();
18229         }
18230     }
18231 
sanitizeFloatPropertyValue(float value, String propertyName)18232     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
18233         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
18234     }
18235 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)18236     private static float sanitizeFloatPropertyValue(float value, String propertyName,
18237             float min, float max) {
18238         // The expected "nothing bad happened" path
18239         if (value >= min && value <= max) return value;
18240 
18241         if (value < min || value == Float.NEGATIVE_INFINITY) {
18242             if (sThrowOnInvalidFloatProperties) {
18243                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
18244                         + value + ", the value must be >= " + min);
18245             }
18246             return min;
18247         }
18248 
18249         if (value > max || value == Float.POSITIVE_INFINITY) {
18250             if (sThrowOnInvalidFloatProperties) {
18251                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
18252                         + value + ", the value must be <= " + max);
18253             }
18254             return max;
18255         }
18256 
18257         if (Float.isNaN(value)) {
18258             if (sThrowOnInvalidFloatProperties) {
18259                 throw new IllegalArgumentException(
18260                         "Cannot set '" + propertyName + "' to Float.NaN");
18261             }
18262             return 0; // Unclear which direction this NaN went so... 0?
18263         }
18264 
18265         // Shouldn't be possible to reach this.
18266         throw new IllegalStateException("How do you get here?? " + value);
18267     }
18268 
18269     /**
18270      * The visual x position of this view, in pixels. This is equivalent to the
18271      * {@link #setTranslationX(float) translationX} property plus the current
18272      * {@link #getLeft() left} property.
18273      *
18274      * @return The visual x position of this view, in pixels.
18275      */
18276     @ViewDebug.ExportedProperty(category = "drawing")
getX()18277     public float getX() {
18278         return mLeft + getTranslationX();
18279     }
18280 
18281     /**
18282      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
18283      * {@link #setTranslationX(float) translationX} property to be the difference between
18284      * the x value passed in and the current {@link #getLeft() left} property.
18285      *
18286      * @param x The visual x position of this view, in pixels.
18287      */
setX(float x)18288     public void setX(float x) {
18289         setTranslationX(x - mLeft);
18290     }
18291 
18292     /**
18293      * The visual y position of this view, in pixels. This is equivalent to the
18294      * {@link #setTranslationY(float) translationY} property plus the current
18295      * {@link #getTop() top} property.
18296      *
18297      * @return The visual y position of this view, in pixels.
18298      */
18299     @ViewDebug.ExportedProperty(category = "drawing")
getY()18300     public float getY() {
18301         return mTop + getTranslationY();
18302     }
18303 
18304     /**
18305      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
18306      * {@link #setTranslationY(float) translationY} property to be the difference between
18307      * the y value passed in and the current {@link #getTop() top} property.
18308      *
18309      * @param y The visual y position of this view, in pixels.
18310      */
setY(float y)18311     public void setY(float y) {
18312         setTranslationY(y - mTop);
18313     }
18314 
18315     /**
18316      * The visual z position of this view, in pixels. This is equivalent to the
18317      * {@link #setTranslationZ(float) translationZ} property plus the current
18318      * {@link #getElevation() elevation} property.
18319      *
18320      * @return The visual z position of this view, in pixels.
18321      */
18322     @ViewDebug.ExportedProperty(category = "drawing")
getZ()18323     public float getZ() {
18324         return getElevation() + getTranslationZ();
18325     }
18326 
18327     /**
18328      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
18329      * {@link #setTranslationZ(float) translationZ} property to be the difference between
18330      * the z value passed in and the current {@link #getElevation() elevation} property.
18331      *
18332      * @param z The visual z position of this view, in pixels.
18333      */
setZ(float z)18334     public void setZ(float z) {
18335         setTranslationZ(z - getElevation());
18336     }
18337 
18338     /**
18339      * The base elevation of this view relative to its parent, in pixels.
18340      *
18341      * @return The base depth position of the view, in pixels.
18342      */
18343     @ViewDebug.ExportedProperty(category = "drawing")
18344     @InspectableProperty
getElevation()18345     public float getElevation() {
18346         return mRenderNode.getElevation();
18347     }
18348 
18349     /**
18350      * Sets the base elevation of this view, in pixels.
18351      *
18352      * @attr ref android.R.styleable#View_elevation
18353      */
18354     @RemotableViewMethod
setElevation(float elevation)18355     public void setElevation(float elevation) {
18356         if (elevation != getElevation()) {
18357             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
18358             invalidateViewProperty(true, false);
18359             mRenderNode.setElevation(elevation);
18360             invalidateViewProperty(false, true);
18361 
18362             invalidateParentIfNeededAndWasQuickRejected();
18363         }
18364     }
18365 
18366     /**
18367      * The horizontal location of this view relative to its {@link #getLeft() left} position.
18368      * This position is post-layout, in addition to wherever the object's
18369      * layout placed it.
18370      *
18371      * @return The horizontal position of this view relative to its left position, in pixels.
18372      */
18373     @ViewDebug.ExportedProperty(category = "drawing")
18374     @InspectableProperty
getTranslationX()18375     public float getTranslationX() {
18376         return mRenderNode.getTranslationX();
18377     }
18378 
18379     /**
18380      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
18381      * This effectively positions the object post-layout, in addition to wherever the object's
18382      * layout placed it.
18383      *
18384      * @param translationX The horizontal position of this view relative to its left position,
18385      * in pixels.
18386      *
18387      * @attr ref android.R.styleable#View_translationX
18388      */
18389     @RemotableViewMethod
setTranslationX(float translationX)18390     public void setTranslationX(float translationX) {
18391         if (translationX != getTranslationX()) {
18392             invalidateViewProperty(true, false);
18393             mRenderNode.setTranslationX(translationX);
18394             invalidateViewProperty(false, true);
18395 
18396             invalidateParentIfNeededAndWasQuickRejected();
18397             notifySubtreeAccessibilityStateChangedIfNeeded();
18398         }
18399     }
18400 
18401     /**
18402      * The vertical location of this view relative to its {@link #getTop() top} position.
18403      * This position is post-layout, in addition to wherever the object's
18404      * layout placed it.
18405      *
18406      * @return The vertical position of this view relative to its top position,
18407      * in pixels.
18408      */
18409     @ViewDebug.ExportedProperty(category = "drawing")
18410     @InspectableProperty
getTranslationY()18411     public float getTranslationY() {
18412         return mRenderNode.getTranslationY();
18413     }
18414 
18415     /**
18416      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
18417      * This effectively positions the object post-layout, in addition to wherever the object's
18418      * layout placed it.
18419      *
18420      * @param translationY The vertical position of this view relative to its top position,
18421      * in pixels.
18422      *
18423      * @attr ref android.R.styleable#View_translationY
18424      */
18425     @RemotableViewMethod
setTranslationY(float translationY)18426     public void setTranslationY(float translationY) {
18427         if (translationY != getTranslationY()) {
18428             invalidateViewProperty(true, false);
18429             mRenderNode.setTranslationY(translationY);
18430             invalidateViewProperty(false, true);
18431 
18432             invalidateParentIfNeededAndWasQuickRejected();
18433             notifySubtreeAccessibilityStateChangedIfNeeded();
18434         }
18435     }
18436 
18437     /**
18438      * The depth location of this view relative to its {@link #getElevation() elevation}.
18439      *
18440      * @return The depth of this view relative to its elevation.
18441      */
18442     @ViewDebug.ExportedProperty(category = "drawing")
18443     @InspectableProperty
getTranslationZ()18444     public float getTranslationZ() {
18445         return mRenderNode.getTranslationZ();
18446     }
18447 
18448     /**
18449      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
18450      *
18451      * @attr ref android.R.styleable#View_translationZ
18452      */
18453     @RemotableViewMethod
setTranslationZ(float translationZ)18454     public void setTranslationZ(float translationZ) {
18455         if (translationZ != getTranslationZ()) {
18456             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
18457             invalidateViewProperty(true, false);
18458             mRenderNode.setTranslationZ(translationZ);
18459             invalidateViewProperty(false, true);
18460 
18461             invalidateParentIfNeededAndWasQuickRejected();
18462         }
18463     }
18464 
18465     /**
18466      * Changes the transformation matrix on the view. This is used in animation frameworks,
18467      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
18468      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
18469      * Application developers should use transformation methods like {@link #setRotation(float)},
18470      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
18471      * and {@link #setTranslationY(float)} (float)}} instead.
18472      *
18473      * @param matrix The matrix, null indicates that the matrix should be cleared.
18474      * @see #getAnimationMatrix()
18475      */
setAnimationMatrix(@ullable Matrix matrix)18476     public void setAnimationMatrix(@Nullable Matrix matrix) {
18477         invalidateViewProperty(true, false);
18478         mRenderNode.setAnimationMatrix(matrix);
18479         invalidateViewProperty(false, true);
18480 
18481         invalidateParentIfNeededAndWasQuickRejected();
18482     }
18483 
18484     /**
18485      * Return the current transformation matrix of the view. This is used in animation frameworks,
18486      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
18487      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
18488      * Application developers should use transformation methods like {@link #setRotation(float)},
18489      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
18490      * and {@link #setTranslationY(float)} (float)}} instead.
18491      *
18492      * @return the Matrix, null indicates there is no transformation
18493      * @see #setAnimationMatrix(Matrix)
18494      */
18495     @Nullable
getAnimationMatrix()18496     public Matrix getAnimationMatrix() {
18497         return mRenderNode.getAnimationMatrix();
18498     }
18499 
18500     /**
18501      * Returns the current StateListAnimator if exists.
18502      *
18503      * @return StateListAnimator or null if it does not exists
18504      * @see    #setStateListAnimator(android.animation.StateListAnimator)
18505      */
18506     @InspectableProperty
getStateListAnimator()18507     public StateListAnimator getStateListAnimator() {
18508         return mStateListAnimator;
18509     }
18510 
18511     /**
18512      * Attaches the provided StateListAnimator to this View.
18513      * <p>
18514      * Any previously attached StateListAnimator will be detached.
18515      *
18516      * @param stateListAnimator The StateListAnimator to update the view
18517      * @see android.animation.StateListAnimator
18518      */
setStateListAnimator(StateListAnimator stateListAnimator)18519     public void setStateListAnimator(StateListAnimator stateListAnimator) {
18520         if (mStateListAnimator == stateListAnimator) {
18521             return;
18522         }
18523         if (mStateListAnimator != null) {
18524             mStateListAnimator.setTarget(null);
18525         }
18526         mStateListAnimator = stateListAnimator;
18527         if (stateListAnimator != null) {
18528             stateListAnimator.setTarget(this);
18529             if (isAttachedToWindow()) {
18530                 stateListAnimator.setState(getDrawableState());
18531             }
18532         }
18533     }
18534 
18535     /**
18536      * Returns whether the Outline should be used to clip the contents of the View.
18537      * <p>
18538      * Note that this flag will only be respected if the View's Outline returns true from
18539      * {@link Outline#canClip()}.
18540      *
18541      * @see #setOutlineProvider(ViewOutlineProvider)
18542      * @see #setClipToOutline(boolean)
18543      */
getClipToOutline()18544     public final boolean getClipToOutline() {
18545         return mRenderNode.getClipToOutline();
18546     }
18547 
18548     /**
18549      * Sets whether the View's Outline should be used to clip the contents of the View.
18550      * <p>
18551      * Only a single non-rectangular clip can be applied on a View at any time.
18552      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
18553      * circular reveal} animation take priority over Outline clipping, and
18554      * child Outline clipping takes priority over Outline clipping done by a
18555      * parent.
18556      * <p>
18557      * Note that this flag will only be respected if the View's Outline returns true from
18558      * {@link Outline#canClip()}.
18559      *
18560      * @see #setOutlineProvider(ViewOutlineProvider)
18561      * @see #getClipToOutline()
18562      *
18563      * @attr ref android.R.styleable#View_clipToOutline
18564      */
18565     @RemotableViewMethod
setClipToOutline(boolean clipToOutline)18566     public void setClipToOutline(boolean clipToOutline) {
18567         damageInParent();
18568         if (getClipToOutline() != clipToOutline) {
18569             mRenderNode.setClipToOutline(clipToOutline);
18570         }
18571     }
18572 
18573     // correspond to the enum values of View_outlineProvider
18574     private static final int PROVIDER_BACKGROUND = 0;
18575     private static final int PROVIDER_NONE = 1;
18576     private static final int PROVIDER_BOUNDS = 2;
18577     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)18578     private void setOutlineProviderFromAttribute(int providerInt) {
18579         switch (providerInt) {
18580             case PROVIDER_BACKGROUND:
18581                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
18582                 break;
18583             case PROVIDER_NONE:
18584                 setOutlineProvider(null);
18585                 break;
18586             case PROVIDER_BOUNDS:
18587                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
18588                 break;
18589             case PROVIDER_PADDED_BOUNDS:
18590                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
18591                 break;
18592         }
18593     }
18594 
18595     /**
18596      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
18597      * the shape of the shadow it casts, and enables outline clipping.
18598      * <p>
18599      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
18600      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
18601      * outline provider with this method allows this behavior to be overridden.
18602      * <p>
18603      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
18604      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
18605      * <p>
18606      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
18607      *
18608      * @see #setClipToOutline(boolean)
18609      * @see #getClipToOutline()
18610      * @see #getOutlineProvider()
18611      */
setOutlineProvider(ViewOutlineProvider provider)18612     public void setOutlineProvider(ViewOutlineProvider provider) {
18613         mOutlineProvider = provider;
18614         invalidateOutline();
18615     }
18616 
18617     /**
18618      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
18619      * that defines the shape of the shadow it casts, and enables outline clipping.
18620      *
18621      * @see #setOutlineProvider(ViewOutlineProvider)
18622      */
18623     @InspectableProperty
getOutlineProvider()18624     public ViewOutlineProvider getOutlineProvider() {
18625         return mOutlineProvider;
18626     }
18627 
18628     /**
18629      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
18630      *
18631      * @see #setOutlineProvider(ViewOutlineProvider)
18632      */
invalidateOutline()18633     public void invalidateOutline() {
18634         rebuildOutline();
18635 
18636         notifySubtreeAccessibilityStateChangedIfNeeded();
18637         invalidateViewProperty(false, false);
18638     }
18639 
18640     /**
18641      * Internal version of {@link #invalidateOutline()} which invalidates the
18642      * outline without invalidating the view itself. This is intended to be called from
18643      * within methods in the View class itself which are the result of the view being
18644      * invalidated already. For example, when we are drawing the background of a View,
18645      * we invalidate the outline in case it changed in the meantime, but we do not
18646      * need to invalidate the view because we're already drawing the background as part
18647      * of drawing the view in response to an earlier invalidation of the view.
18648      */
rebuildOutline()18649     private void rebuildOutline() {
18650         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
18651         if (mAttachInfo == null) return;
18652 
18653         if (mOutlineProvider == null) {
18654             // no provider, remove outline
18655             mRenderNode.setOutline(null);
18656         } else {
18657             final Outline outline = mAttachInfo.mTmpOutline;
18658             outline.setEmpty();
18659             outline.setAlpha(1.0f);
18660 
18661             mOutlineProvider.getOutline(this, outline);
18662             mRenderNode.setOutline(outline);
18663         }
18664     }
18665 
18666     /**
18667      * HierarchyViewer only
18668      *
18669      * @hide
18670      */
18671     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()18672     public boolean hasShadow() {
18673         return mRenderNode.hasShadow();
18674     }
18675 
18676     /**
18677      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
18678      * elevation value.
18679      * <p>
18680      * By default the shadow color is black. Generally, this color will be opaque so the intensity
18681      * of the shadow is consistent between different views with different colors.
18682      * <p>
18683      * The opacity of the final spot shadow is a function of the shadow caster height, the
18684      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
18685      * {@link android.R.attr#spotShadowAlpha} theme attribute.
18686      *
18687      * @attr ref android.R.styleable#View_outlineSpotShadowColor
18688      * @param color The color this View will cast for its elevation spot shadow.
18689      */
setOutlineSpotShadowColor(@olorInt int color)18690     public void setOutlineSpotShadowColor(@ColorInt int color) {
18691         if (mRenderNode.setSpotShadowColor(color)) {
18692             invalidateViewProperty(true, true);
18693         }
18694     }
18695 
18696     /**
18697      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
18698      * was set
18699      */
18700     @InspectableProperty
getOutlineSpotShadowColor()18701     public @ColorInt int getOutlineSpotShadowColor() {
18702         return mRenderNode.getSpotShadowColor();
18703     }
18704 
18705     /**
18706      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
18707      * elevation value.
18708      * <p>
18709      * By default the shadow color is black. Generally, this color will be opaque so the intensity
18710      * of the shadow is consistent between different views with different colors.
18711      * <p>
18712      * The opacity of the final ambient shadow is a function of the shadow caster height, the
18713      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
18714      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
18715      *
18716      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
18717      * @param color The color this View will cast for its elevation shadow.
18718      */
setOutlineAmbientShadowColor(@olorInt int color)18719     public void setOutlineAmbientShadowColor(@ColorInt int color) {
18720         if (mRenderNode.setAmbientShadowColor(color)) {
18721             invalidateViewProperty(true, true);
18722         }
18723     }
18724 
18725     /**
18726      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
18727      * nothing was set
18728      */
18729     @InspectableProperty
getOutlineAmbientShadowColor()18730     public @ColorInt int getOutlineAmbientShadowColor() {
18731         return mRenderNode.getAmbientShadowColor();
18732     }
18733 
18734 
18735     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)18736     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
18737         mRenderNode.setRevealClip(shouldClip, x, y, radius);
18738         invalidateViewProperty(false, false);
18739     }
18740 
18741     /**
18742      * Hit rectangle in parent's coordinates
18743      *
18744      * @param outRect The hit rectangle of the view.
18745      */
getHitRect(Rect outRect)18746     public void getHitRect(Rect outRect) {
18747         if (hasIdentityMatrix() || mAttachInfo == null) {
18748             outRect.set(mLeft, mTop, mRight, mBottom);
18749         } else {
18750             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
18751             tmpRect.set(0, 0, getWidth(), getHeight());
18752             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
18753             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
18754                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
18755         }
18756     }
18757 
18758     /**
18759      * Determines whether the given point, in local coordinates is inside the view.
18760      */
pointInView(float localX, float localY)18761     /*package*/ final boolean pointInView(float localX, float localY) {
18762         return pointInView(localX, localY, 0);
18763     }
18764 
18765     /**
18766      * Utility method to determine whether the given point, in local coordinates,
18767      * is inside the view, where the area of the view is expanded by the slop factor.
18768      * This method is called while processing touch-move events to determine if the event
18769      * is still within the view.
18770      *
18771      * @hide
18772      */
18773     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)18774     public boolean pointInView(float localX, float localY, float slop) {
18775         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
18776                 localY < ((mBottom - mTop) + slop);
18777     }
18778 
18779     /**
18780      * When a view has focus and the user navigates away from it, the next view is searched for
18781      * starting from the rectangle filled in by this method.
18782      *
18783      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
18784      * of the view.  However, if your view maintains some idea of internal selection,
18785      * such as a cursor, or a selected row or column, you should override this method and
18786      * fill in a more specific rectangle.
18787      *
18788      * @param r The rectangle to fill in, in this view's coordinates.
18789      */
getFocusedRect(Rect r)18790     public void getFocusedRect(Rect r) {
18791         getDrawingRect(r);
18792     }
18793 
18794     /**
18795      * Sets {@code r} to the coordinates of the non-clipped area of this view in
18796      * the coordinate space of the view's root view. Sets {@code globalOffset}
18797      * to the offset of the view's x and y coordinates from the coordinate space
18798      * origin, which is the top left corner of the root view irrespective of
18799      * screen decorations and system UI elements.
18800      *
18801      * <p>To convert {@code r} to coordinates relative to the top left corner of
18802      * this view (without taking view rotations into account), offset {@code r}
18803      * by the inverse values of
18804      * {@code globalOffset}&mdash;{@code r.offset(-globalOffset.x,
18805      * -globalOffset.y)}&mdash;which is equivalent to calling
18806      * {@link #getLocalVisibleRect(Rect) getLocalVisibleRect(Rect)}.
18807      *
18808      * <p><b>Note:</b> Do not use this method to determine the size of a window
18809      * in multi-window mode; use
18810      * {@link WindowManager#getCurrentWindowMetrics()}.
18811      *
18812      * @param r If the method returns true, contains the coordinates of the
18813      *      visible portion of this view in the coordinate space of the view's
18814      *      root view. If the method returns false, the contents of {@code r}
18815      *      are undefined.
18816      * @param globalOffset If the method returns true, contains the offset of
18817      *      the x and y coordinates of this view from the top left corner of the
18818      *      view's root view. If the method returns false, the contents of
18819      *      {@code globalOffset} are undefined. The argument can be null (see
18820      *      {@link #getGlobalVisibleRect(Rect) getGlobalVisibleRect(Rect)}.
18821      * @return true if at least part of the view is visible within the root
18822      *      view; false if the view is completely clipped or translated out of
18823      *      the visible area of the root view.
18824      *
18825      * @see #getLocalVisibleRect(Rect)
18826      */
getGlobalVisibleRect(Rect r, Point globalOffset)18827     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
18828         int width = mRight - mLeft;
18829         int height = mBottom - mTop;
18830         if (width > 0 && height > 0) {
18831             r.set(0, 0, width, height);
18832             if (globalOffset != null) {
18833                 globalOffset.set(-mScrollX, -mScrollY);
18834             }
18835             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
18836         }
18837         return false;
18838     }
18839 
18840     /**
18841      * Sets {@code r} to the coordinates of the non-clipped area of this view in
18842      * the coordinate space of the view's root view.
18843      *
18844      * <p>See {@link #getGlobalVisibleRect(Rect, Point)
18845      * getGlobalVisibleRect(Rect, Point)} for more information.
18846      *
18847      * @param r If the method returns true, contains the coordinates of the
18848      *      visible portion of this view in the coordinate space of the view's
18849      *      root view. If the method returns false, the contents of {@code r}
18850      *      are undefined.
18851      * @return true if at least part of the view is visible within the root
18852      *      view; otherwise false.
18853      */
getGlobalVisibleRect(Rect r)18854     public final boolean getGlobalVisibleRect(Rect r) {
18855         return getGlobalVisibleRect(r, null);
18856     }
18857 
18858     /**
18859      * Sets {@code r} to the coordinates of the non-clipped area of this view
18860      * relative to the top left corner of the view.
18861      *
18862      * <p>If the view is clipped on the left or top, the left and top
18863      * coordinates are offset from 0 by the clipped amount. For example, if the
18864      * view is off screen 50px on the left and 30px at the top, the left and top
18865      * coordinates are 50 and 30 respectively.
18866      *
18867      * <p>If the view is clipped on the right or bottom, the right and bottom
18868      * coordinates are reduced by the clipped amount. For example, if the view
18869      * is off screen 40px on the right and 20px at the bottom, the right
18870      * coordinate is the view width - 40, and the bottom coordinate is the view
18871      * height - 20.
18872      *
18873      * @param r If the method returns true, contains the coordinates of the
18874      *      visible portion of this view relative to the top left corner of the
18875      *      view. If the method returns false, the contents of {@code r} are
18876      *      undefined.
18877      * @return true if at least part of the view is visible; false if the view
18878      *      is completely clipped or translated out of the visible area.
18879      *
18880      * @see #getGlobalVisibleRect(Rect, Point)
18881      */
getLocalVisibleRect(Rect r)18882     public final boolean getLocalVisibleRect(Rect r) {
18883         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
18884         if (getGlobalVisibleRect(r, offset)) {
18885             r.offset(-offset.x, -offset.y); // make r local
18886             return true;
18887         }
18888         return false;
18889     }
18890 
18891     /**
18892      * Offset this view's vertical location by the specified number of pixels.
18893      *
18894      * @param offset the number of pixels to offset the view by
18895      */
offsetTopAndBottom(int offset)18896     public void offsetTopAndBottom(int offset) {
18897         if (offset != 0) {
18898             final boolean matrixIsIdentity = hasIdentityMatrix();
18899             if (matrixIsIdentity) {
18900                 if (isHardwareAccelerated()) {
18901                     invalidateViewProperty(false, false);
18902                 } else {
18903                     final ViewParent p = mParent;
18904                     if (p != null && mAttachInfo != null) {
18905                         final Rect r = mAttachInfo.mTmpInvalRect;
18906                         int minTop;
18907                         int maxBottom;
18908                         int yLoc;
18909                         if (offset < 0) {
18910                             minTop = mTop + offset;
18911                             maxBottom = mBottom;
18912                             yLoc = offset;
18913                         } else {
18914                             minTop = mTop;
18915                             maxBottom = mBottom + offset;
18916                             yLoc = 0;
18917                         }
18918                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
18919                         p.invalidateChild(this, r);
18920                     }
18921                 }
18922             } else {
18923                 invalidateViewProperty(false, false);
18924             }
18925 
18926             mTop += offset;
18927             mBottom += offset;
18928             mRenderNode.offsetTopAndBottom(offset);
18929             if (isHardwareAccelerated()) {
18930                 invalidateViewProperty(false, false);
18931                 invalidateParentIfNeededAndWasQuickRejected();
18932             } else {
18933                 if (!matrixIsIdentity) {
18934                     invalidateViewProperty(false, true);
18935                 }
18936                 invalidateParentIfNeeded();
18937             }
18938             notifySubtreeAccessibilityStateChangedIfNeeded();
18939         }
18940     }
18941 
18942     /**
18943      * Offset this view's horizontal location by the specified amount of pixels.
18944      *
18945      * @param offset the number of pixels to offset the view by
18946      */
offsetLeftAndRight(int offset)18947     public void offsetLeftAndRight(int offset) {
18948         if (offset != 0) {
18949             final boolean matrixIsIdentity = hasIdentityMatrix();
18950             if (matrixIsIdentity) {
18951                 if (isHardwareAccelerated()) {
18952                     invalidateViewProperty(false, false);
18953                 } else {
18954                     final ViewParent p = mParent;
18955                     if (p != null && mAttachInfo != null) {
18956                         final Rect r = mAttachInfo.mTmpInvalRect;
18957                         int minLeft;
18958                         int maxRight;
18959                         if (offset < 0) {
18960                             minLeft = mLeft + offset;
18961                             maxRight = mRight;
18962                         } else {
18963                             minLeft = mLeft;
18964                             maxRight = mRight + offset;
18965                         }
18966                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
18967                         p.invalidateChild(this, r);
18968                     }
18969                 }
18970             } else {
18971                 invalidateViewProperty(false, false);
18972             }
18973 
18974             mLeft += offset;
18975             mRight += offset;
18976             mRenderNode.offsetLeftAndRight(offset);
18977             if (isHardwareAccelerated()) {
18978                 invalidateViewProperty(false, false);
18979                 invalidateParentIfNeededAndWasQuickRejected();
18980             } else {
18981                 if (!matrixIsIdentity) {
18982                     invalidateViewProperty(false, true);
18983                 }
18984                 invalidateParentIfNeeded();
18985             }
18986             notifySubtreeAccessibilityStateChangedIfNeeded();
18987         }
18988     }
18989 
18990     /**
18991      * Get the LayoutParams associated with this view. All views should have
18992      * layout parameters. These supply parameters to the <i>parent</i> of this
18993      * view specifying how it should be arranged. There are many subclasses of
18994      * ViewGroup.LayoutParams, and these correspond to the different subclasses
18995      * of ViewGroup that are responsible for arranging their children.
18996      *
18997      * This method may return null if this View is not attached to a parent
18998      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
18999      * was not invoked successfully. When a View is attached to a parent
19000      * ViewGroup, this method must not return null.
19001      *
19002      * @return The LayoutParams associated with this view, or null if no
19003      *         parameters have been set yet
19004      */
19005     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()19006     public ViewGroup.LayoutParams getLayoutParams() {
19007         return mLayoutParams;
19008     }
19009 
19010     /**
19011      * Set the layout parameters associated with this view. These supply
19012      * parameters to the <i>parent</i> of this view specifying how it should be
19013      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
19014      * correspond to the different subclasses of ViewGroup that are responsible
19015      * for arranging their children.
19016      *
19017      * @param params The layout parameters for this view, cannot be null
19018      */
setLayoutParams(ViewGroup.LayoutParams params)19019     public void setLayoutParams(ViewGroup.LayoutParams params) {
19020         if (params == null) {
19021             throw new NullPointerException("Layout parameters cannot be null");
19022         }
19023         mLayoutParams = params;
19024         resolveLayoutParams();
19025         if (mParent instanceof ViewGroup) {
19026             ((ViewGroup) mParent).onSetLayoutParams(this, params);
19027         }
19028         requestLayout();
19029     }
19030 
19031     /**
19032      * Resolve the layout parameters depending on the resolved layout direction
19033      *
19034      * @hide
19035      */
resolveLayoutParams()19036     public void resolveLayoutParams() {
19037         if (mLayoutParams != null) {
19038             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
19039         }
19040     }
19041 
19042     /**
19043      * Set the scrolled position of your view. This will cause a call to
19044      * {@link #onScrollChanged(int, int, int, int)} and the view will be
19045      * invalidated.
19046      * @param x the x position to scroll to
19047      * @param y the y position to scroll to
19048      */
scrollTo(int x, int y)19049     public void scrollTo(int x, int y) {
19050         if (mScrollX != x || mScrollY != y) {
19051             int oldX = mScrollX;
19052             int oldY = mScrollY;
19053             mScrollX = x;
19054             mScrollY = y;
19055             invalidateParentCaches();
19056             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
19057             if (!awakenScrollBars()) {
19058                 postInvalidateOnAnimation();
19059             }
19060         }
19061     }
19062 
19063     /**
19064      * Move the scrolled position of your view. This will cause a call to
19065      * {@link #onScrollChanged(int, int, int, int)} and the view will be
19066      * invalidated.
19067      * @param x the amount of pixels to scroll by horizontally
19068      * @param y the amount of pixels to scroll by vertically
19069      */
scrollBy(int x, int y)19070     public void scrollBy(int x, int y) {
19071         scrollTo(mScrollX + x, mScrollY + y);
19072     }
19073 
19074     /**
19075      * <p>Trigger the scrollbars to draw. When invoked this method starts an
19076      * animation to fade the scrollbars out after a default delay. If a subclass
19077      * provides animated scrolling, the start delay should equal the duration
19078      * of the scrolling animation.</p>
19079      *
19080      * <p>The animation starts only if at least one of the scrollbars is
19081      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
19082      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
19083      * this method returns true, and false otherwise. If the animation is
19084      * started, this method calls {@link #invalidate()}; in that case the
19085      * caller should not call {@link #invalidate()}.</p>
19086      *
19087      * <p>This method should be invoked every time a subclass directly updates
19088      * the scroll parameters.</p>
19089      *
19090      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
19091      * and {@link #scrollTo(int, int)}.</p>
19092      *
19093      * @return true if the animation is played, false otherwise
19094      *
19095      * @see #awakenScrollBars(int)
19096      * @see #scrollBy(int, int)
19097      * @see #scrollTo(int, int)
19098      * @see #isHorizontalScrollBarEnabled()
19099      * @see #isVerticalScrollBarEnabled()
19100      * @see #setHorizontalScrollBarEnabled(boolean)
19101      * @see #setVerticalScrollBarEnabled(boolean)
19102      */
awakenScrollBars()19103     protected boolean awakenScrollBars() {
19104         return mScrollCache != null &&
19105                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
19106     }
19107 
19108     /**
19109      * Trigger the scrollbars to draw.
19110      * This method differs from awakenScrollBars() only in its default duration.
19111      * initialAwakenScrollBars() will show the scroll bars for longer than
19112      * usual to give the user more of a chance to notice them.
19113      *
19114      * @return true if the animation is played, false otherwise.
19115      */
initialAwakenScrollBars()19116     private boolean initialAwakenScrollBars() {
19117         return mScrollCache != null &&
19118                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
19119     }
19120 
19121     /**
19122      * <p>
19123      * Trigger the scrollbars to draw. When invoked this method starts an
19124      * animation to fade the scrollbars out after a fixed delay. If a subclass
19125      * provides animated scrolling, the start delay should equal the duration of
19126      * the scrolling animation.
19127      * </p>
19128      *
19129      * <p>
19130      * The animation starts only if at least one of the scrollbars is enabled,
19131      * as specified by {@link #isHorizontalScrollBarEnabled()} and
19132      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
19133      * this method returns true, and false otherwise. If the animation is
19134      * started, this method calls {@link #invalidate()}; in that case the caller
19135      * should not call {@link #invalidate()}.
19136      * </p>
19137      *
19138      * <p>
19139      * This method should be invoked every time a subclass directly updates the
19140      * scroll parameters.
19141      * </p>
19142      *
19143      * @param startDelay the delay, in milliseconds, after which the animation
19144      *        should start; when the delay is 0, the animation starts
19145      *        immediately
19146      * @return true if the animation is played, false otherwise
19147      *
19148      * @see #scrollBy(int, int)
19149      * @see #scrollTo(int, int)
19150      * @see #isHorizontalScrollBarEnabled()
19151      * @see #isVerticalScrollBarEnabled()
19152      * @see #setHorizontalScrollBarEnabled(boolean)
19153      * @see #setVerticalScrollBarEnabled(boolean)
19154      */
awakenScrollBars(int startDelay)19155     protected boolean awakenScrollBars(int startDelay) {
19156         return awakenScrollBars(startDelay, true);
19157     }
19158 
19159     /**
19160      * <p>
19161      * Trigger the scrollbars to draw. When invoked this method starts an
19162      * animation to fade the scrollbars out after a fixed delay. If a subclass
19163      * provides animated scrolling, the start delay should equal the duration of
19164      * the scrolling animation.
19165      * </p>
19166      *
19167      * <p>
19168      * The animation starts only if at least one of the scrollbars is enabled,
19169      * as specified by {@link #isHorizontalScrollBarEnabled()} and
19170      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
19171      * this method returns true, and false otherwise. If the animation is
19172      * started, this method calls {@link #invalidate()} if the invalidate parameter
19173      * is set to true; in that case the caller
19174      * should not call {@link #invalidate()}.
19175      * </p>
19176      *
19177      * <p>
19178      * This method should be invoked every time a subclass directly updates the
19179      * scroll parameters.
19180      * </p>
19181      *
19182      * @param startDelay the delay, in milliseconds, after which the animation
19183      *        should start; when the delay is 0, the animation starts
19184      *        immediately
19185      *
19186      * @param invalidate Whether this method should call invalidate
19187      *
19188      * @return true if the animation is played, false otherwise
19189      *
19190      * @see #scrollBy(int, int)
19191      * @see #scrollTo(int, int)
19192      * @see #isHorizontalScrollBarEnabled()
19193      * @see #isVerticalScrollBarEnabled()
19194      * @see #setHorizontalScrollBarEnabled(boolean)
19195      * @see #setVerticalScrollBarEnabled(boolean)
19196      */
awakenScrollBars(int startDelay, boolean invalidate)19197     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
19198         final ScrollabilityCache scrollCache = mScrollCache;
19199 
19200         if (scrollCache == null || !scrollCache.fadeScrollBars) {
19201             return false;
19202         }
19203 
19204         if (scrollCache.scrollBar == null) {
19205             scrollCache.scrollBar = new ScrollBarDrawable();
19206             scrollCache.scrollBar.setState(getDrawableState());
19207             scrollCache.scrollBar.setCallback(this);
19208         }
19209 
19210         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
19211 
19212             if (invalidate) {
19213                 // Invalidate to show the scrollbars
19214                 postInvalidateOnAnimation();
19215             }
19216 
19217             if (scrollCache.state == ScrollabilityCache.OFF) {
19218                 // FIXME: this is copied from WindowManagerService.
19219                 // We should get this value from the system when it
19220                 // is possible to do so.
19221                 final int KEY_REPEAT_FIRST_DELAY = 750;
19222                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
19223             }
19224 
19225             // Tell mScrollCache when we should start fading. This may
19226             // extend the fade start time if one was already scheduled
19227             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
19228             scrollCache.fadeStartTime = fadeStartTime;
19229             scrollCache.state = ScrollabilityCache.ON;
19230 
19231             // Schedule our fader to run, unscheduling any old ones first
19232             if (mAttachInfo != null) {
19233                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
19234                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
19235             }
19236 
19237             return true;
19238         }
19239 
19240         return false;
19241     }
19242 
19243     /**
19244      * Do not invalidate views which are not visible and which are not running an animation. They
19245      * will not get drawn and they should not set dirty flags as if they will be drawn
19246      */
skipInvalidate()19247     private boolean skipInvalidate() {
19248         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
19249                 (!(mParent instanceof ViewGroup) ||
19250                         !((ViewGroup) mParent).isViewTransitioning(this));
19251     }
19252 
19253     /**
19254      * Mark the area defined by dirty as needing to be drawn. If the view is
19255      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
19256      * point in the future.
19257      * <p>
19258      * This must be called from a UI thread. To call from a non-UI thread, call
19259      * {@link #postInvalidate()}.
19260      * <p>
19261      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
19262      * {@code dirty}.
19263      *
19264      * @param dirty the rectangle representing the bounds of the dirty region
19265      *
19266      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
19267      * the importance of the dirty rectangle. In API 21 the given rectangle is
19268      * ignored entirely in favor of an internally-calculated area instead.
19269      * Because of this, clients are encouraged to just call {@link #invalidate()}.
19270      */
19271     @Deprecated
invalidate(Rect dirty)19272     public void invalidate(Rect dirty) {
19273         final int scrollX = mScrollX;
19274         final int scrollY = mScrollY;
19275         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
19276                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
19277     }
19278 
19279     /**
19280      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
19281      * coordinates of the dirty rect are relative to the view. If the view is
19282      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
19283      * point in the future.
19284      * <p>
19285      * This must be called from a UI thread. To call from a non-UI thread, call
19286      * {@link #postInvalidate()}.
19287      *
19288      * @param l the left position of the dirty region
19289      * @param t the top position of the dirty region
19290      * @param r the right position of the dirty region
19291      * @param b the bottom position of the dirty region
19292      *
19293      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
19294      * the importance of the dirty rectangle. In API 21 the given rectangle is
19295      * ignored entirely in favor of an internally-calculated area instead.
19296      * Because of this, clients are encouraged to just call {@link #invalidate()}.
19297      */
19298     @Deprecated
invalidate(int l, int t, int r, int b)19299     public void invalidate(int l, int t, int r, int b) {
19300         final int scrollX = mScrollX;
19301         final int scrollY = mScrollY;
19302         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
19303     }
19304 
19305     /**
19306      * Invalidate the whole view. If the view is visible,
19307      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
19308      * the future.
19309      * <p>
19310      * This must be called from a UI thread. To call from a non-UI thread, call
19311      * {@link #postInvalidate()}.
19312      */
invalidate()19313     public void invalidate() {
19314         invalidate(true);
19315     }
19316 
19317     /**
19318      * This is where the invalidate() work actually happens. A full invalidate()
19319      * causes the drawing cache to be invalidated, but this function can be
19320      * called with invalidateCache set to false to skip that invalidation step
19321      * for cases that do not need it (for example, a component that remains at
19322      * the same dimensions with the same content).
19323      *
19324      * @param invalidateCache Whether the drawing cache for this view should be
19325      *            invalidated as well. This is usually true for a full
19326      *            invalidate, but may be set to false if the View's contents or
19327      *            dimensions have not changed.
19328      * @hide
19329      */
19330     @UnsupportedAppUsage
invalidate(boolean invalidateCache)19331     public void invalidate(boolean invalidateCache) {
19332         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
19333     }
19334 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)19335     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
19336             boolean fullInvalidate) {
19337         if (mGhostView != null) {
19338             mGhostView.invalidate(true);
19339             return;
19340         }
19341 
19342         if (skipInvalidate()) {
19343             return;
19344         }
19345 
19346         // Reset content capture caches
19347         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
19348         mContentCaptureSessionCached = false;
19349 
19350         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
19351                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
19352                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
19353                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
19354             if (fullInvalidate) {
19355                 mLastIsOpaque = isOpaque();
19356                 mPrivateFlags &= ~PFLAG_DRAWN;
19357             }
19358 
19359             mPrivateFlags |= PFLAG_DIRTY;
19360 
19361             if (invalidateCache) {
19362                 mPrivateFlags |= PFLAG_INVALIDATED;
19363                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
19364             }
19365 
19366             // Propagate the damage rectangle to the parent view.
19367             final AttachInfo ai = mAttachInfo;
19368             final ViewParent p = mParent;
19369             if (p != null && ai != null && l < r && t < b) {
19370                 final Rect damage = ai.mTmpInvalRect;
19371                 damage.set(l, t, r, b);
19372                 p.invalidateChild(this, damage);
19373             }
19374 
19375             // Damage the entire projection receiver, if necessary.
19376             if (mBackground != null && mBackground.isProjected()) {
19377                 final View receiver = getProjectionReceiver();
19378                 if (receiver != null) {
19379                     receiver.damageInParent();
19380                 }
19381             }
19382         }
19383     }
19384 
19385     /**
19386      * @return this view's projection receiver, or {@code null} if none exists
19387      */
getProjectionReceiver()19388     private View getProjectionReceiver() {
19389         ViewParent p = getParent();
19390         while (p != null && p instanceof View) {
19391             final View v = (View) p;
19392             if (v.isProjectionReceiver()) {
19393                 return v;
19394             }
19395             p = p.getParent();
19396         }
19397 
19398         return null;
19399     }
19400 
19401     /**
19402      * @return whether the view is a projection receiver
19403      */
isProjectionReceiver()19404     private boolean isProjectionReceiver() {
19405         return mBackground != null;
19406     }
19407 
19408     /**
19409      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
19410      * set any flags or handle all of the cases handled by the default invalidation methods.
19411      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
19412      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
19413      * walk up the hierarchy, transforming the dirty rect as necessary.
19414      *
19415      * The method also handles normal invalidation logic if display list properties are not
19416      * being used in this view. The invalidateParent and forceRedraw flags are used by that
19417      * backup approach, to handle these cases used in the various property-setting methods.
19418      *
19419      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
19420      * are not being used in this view
19421      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
19422      * list properties are not being used in this view
19423      */
19424     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)19425     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
19426         if (!isHardwareAccelerated()
19427                 || !mRenderNode.hasDisplayList()
19428                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
19429             if (invalidateParent) {
19430                 invalidateParentCaches();
19431             }
19432             if (forceRedraw) {
19433                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19434             }
19435             invalidate(false);
19436         } else {
19437             damageInParent();
19438         }
19439     }
19440 
19441     /**
19442      * Tells the parent view to damage this view's bounds.
19443      *
19444      * @hide
19445      */
damageInParent()19446     protected void damageInParent() {
19447         if (mParent != null && mAttachInfo != null) {
19448             mParent.onDescendantInvalidated(this, this);
19449         }
19450     }
19451 
19452     /**
19453      * Used to indicate that the parent of this view should clear its caches. This functionality
19454      * is used to force the parent to rebuild its display list (when hardware-accelerated),
19455      * which is necessary when various parent-managed properties of the view change, such as
19456      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
19457      * clears the parent caches and does not causes an invalidate event.
19458      *
19459      * @hide
19460      */
19461     @UnsupportedAppUsage
invalidateParentCaches()19462     protected void invalidateParentCaches() {
19463         if (mParent instanceof View) {
19464             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
19465         }
19466     }
19467 
19468     /**
19469      * Used to indicate that the parent of this view should be invalidated. This functionality
19470      * is used to force the parent to rebuild its display list (when hardware-accelerated),
19471      * which is necessary when various parent-managed properties of the view change, such as
19472      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
19473      * an invalidation event to the parent.
19474      *
19475      * @hide
19476      */
19477     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
invalidateParentIfNeeded()19478     protected void invalidateParentIfNeeded() {
19479         if (isHardwareAccelerated() && mParent instanceof View) {
19480             ((View) mParent).invalidate(true);
19481         }
19482     }
19483 
19484     /**
19485      * @hide
19486      */
invalidateParentIfNeededAndWasQuickRejected()19487     protected void invalidateParentIfNeededAndWasQuickRejected() {
19488         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
19489             // View was rejected last time it was drawn by its parent; this may have changed
19490             invalidateParentIfNeeded();
19491         }
19492     }
19493 
19494     /**
19495      * Indicates whether this View is opaque. An opaque View guarantees that it will
19496      * draw all the pixels overlapping its bounds using a fully opaque color.
19497      *
19498      * Subclasses of View should override this method whenever possible to indicate
19499      * whether an instance is opaque. Opaque Views are treated in a special way by
19500      * the View hierarchy, possibly allowing it to perform optimizations during
19501      * invalidate/draw passes.
19502      *
19503      * @return True if this View is guaranteed to be fully opaque, false otherwise.
19504      */
19505     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()19506     public boolean isOpaque() {
19507         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
19508                 getFinalAlpha() >= 1.0f;
19509     }
19510 
19511     /**
19512      * @hide
19513      */
19514     @UnsupportedAppUsage
computeOpaqueFlags()19515     protected void computeOpaqueFlags() {
19516         // Opaque if:
19517         //   - Has a background
19518         //   - Background is opaque
19519         //   - Doesn't have scrollbars or scrollbars overlay
19520 
19521         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
19522             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
19523         } else {
19524             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
19525         }
19526 
19527         final int flags = mViewFlags;
19528         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
19529                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
19530                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
19531             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
19532         } else {
19533             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
19534         }
19535     }
19536 
19537     /**
19538      * @hide
19539      */
hasOpaqueScrollbars()19540     protected boolean hasOpaqueScrollbars() {
19541         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
19542     }
19543 
19544     /**
19545      * @return A handler associated with the thread running the View. This
19546      * handler can be used to pump events in the UI events queue.
19547      */
getHandler()19548     public Handler getHandler() {
19549         final AttachInfo attachInfo = mAttachInfo;
19550         if (attachInfo != null) {
19551             return attachInfo.mHandler;
19552         }
19553         return null;
19554     }
19555 
19556     /**
19557      * Returns the queue of runnable for this view.
19558      *
19559      * @return the queue of runnables for this view
19560      */
getRunQueue()19561     private HandlerActionQueue getRunQueue() {
19562         if (mRunQueue == null) {
19563             mRunQueue = new HandlerActionQueue();
19564         }
19565         return mRunQueue;
19566     }
19567 
19568     /**
19569      * Gets the view root associated with the View.
19570      * @return The view root, or null if none.
19571      * @hide
19572      */
19573     @UnsupportedAppUsage
getViewRootImpl()19574     public ViewRootImpl getViewRootImpl() {
19575         if (mAttachInfo != null) {
19576             return mAttachInfo.mViewRootImpl;
19577         }
19578         return null;
19579     }
19580 
19581     /**
19582      * @hide
19583      */
19584     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getThreadedRenderer()19585     public ThreadedRenderer getThreadedRenderer() {
19586         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
19587     }
19588 
19589     /**
19590      * <p>Causes the Runnable to be added to the message queue.
19591      * The runnable will be run on the user interface thread.</p>
19592      *
19593      * @param action The Runnable that will be executed.
19594      *
19595      * @return Returns true if the Runnable was successfully placed in to the
19596      *         message queue.  Returns false on failure, usually because the
19597      *         looper processing the message queue is exiting.
19598      *
19599      * @see #postDelayed
19600      * @see #removeCallbacks
19601      */
post(Runnable action)19602     public boolean post(Runnable action) {
19603         final AttachInfo attachInfo = mAttachInfo;
19604         if (attachInfo != null) {
19605             return attachInfo.mHandler.post(action);
19606         }
19607 
19608         // Postpone the runnable until we know on which thread it needs to run.
19609         // Assume that the runnable will be successfully placed after attach.
19610         getRunQueue().post(action);
19611         return true;
19612     }
19613 
19614     /**
19615      * <p>Causes the Runnable to be added to the message queue, to be run
19616      * after the specified amount of time elapses.
19617      * The runnable will be run on the user interface thread.</p>
19618      *
19619      * @param action The Runnable that will be executed.
19620      * @param delayMillis The delay (in milliseconds) until the Runnable
19621      *        will be executed.
19622      *
19623      * @return true if the Runnable was successfully placed in to the
19624      *         message queue.  Returns false on failure, usually because the
19625      *         looper processing the message queue is exiting.  Note that a
19626      *         result of true does not mean the Runnable will be processed --
19627      *         if the looper is quit before the delivery time of the message
19628      *         occurs then the message will be dropped.
19629      *
19630      * @see #post
19631      * @see #removeCallbacks
19632      */
postDelayed(Runnable action, long delayMillis)19633     public boolean postDelayed(Runnable action, long delayMillis) {
19634         final AttachInfo attachInfo = mAttachInfo;
19635         if (attachInfo != null) {
19636             return attachInfo.mHandler.postDelayed(action, delayMillis);
19637         }
19638 
19639         // Postpone the runnable until we know on which thread it needs to run.
19640         // Assume that the runnable will be successfully placed after attach.
19641         getRunQueue().postDelayed(action, delayMillis);
19642         return true;
19643     }
19644 
19645     /**
19646      * <p>Causes the Runnable to execute on the next animation time step.
19647      * The runnable will be run on the user interface thread.</p>
19648      *
19649      * @param action The Runnable that will be executed.
19650      *
19651      * @see #postOnAnimationDelayed
19652      * @see #removeCallbacks
19653      */
postOnAnimation(Runnable action)19654     public void postOnAnimation(Runnable action) {
19655         final AttachInfo attachInfo = mAttachInfo;
19656         if (attachInfo != null) {
19657             attachInfo.mViewRootImpl.mChoreographer.postCallback(
19658                     Choreographer.CALLBACK_ANIMATION, action, null);
19659         } else {
19660             // Postpone the runnable until we know
19661             // on which thread it needs to run.
19662             getRunQueue().post(action);
19663         }
19664     }
19665 
19666     /**
19667      * <p>Causes the Runnable to execute on the next animation time step,
19668      * after the specified amount of time elapses.
19669      * The runnable will be run on the user interface thread.</p>
19670      *
19671      * @param action The Runnable that will be executed.
19672      * @param delayMillis The delay (in milliseconds) until the Runnable
19673      *        will be executed.
19674      *
19675      * @see #postOnAnimation
19676      * @see #removeCallbacks
19677      */
postOnAnimationDelayed(Runnable action, long delayMillis)19678     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
19679         final AttachInfo attachInfo = mAttachInfo;
19680         if (attachInfo != null) {
19681             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19682                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
19683         } else {
19684             // Postpone the runnable until we know
19685             // on which thread it needs to run.
19686             getRunQueue().postDelayed(action, delayMillis);
19687         }
19688     }
19689 
19690     /**
19691      * <p>Removes the specified Runnable from the message queue.</p>
19692      *
19693      * @param action The Runnable to remove from the message handling queue
19694      *
19695      * @return true if this view could ask the Handler to remove the Runnable,
19696      *         false otherwise. When the returned value is true, the Runnable
19697      *         may or may not have been actually removed from the message queue
19698      *         (for instance, if the Runnable was not in the queue already.)
19699      *
19700      * @see #post
19701      * @see #postDelayed
19702      * @see #postOnAnimation
19703      * @see #postOnAnimationDelayed
19704      */
removeCallbacks(Runnable action)19705     public boolean removeCallbacks(Runnable action) {
19706         if (action != null) {
19707             final AttachInfo attachInfo = mAttachInfo;
19708             if (attachInfo != null) {
19709                 attachInfo.mHandler.removeCallbacks(action);
19710                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19711                         Choreographer.CALLBACK_ANIMATION, action, null);
19712             }
19713             getRunQueue().removeCallbacks(action);
19714         }
19715         return true;
19716     }
19717 
19718     /**
19719      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
19720      * Use this to invalidate the View from a non-UI thread.</p>
19721      *
19722      * <p>This method can be invoked from outside of the UI thread
19723      * only when this View is attached to a window.</p>
19724      *
19725      * @see #invalidate()
19726      * @see #postInvalidateDelayed(long)
19727      */
postInvalidate()19728     public void postInvalidate() {
19729         postInvalidateDelayed(0);
19730     }
19731 
19732     /**
19733      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
19734      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
19735      *
19736      * <p>This method can be invoked from outside of the UI thread
19737      * only when this View is attached to a window.</p>
19738      *
19739      * @param left The left coordinate of the rectangle to invalidate.
19740      * @param top The top coordinate of the rectangle to invalidate.
19741      * @param right The right coordinate of the rectangle to invalidate.
19742      * @param bottom The bottom coordinate of the rectangle to invalidate.
19743      *
19744      * @see #invalidate(int, int, int, int)
19745      * @see #invalidate(Rect)
19746      * @see #postInvalidateDelayed(long, int, int, int, int)
19747      */
postInvalidate(int left, int top, int right, int bottom)19748     public void postInvalidate(int left, int top, int right, int bottom) {
19749         postInvalidateDelayed(0, left, top, right, bottom);
19750     }
19751 
19752     /**
19753      * <p>Cause an invalidate to happen on a subsequent cycle through the event
19754      * loop. Waits for the specified amount of time.</p>
19755      *
19756      * <p>This method can be invoked from outside of the UI thread
19757      * only when this View is attached to a window.</p>
19758      *
19759      * @param delayMilliseconds the duration in milliseconds to delay the
19760      *         invalidation by
19761      *
19762      * @see #invalidate()
19763      * @see #postInvalidate()
19764      */
postInvalidateDelayed(long delayMilliseconds)19765     public void postInvalidateDelayed(long delayMilliseconds) {
19766         // We try only with the AttachInfo because there's no point in invalidating
19767         // if we are not attached to our window
19768         final AttachInfo attachInfo = mAttachInfo;
19769         if (attachInfo != null) {
19770             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
19771         }
19772     }
19773 
19774     /**
19775      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
19776      * through the event loop. Waits for the specified amount of time.</p>
19777      *
19778      * <p>This method can be invoked from outside of the UI thread
19779      * only when this View is attached to a window.</p>
19780      *
19781      * @param delayMilliseconds the duration in milliseconds to delay the
19782      *         invalidation by
19783      * @param left The left coordinate of the rectangle to invalidate.
19784      * @param top The top coordinate of the rectangle to invalidate.
19785      * @param right The right coordinate of the rectangle to invalidate.
19786      * @param bottom The bottom coordinate of the rectangle to invalidate.
19787      *
19788      * @see #invalidate(int, int, int, int)
19789      * @see #invalidate(Rect)
19790      * @see #postInvalidate(int, int, int, int)
19791      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)19792     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
19793             int right, int bottom) {
19794 
19795         // We try only with the AttachInfo because there's no point in invalidating
19796         // if we are not attached to our window
19797         final AttachInfo attachInfo = mAttachInfo;
19798         if (attachInfo != null) {
19799             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19800             info.target = this;
19801             info.left = left;
19802             info.top = top;
19803             info.right = right;
19804             info.bottom = bottom;
19805 
19806             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
19807         }
19808     }
19809 
19810     /**
19811      * <p>Cause an invalidate to happen on the next animation time step, typically the
19812      * next display frame.</p>
19813      *
19814      * <p>This method can be invoked from outside of the UI thread
19815      * only when this View is attached to a window.</p>
19816      *
19817      * @see #invalidate()
19818      */
postInvalidateOnAnimation()19819     public void postInvalidateOnAnimation() {
19820         // We try only with the AttachInfo because there's no point in invalidating
19821         // if we are not attached to our window
19822         final AttachInfo attachInfo = mAttachInfo;
19823         if (attachInfo != null) {
19824             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
19825         }
19826     }
19827 
19828     /**
19829      * <p>Cause an invalidate of the specified area to happen on the next animation
19830      * time step, typically the next display frame.</p>
19831      *
19832      * <p>This method can be invoked from outside of the UI thread
19833      * only when this View is attached to a window.</p>
19834      *
19835      * @param left The left coordinate of the rectangle to invalidate.
19836      * @param top The top coordinate of the rectangle to invalidate.
19837      * @param right The right coordinate of the rectangle to invalidate.
19838      * @param bottom The bottom coordinate of the rectangle to invalidate.
19839      *
19840      * @see #invalidate(int, int, int, int)
19841      * @see #invalidate(Rect)
19842      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)19843     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
19844         // We try only with the AttachInfo because there's no point in invalidating
19845         // if we are not attached to our window
19846         final AttachInfo attachInfo = mAttachInfo;
19847         if (attachInfo != null) {
19848             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19849             info.target = this;
19850             info.left = left;
19851             info.top = top;
19852             info.right = right;
19853             info.bottom = bottom;
19854 
19855             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
19856         }
19857     }
19858 
19859     /**
19860      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
19861      * This event is sent at most once every
19862      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
19863      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)19864     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
19865         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
19866             AccessibilityEvent event =
19867                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
19868             event.setScrollDeltaX(dx);
19869             event.setScrollDeltaY(dy);
19870             sendAccessibilityEventUnchecked(event);
19871         }
19872     }
19873 
19874     /**
19875      * Called by a parent to request that a child update its values for mScrollX
19876      * and mScrollY if necessary. This will typically be done if the child is
19877      * animating a scroll using a {@link android.widget.Scroller Scroller}
19878      * object.
19879      */
computeScroll()19880     public void computeScroll() {
19881     }
19882 
19883     /**
19884      * <p>Indicate whether the horizontal edges are faded when the view is
19885      * scrolled horizontally.</p>
19886      *
19887      * @return true if the horizontal edges should are faded on scroll, false
19888      *         otherwise
19889      *
19890      * @see #setHorizontalFadingEdgeEnabled(boolean)
19891      *
19892      * @attr ref android.R.styleable#View_requiresFadingEdge
19893      */
isHorizontalFadingEdgeEnabled()19894     public boolean isHorizontalFadingEdgeEnabled() {
19895         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
19896     }
19897 
19898     /**
19899      * <p>Define whether the horizontal edges should be faded when this view
19900      * is scrolled horizontally.</p>
19901      *
19902      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
19903      *                                    be faded when the view is scrolled
19904      *                                    horizontally
19905      *
19906      * @see #isHorizontalFadingEdgeEnabled()
19907      *
19908      * @attr ref android.R.styleable#View_requiresFadingEdge
19909      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)19910     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
19911         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
19912             if (horizontalFadingEdgeEnabled) {
19913                 initScrollCache();
19914             }
19915 
19916             mViewFlags ^= FADING_EDGE_HORIZONTAL;
19917         }
19918     }
19919 
19920     /**
19921      * <p>Indicate whether the vertical edges are faded when the view is
19922      * scrolled horizontally.</p>
19923      *
19924      * @return true if the vertical edges should are faded on scroll, false
19925      *         otherwise
19926      *
19927      * @see #setVerticalFadingEdgeEnabled(boolean)
19928      *
19929      * @attr ref android.R.styleable#View_requiresFadingEdge
19930      */
isVerticalFadingEdgeEnabled()19931     public boolean isVerticalFadingEdgeEnabled() {
19932         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
19933     }
19934 
19935     /**
19936      * <p>Define whether the vertical edges should be faded when this view
19937      * is scrolled vertically.</p>
19938      *
19939      * @param verticalFadingEdgeEnabled true if the vertical edges should
19940      *                                  be faded when the view is scrolled
19941      *                                  vertically
19942      *
19943      * @see #isVerticalFadingEdgeEnabled()
19944      *
19945      * @attr ref android.R.styleable#View_requiresFadingEdge
19946      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)19947     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
19948         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
19949             if (verticalFadingEdgeEnabled) {
19950                 initScrollCache();
19951             }
19952 
19953             mViewFlags ^= FADING_EDGE_VERTICAL;
19954         }
19955     }
19956 
19957     /**
19958      * Get the fading edge flags, used for inspection.
19959      *
19960      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
19961      *         or {@link #FADING_EDGE_HORIZONTAL}
19962      * @hide
19963      */
19964     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
19965             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
19966             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
19967             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
19968     })
getFadingEdge()19969     public int getFadingEdge() {
19970         return mViewFlags & FADING_EDGE_MASK;
19971     }
19972 
19973     /**
19974      * Get the fading edge length, used for inspection
19975      *
19976      * @return The fading edge length or 0
19977      * @hide
19978      */
19979     @InspectableProperty
getFadingEdgeLength()19980     public int getFadingEdgeLength() {
19981         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
19982             return mScrollCache.fadingEdgeLength;
19983         }
19984         return 0;
19985     }
19986 
19987     /**
19988      * Returns the strength, or intensity, of the top faded edge. The strength is
19989      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19990      * returns 0.0 or 1.0 but no value in between.
19991      *
19992      * Subclasses should override this method to provide a smoother fade transition
19993      * when scrolling occurs.
19994      *
19995      * @return the intensity of the top fade as a float between 0.0f and 1.0f
19996      */
getTopFadingEdgeStrength()19997     protected float getTopFadingEdgeStrength() {
19998         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
19999     }
20000 
20001     /**
20002      * Returns the strength, or intensity, of the bottom faded edge. The strength is
20003      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20004      * returns 0.0 or 1.0 but no value in between.
20005      *
20006      * Subclasses should override this method to provide a smoother fade transition
20007      * when scrolling occurs.
20008      *
20009      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
20010      */
getBottomFadingEdgeStrength()20011     protected float getBottomFadingEdgeStrength() {
20012         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
20013                 computeVerticalScrollRange() ? 1.0f : 0.0f;
20014     }
20015 
20016     /**
20017      * Returns the strength, or intensity, of the left faded edge. The strength is
20018      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20019      * returns 0.0 or 1.0 but no value in between.
20020      *
20021      * Subclasses should override this method to provide a smoother fade transition
20022      * when scrolling occurs.
20023      *
20024      * @return the intensity of the left fade as a float between 0.0f and 1.0f
20025      */
getLeftFadingEdgeStrength()20026     protected float getLeftFadingEdgeStrength() {
20027         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
20028     }
20029 
20030     /**
20031      * Returns the strength, or intensity, of the right faded edge. The strength is
20032      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20033      * returns 0.0 or 1.0 but no value in between.
20034      *
20035      * Subclasses should override this method to provide a smoother fade transition
20036      * when scrolling occurs.
20037      *
20038      * @return the intensity of the right fade as a float between 0.0f and 1.0f
20039      */
getRightFadingEdgeStrength()20040     protected float getRightFadingEdgeStrength() {
20041         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
20042                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
20043     }
20044 
20045     /**
20046      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
20047      * scrollbar is not drawn by default.</p>
20048      *
20049      * @return true if the horizontal scrollbar should be painted, false
20050      *         otherwise
20051      *
20052      * @see #setHorizontalScrollBarEnabled(boolean)
20053      */
isHorizontalScrollBarEnabled()20054     public boolean isHorizontalScrollBarEnabled() {
20055         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
20056     }
20057 
20058     /**
20059      * <p>Define whether the horizontal scrollbar should be drawn or not. The
20060      * scrollbar is not drawn by default.</p>
20061      *
20062      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
20063      *                                   be painted
20064      *
20065      * @see #isHorizontalScrollBarEnabled()
20066      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)20067     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
20068         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
20069             mViewFlags ^= SCROLLBARS_HORIZONTAL;
20070             computeOpaqueFlags();
20071             resolvePadding();
20072         }
20073     }
20074 
20075     /**
20076      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
20077      * scrollbar is not drawn by default.</p>
20078      *
20079      * @return true if the vertical scrollbar should be painted, false
20080      *         otherwise
20081      *
20082      * @see #setVerticalScrollBarEnabled(boolean)
20083      */
isVerticalScrollBarEnabled()20084     public boolean isVerticalScrollBarEnabled() {
20085         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
20086     }
20087 
20088     /**
20089      * <p>Define whether the vertical scrollbar should be drawn or not. The
20090      * scrollbar is not drawn by default.</p>
20091      *
20092      * @param verticalScrollBarEnabled true if the vertical scrollbar should
20093      *                                 be painted
20094      *
20095      * @see #isVerticalScrollBarEnabled()
20096      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)20097     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
20098         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
20099             mViewFlags ^= SCROLLBARS_VERTICAL;
20100             computeOpaqueFlags();
20101             resolvePadding();
20102         }
20103     }
20104 
20105     /**
20106      * @hide
20107      */
20108     @UnsupportedAppUsage
recomputePadding()20109     protected void recomputePadding() {
20110         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
20111     }
20112 
20113     /**
20114      * Define whether scrollbars will fade when the view is not scrolling.
20115      *
20116      * @param fadeScrollbars whether to enable fading
20117      *
20118      * @attr ref android.R.styleable#View_fadeScrollbars
20119      */
setScrollbarFadingEnabled(boolean fadeScrollbars)20120     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
20121         initScrollCache();
20122         final ScrollabilityCache scrollabilityCache = mScrollCache;
20123         scrollabilityCache.fadeScrollBars = fadeScrollbars;
20124         if (fadeScrollbars) {
20125             scrollabilityCache.state = ScrollabilityCache.OFF;
20126         } else {
20127             scrollabilityCache.state = ScrollabilityCache.ON;
20128         }
20129     }
20130 
20131     /**
20132      *
20133      * Returns true if scrollbars will fade when this view is not scrolling
20134      *
20135      * @return true if scrollbar fading is enabled
20136      *
20137      * @attr ref android.R.styleable#View_fadeScrollbars
20138      */
isScrollbarFadingEnabled()20139     public boolean isScrollbarFadingEnabled() {
20140         return mScrollCache != null && mScrollCache.fadeScrollBars;
20141     }
20142 
20143     /**
20144      *
20145      * Returns the delay before scrollbars fade.
20146      *
20147      * @return the delay before scrollbars fade
20148      *
20149      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
20150      */
20151     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()20152     public int getScrollBarDefaultDelayBeforeFade() {
20153         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
20154                 mScrollCache.scrollBarDefaultDelayBeforeFade;
20155     }
20156 
20157     /**
20158      * Define the delay before scrollbars fade.
20159      *
20160      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
20161      *
20162      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
20163      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)20164     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
20165         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
20166     }
20167 
20168     /**
20169      *
20170      * Returns the scrollbar fade duration.
20171      *
20172      * @return the scrollbar fade duration, in milliseconds
20173      *
20174      * @attr ref android.R.styleable#View_scrollbarFadeDuration
20175      */
20176     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()20177     public int getScrollBarFadeDuration() {
20178         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
20179                 mScrollCache.scrollBarFadeDuration;
20180     }
20181 
20182     /**
20183      * Define the scrollbar fade duration.
20184      *
20185      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
20186      *
20187      * @attr ref android.R.styleable#View_scrollbarFadeDuration
20188      */
setScrollBarFadeDuration(int scrollBarFadeDuration)20189     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
20190         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
20191     }
20192 
20193     /**
20194      *
20195      * Returns the scrollbar size.
20196      *
20197      * @return the scrollbar size
20198      *
20199      * @attr ref android.R.styleable#View_scrollbarSize
20200      */
20201     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()20202     public int getScrollBarSize() {
20203         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
20204                 mScrollCache.scrollBarSize;
20205     }
20206 
20207     /**
20208      * Define the scrollbar size.
20209      *
20210      * @param scrollBarSize - the scrollbar size
20211      *
20212      * @attr ref android.R.styleable#View_scrollbarSize
20213      */
setScrollBarSize(int scrollBarSize)20214     public void setScrollBarSize(int scrollBarSize) {
20215         getScrollCache().scrollBarSize = scrollBarSize;
20216     }
20217 
20218     /**
20219      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
20220      * inset. When inset, they add to the padding of the view. And the scrollbars
20221      * can be drawn inside the padding area or on the edge of the view. For example,
20222      * if a view has a background drawable and you want to draw the scrollbars
20223      * inside the padding specified by the drawable, you can use
20224      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
20225      * appear at the edge of the view, ignoring the padding, then you can use
20226      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
20227      * @param style the style of the scrollbars. Should be one of
20228      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
20229      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
20230      * @see #SCROLLBARS_INSIDE_OVERLAY
20231      * @see #SCROLLBARS_INSIDE_INSET
20232      * @see #SCROLLBARS_OUTSIDE_OVERLAY
20233      * @see #SCROLLBARS_OUTSIDE_INSET
20234      *
20235      * @attr ref android.R.styleable#View_scrollbarStyle
20236      */
setScrollBarStyle(@crollBarStyle int style)20237     public void setScrollBarStyle(@ScrollBarStyle int style) {
20238         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
20239             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
20240             computeOpaqueFlags();
20241             resolvePadding();
20242         }
20243     }
20244 
20245     /**
20246      * <p>Returns the current scrollbar style.</p>
20247      * @return the current scrollbar style
20248      * @see #SCROLLBARS_INSIDE_OVERLAY
20249      * @see #SCROLLBARS_INSIDE_INSET
20250      * @see #SCROLLBARS_OUTSIDE_OVERLAY
20251      * @see #SCROLLBARS_OUTSIDE_INSET
20252      *
20253      * @attr ref android.R.styleable#View_scrollbarStyle
20254      */
20255     @ViewDebug.ExportedProperty(mapping = {
20256             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
20257             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
20258             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
20259             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
20260     })
20261     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
20262             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
20263             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
20264             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
20265             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
20266     })
20267     @ScrollBarStyle
getScrollBarStyle()20268     public int getScrollBarStyle() {
20269         return mViewFlags & SCROLLBARS_STYLE_MASK;
20270     }
20271 
20272     /**
20273      * <p>Compute the horizontal range that the horizontal scrollbar
20274      * represents.</p>
20275      *
20276      * <p>The range is expressed in arbitrary units that must be the same as the
20277      * units used by {@link #computeHorizontalScrollExtent()} and
20278      * {@link #computeHorizontalScrollOffset()}.</p>
20279      *
20280      * <p>The default range is the drawing width of this view.</p>
20281      *
20282      * @return the total horizontal range represented by the horizontal
20283      *         scrollbar
20284      *
20285      * @see #computeHorizontalScrollExtent()
20286      * @see #computeHorizontalScrollOffset()
20287      */
computeHorizontalScrollRange()20288     protected int computeHorizontalScrollRange() {
20289         return getWidth();
20290     }
20291 
20292     /**
20293      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
20294      * within the horizontal range. This value is used to compute the position
20295      * of the thumb within the scrollbar's track.</p>
20296      *
20297      * <p>The range is expressed in arbitrary units that must be the same as the
20298      * units used by {@link #computeHorizontalScrollRange()} and
20299      * {@link #computeHorizontalScrollExtent()}.</p>
20300      *
20301      * <p>The default offset is the scroll offset of this view.</p>
20302      *
20303      * @return the horizontal offset of the scrollbar's thumb
20304      *
20305      * @see #computeHorizontalScrollRange()
20306      * @see #computeHorizontalScrollExtent()
20307      */
computeHorizontalScrollOffset()20308     protected int computeHorizontalScrollOffset() {
20309         return mScrollX;
20310     }
20311 
20312     /**
20313      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
20314      * within the horizontal range. This value is used to compute the length
20315      * of the thumb within the scrollbar's track.</p>
20316      *
20317      * <p>The range is expressed in arbitrary units that must be the same as the
20318      * units used by {@link #computeHorizontalScrollRange()} and
20319      * {@link #computeHorizontalScrollOffset()}.</p>
20320      *
20321      * <p>The default extent is the drawing width of this view.</p>
20322      *
20323      * @return the horizontal extent of the scrollbar's thumb
20324      *
20325      * @see #computeHorizontalScrollRange()
20326      * @see #computeHorizontalScrollOffset()
20327      */
computeHorizontalScrollExtent()20328     protected int computeHorizontalScrollExtent() {
20329         return getWidth();
20330     }
20331 
20332     /**
20333      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
20334      *
20335      * <p>The range is expressed in arbitrary units that must be the same as the
20336      * units used by {@link #computeVerticalScrollExtent()} and
20337      * {@link #computeVerticalScrollOffset()}.</p>
20338      *
20339      * @return the total vertical range represented by the vertical scrollbar
20340      *
20341      * <p>The default range is the drawing height of this view.</p>
20342      *
20343      * @see #computeVerticalScrollExtent()
20344      * @see #computeVerticalScrollOffset()
20345      */
computeVerticalScrollRange()20346     protected int computeVerticalScrollRange() {
20347         return getHeight();
20348     }
20349 
20350     /**
20351      * <p>Compute the vertical offset of the vertical scrollbar's thumb
20352      * within the horizontal range. This value is used to compute the position
20353      * of the thumb within the scrollbar's track.</p>
20354      *
20355      * <p>The range is expressed in arbitrary units that must be the same as the
20356      * units used by {@link #computeVerticalScrollRange()} and
20357      * {@link #computeVerticalScrollExtent()}.</p>
20358      *
20359      * <p>The default offset is the scroll offset of this view.</p>
20360      *
20361      * @return the vertical offset of the scrollbar's thumb
20362      *
20363      * @see #computeVerticalScrollRange()
20364      * @see #computeVerticalScrollExtent()
20365      */
computeVerticalScrollOffset()20366     protected int computeVerticalScrollOffset() {
20367         return mScrollY;
20368     }
20369 
20370     /**
20371      * <p>Compute the vertical extent of the vertical scrollbar's thumb
20372      * within the vertical range. This value is used to compute the length
20373      * of the thumb within the scrollbar's track.</p>
20374      *
20375      * <p>The range is expressed in arbitrary units that must be the same as the
20376      * units used by {@link #computeVerticalScrollRange()} and
20377      * {@link #computeVerticalScrollOffset()}.</p>
20378      *
20379      * <p>The default extent is the drawing height of this view.</p>
20380      *
20381      * @return the vertical extent of the scrollbar's thumb
20382      *
20383      * @see #computeVerticalScrollRange()
20384      * @see #computeVerticalScrollOffset()
20385      */
computeVerticalScrollExtent()20386     protected int computeVerticalScrollExtent() {
20387         return getHeight();
20388     }
20389 
20390     /**
20391      * Check if this view can be scrolled horizontally in a certain direction.
20392      *
20393      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
20394      * in response to user input or not.
20395      *
20396      * @param direction Negative to check scrolling left, positive to check scrolling right.
20397      * @return true if this view can be scrolled in the specified direction, false otherwise.
20398      */
canScrollHorizontally(int direction)20399     public boolean canScrollHorizontally(int direction) {
20400         final int offset = computeHorizontalScrollOffset();
20401         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
20402         if (range == 0) return false;
20403         if (direction < 0) {
20404             return offset > 0;
20405         } else {
20406             return offset < range - 1;
20407         }
20408     }
20409 
20410     /**
20411      * Check if this view can be scrolled vertically in a certain direction.
20412      *
20413      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
20414      * in response to user input or not.
20415      *
20416      * @param direction Negative to check scrolling up, positive to check scrolling down.
20417      * @return true if this view can be scrolled in the specified direction, false otherwise.
20418      */
canScrollVertically(int direction)20419     public boolean canScrollVertically(int direction) {
20420         final int offset = computeVerticalScrollOffset();
20421         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
20422         if (range == 0) return false;
20423         if (direction < 0) {
20424             return offset > 0;
20425         } else {
20426             return offset < range - 1;
20427         }
20428     }
20429 
getScrollIndicatorBounds(@onNull Rect out)20430     void getScrollIndicatorBounds(@NonNull Rect out) {
20431         out.left = mScrollX;
20432         out.right = mScrollX + mRight - mLeft;
20433         out.top = mScrollY;
20434         out.bottom = mScrollY + mBottom - mTop;
20435     }
20436 
onDrawScrollIndicators(Canvas c)20437     private void onDrawScrollIndicators(Canvas c) {
20438         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
20439             // No scroll indicators enabled.
20440             return;
20441         }
20442 
20443         final Drawable dr = mScrollIndicatorDrawable;
20444         if (dr == null) {
20445             // Scroll indicators aren't supported here.
20446             return;
20447         }
20448 
20449         if (mAttachInfo == null) {
20450             // View is not attached.
20451             return;
20452         }
20453 
20454         final int h = dr.getIntrinsicHeight();
20455         final int w = dr.getIntrinsicWidth();
20456         final Rect rect = mAttachInfo.mTmpInvalRect;
20457         getScrollIndicatorBounds(rect);
20458 
20459         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
20460             final boolean canScrollUp = canScrollVertically(-1);
20461             if (canScrollUp) {
20462                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
20463                 dr.draw(c);
20464             }
20465         }
20466 
20467         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
20468             final boolean canScrollDown = canScrollVertically(1);
20469             if (canScrollDown) {
20470                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
20471                 dr.draw(c);
20472             }
20473         }
20474 
20475         final int leftRtl;
20476         final int rightRtl;
20477         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
20478             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
20479             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
20480         } else {
20481             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
20482             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
20483         }
20484 
20485         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
20486         if ((mPrivateFlags3 & leftMask) != 0) {
20487             final boolean canScrollLeft = canScrollHorizontally(-1);
20488             if (canScrollLeft) {
20489                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
20490                 dr.draw(c);
20491             }
20492         }
20493 
20494         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
20495         if ((mPrivateFlags3 & rightMask) != 0) {
20496             final boolean canScrollRight = canScrollHorizontally(1);
20497             if (canScrollRight) {
20498                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
20499                 dr.draw(c);
20500             }
20501         }
20502     }
20503 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)20504     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
20505             @Nullable Rect touchBounds) {
20506         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
20507         if (bounds == null) {
20508             return;
20509         }
20510         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
20511         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
20512                 && !isVerticalScrollBarHidden();
20513         final int size = getHorizontalScrollbarHeight();
20514         final int verticalScrollBarGap = drawVerticalScrollBar ?
20515                 getVerticalScrollbarWidth() : 0;
20516         final int width = mRight - mLeft;
20517         final int height = mBottom - mTop;
20518         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
20519         bounds.left = mScrollX + (mPaddingLeft & inside);
20520         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
20521         bounds.bottom = bounds.top + size;
20522 
20523         if (touchBounds == null) {
20524             return;
20525         }
20526         if (touchBounds != bounds) {
20527             touchBounds.set(bounds);
20528         }
20529         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
20530         if (touchBounds.height() < minTouchTarget) {
20531             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
20532             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
20533             touchBounds.top = touchBounds.bottom - minTouchTarget;
20534         }
20535         if (touchBounds.width() < minTouchTarget) {
20536             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
20537             touchBounds.left -= adjust;
20538             touchBounds.right = touchBounds.left + minTouchTarget;
20539         }
20540     }
20541 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)20542     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
20543         if (mRoundScrollbarRenderer == null) {
20544             getStraightVerticalScrollBarBounds(bounds, touchBounds);
20545         } else {
20546             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
20547         }
20548     }
20549 
getRoundVerticalScrollBarBounds(Rect bounds)20550     private void getRoundVerticalScrollBarBounds(Rect bounds) {
20551         final int width = mRight - mLeft;
20552         final int height = mBottom - mTop;
20553         // Do not take padding into account as we always want the scrollbars
20554         // to hug the screen for round wearable devices.
20555         bounds.left = mScrollX;
20556         bounds.top = mScrollY;
20557         bounds.right = bounds.left + width;
20558         bounds.bottom = mScrollY + height;
20559     }
20560 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)20561     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
20562             @Nullable Rect touchBounds) {
20563         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
20564         if (bounds == null) {
20565             return;
20566         }
20567         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
20568         final int size = getVerticalScrollbarWidth();
20569         int verticalScrollbarPosition = mVerticalScrollbarPosition;
20570         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
20571             verticalScrollbarPosition = isLayoutRtl() ?
20572                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
20573         }
20574         final int width = mRight - mLeft;
20575         final int height = mBottom - mTop;
20576         switch (verticalScrollbarPosition) {
20577             default:
20578             case SCROLLBAR_POSITION_RIGHT:
20579                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
20580                 break;
20581             case SCROLLBAR_POSITION_LEFT:
20582                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
20583                 break;
20584         }
20585         bounds.top = mScrollY + (mPaddingTop & inside);
20586         bounds.right = bounds.left + size;
20587         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
20588 
20589         if (touchBounds == null) {
20590             return;
20591         }
20592         if (touchBounds != bounds) {
20593             touchBounds.set(bounds);
20594         }
20595         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
20596         if (touchBounds.width() < minTouchTarget) {
20597             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
20598             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
20599                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
20600                 touchBounds.left = touchBounds.right - minTouchTarget;
20601             } else {
20602                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
20603                 touchBounds.right = touchBounds.left + minTouchTarget;
20604             }
20605         }
20606         if (touchBounds.height() < minTouchTarget) {
20607             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
20608             touchBounds.top -= adjust;
20609             touchBounds.bottom = touchBounds.top + minTouchTarget;
20610         }
20611     }
20612 
20613     /**
20614      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
20615      * scrollbars are painted only if they have been awakened first.</p>
20616      *
20617      * @param canvas the canvas on which to draw the scrollbars
20618      *
20619      * @see #awakenScrollBars(int)
20620      */
onDrawScrollBars(Canvas canvas)20621     protected final void onDrawScrollBars(Canvas canvas) {
20622         // scrollbars are drawn only when the animation is running
20623         final ScrollabilityCache cache = mScrollCache;
20624 
20625         if (cache != null) {
20626 
20627             int state = cache.state;
20628 
20629             if (state == ScrollabilityCache.OFF) {
20630                 return;
20631             }
20632 
20633             boolean invalidate = false;
20634 
20635             if (state == ScrollabilityCache.FADING) {
20636                 // We're fading -- get our fade interpolation
20637                 if (cache.interpolatorValues == null) {
20638                     cache.interpolatorValues = new float[1];
20639                 }
20640 
20641                 float[] values = cache.interpolatorValues;
20642 
20643                 // Stops the animation if we're done
20644                 if (cache.scrollBarInterpolator.timeToValues(values) ==
20645                         Interpolator.Result.FREEZE_END) {
20646                     cache.state = ScrollabilityCache.OFF;
20647                 } else {
20648                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
20649                 }
20650 
20651                 // This will make the scroll bars inval themselves after
20652                 // drawing. We only want this when we're fading so that
20653                 // we prevent excessive redraws
20654                 invalidate = true;
20655             } else {
20656                 // We're just on -- but we may have been fading before so
20657                 // reset alpha
20658                 cache.scrollBar.mutate().setAlpha(255);
20659             }
20660 
20661             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
20662             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
20663                     && !isVerticalScrollBarHidden();
20664 
20665             // Fork out the scroll bar drawing for round wearable devices.
20666             if (mRoundScrollbarRenderer != null) {
20667                 if (drawVerticalScrollBar) {
20668                     final Rect bounds = cache.mScrollBarBounds;
20669                     getVerticalScrollBarBounds(bounds, null);
20670                     mRoundScrollbarRenderer.drawRoundScrollbars(
20671                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
20672                     if (invalidate) {
20673                         invalidate();
20674                     }
20675                 }
20676                 // Do not draw horizontal scroll bars for round wearable devices.
20677             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
20678                 final ScrollBarDrawable scrollBar = cache.scrollBar;
20679 
20680                 if (drawHorizontalScrollBar) {
20681                     scrollBar.setParameters(computeHorizontalScrollRange(),
20682                             computeHorizontalScrollOffset(),
20683                             computeHorizontalScrollExtent(), false);
20684                     final Rect bounds = cache.mScrollBarBounds;
20685                     getHorizontalScrollBarBounds(bounds, null);
20686                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
20687                             bounds.right, bounds.bottom);
20688                     if (invalidate) {
20689                         invalidate(bounds);
20690                     }
20691                 }
20692 
20693                 if (drawVerticalScrollBar) {
20694                     scrollBar.setParameters(computeVerticalScrollRange(),
20695                             computeVerticalScrollOffset(),
20696                             computeVerticalScrollExtent(), true);
20697                     final Rect bounds = cache.mScrollBarBounds;
20698                     getVerticalScrollBarBounds(bounds, null);
20699                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
20700                             bounds.right, bounds.bottom);
20701                     if (invalidate) {
20702                         invalidate(bounds);
20703                     }
20704                 }
20705             }
20706         }
20707     }
20708 
20709     /**
20710      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
20711      * FastScroller is visible.
20712      * @return whether to temporarily hide the vertical scrollbar
20713      * @hide
20714      */
isVerticalScrollBarHidden()20715     protected boolean isVerticalScrollBarHidden() {
20716         return false;
20717     }
20718 
20719     /**
20720      * <p>Draw the horizontal scrollbar if
20721      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
20722      *
20723      * @param canvas the canvas on which to draw the scrollbar
20724      * @param scrollBar the scrollbar's drawable
20725      *
20726      * @see #isHorizontalScrollBarEnabled()
20727      * @see #computeHorizontalScrollRange()
20728      * @see #computeHorizontalScrollExtent()
20729      * @see #computeHorizontalScrollOffset()
20730      * @hide
20731      */
20732     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)20733     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
20734             int l, int t, int r, int b) {
20735         scrollBar.setBounds(l, t, r, b);
20736         scrollBar.draw(canvas);
20737     }
20738 
20739     /**
20740      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
20741      * returns true.</p>
20742      *
20743      * @param canvas the canvas on which to draw the scrollbar
20744      * @param scrollBar the scrollbar's drawable
20745      *
20746      * @see #isVerticalScrollBarEnabled()
20747      * @see #computeVerticalScrollRange()
20748      * @see #computeVerticalScrollExtent()
20749      * @see #computeVerticalScrollOffset()
20750      * @hide
20751      */
20752     @UnsupportedAppUsage
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)20753     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
20754             int l, int t, int r, int b) {
20755         scrollBar.setBounds(l, t, r, b);
20756         scrollBar.draw(canvas);
20757     }
20758 
20759     /**
20760      * Implement this to do your drawing.
20761      *
20762      * @param canvas the canvas on which the background will be drawn
20763      */
onDraw(Canvas canvas)20764     protected void onDraw(Canvas canvas) {
20765     }
20766 
20767     /*
20768      * Caller is responsible for calling requestLayout if necessary.
20769      * (This allows addViewInLayout to not request a new layout.)
20770      */
20771     @UnsupportedAppUsage
assignParent(ViewParent parent)20772     void assignParent(ViewParent parent) {
20773         if (mParent == null) {
20774             mParent = parent;
20775         } else if (parent == null) {
20776             mParent = null;
20777         } else {
20778             throw new RuntimeException("view " + this + " being added, but"
20779                     + " it already has a parent");
20780         }
20781     }
20782 
20783     /**
20784      * This is called when the view is attached to a window.  At this point it
20785      * has a Surface and will start drawing.  Note that this function is
20786      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
20787      * however it may be called any time before the first onDraw -- including
20788      * before or after {@link #onMeasure(int, int)}.
20789      *
20790      * @see #onDetachedFromWindow()
20791      */
20792     @CallSuper
onAttachedToWindow()20793     protected void onAttachedToWindow() {
20794         if (mParent != null && (mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
20795             mParent.requestTransparentRegion(this);
20796         }
20797 
20798         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
20799 
20800         jumpDrawablesToCurrentState();
20801 
20802         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
20803         resetSubtreeAccessibilityStateChanged();
20804 
20805         // rebuild, since Outline not maintained while View is detached
20806         rebuildOutline();
20807 
20808         if (isFocused()) {
20809             notifyFocusChangeToImeFocusController(true /* hasFocus */);
20810         }
20811 
20812         if (sTraceLayoutSteps) {
20813             setTraversalTracingEnabled(true);
20814         }
20815         if (sTraceRequestLayoutClass != null
20816                 && sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
20817             setRelayoutTracingEnabled(true);
20818         }
20819     }
20820 
20821     /**
20822      * Resolve all RTL related properties.
20823      *
20824      * @return true if resolution of RTL properties has been done
20825      *
20826      * @hide
20827      */
resolveRtlPropertiesIfNeeded()20828     public boolean resolveRtlPropertiesIfNeeded() {
20829         if (!needRtlPropertiesResolution()) return false;
20830 
20831         // Order is important here: LayoutDirection MUST be resolved first
20832         if (!isLayoutDirectionResolved()) {
20833             resolveLayoutDirection();
20834             resolveLayoutParams();
20835         }
20836         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
20837         if (!isTextDirectionResolved()) {
20838             resolveTextDirection();
20839         }
20840         if (!isTextAlignmentResolved()) {
20841             resolveTextAlignment();
20842         }
20843         // Should resolve Drawables before Padding because we need the layout direction of the
20844         // Drawable to correctly resolve Padding.
20845         if (!areDrawablesResolved()) {
20846             resolveDrawables();
20847         }
20848         if (!isPaddingResolved()) {
20849             resolvePadding();
20850         }
20851         onRtlPropertiesChanged(getLayoutDirection());
20852         return true;
20853     }
20854 
20855     /**
20856      * Reset resolution of all RTL related properties.
20857      *
20858      * @hide
20859      */
20860     @TestApi
resetRtlProperties()20861     public void resetRtlProperties() {
20862         resetResolvedLayoutDirection();
20863         resetResolvedTextDirection();
20864         resetResolvedTextAlignment();
20865         resetResolvedPadding();
20866         resetResolvedDrawables();
20867     }
20868 
20869     /**
20870      * @see #onScreenStateChanged(int)
20871      */
dispatchScreenStateChanged(int screenState)20872     void dispatchScreenStateChanged(int screenState) {
20873         onScreenStateChanged(screenState);
20874     }
20875 
20876     /**
20877      * This method is called whenever the state of the screen this view is
20878      * attached to changes. A state change will usually occurs when the screen
20879      * turns on or off (whether it happens automatically or the user does it
20880      * manually.)
20881      *
20882      * @param screenState The new state of the screen. Can be either
20883      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
20884      */
onScreenStateChanged(int screenState)20885     public void onScreenStateChanged(int screenState) {
20886     }
20887 
20888     /**
20889      * @see #onMovedToDisplay(int, Configuration)
20890      */
dispatchMovedToDisplay(Display display, Configuration config)20891     void dispatchMovedToDisplay(Display display, Configuration config) {
20892         mAttachInfo.mDisplay = display;
20893         mAttachInfo.mDisplayState = display.getState();
20894         onMovedToDisplay(display.getDisplayId(), config);
20895     }
20896 
20897     /**
20898      * Called by the system when the hosting activity is moved from one display to another without
20899      * recreation. This means that the activity is declared to handle all changes to configuration
20900      * that happened when it was switched to another display, so it wasn't destroyed and created
20901      * again.
20902      *
20903      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
20904      * applied configuration actually changed. It is up to app developer to choose whether to handle
20905      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
20906      * call.
20907      *
20908      * <p>Use this callback to track changes to the displays if some functionality relies on an
20909      * association with some display properties.
20910      *
20911      * @param displayId The id of the display to which the view was moved.
20912      * @param config Configuration of the resources on new display after move.
20913      *
20914      * @see #onConfigurationChanged(Configuration)
20915      * @hide
20916      */
onMovedToDisplay(int displayId, Configuration config)20917     public void onMovedToDisplay(int displayId, Configuration config) {
20918     }
20919 
20920     /**
20921      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
20922      */
20923     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hasRtlSupport()20924     private boolean hasRtlSupport() {
20925         return mContext.getApplicationInfo().hasRtlSupport();
20926     }
20927 
20928     /**
20929      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
20930      * RTL not supported)
20931      */
isRtlCompatibilityMode()20932     private boolean isRtlCompatibilityMode() {
20933         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
20934         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
20935     }
20936 
20937     /**
20938      * @return true if RTL properties need resolution.
20939      *
20940      */
needRtlPropertiesResolution()20941     private boolean needRtlPropertiesResolution() {
20942         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
20943     }
20944 
20945     /**
20946      * Called when any RTL property (layout direction or text direction or text alignment) has
20947      * been changed.
20948      *
20949      * Subclasses need to override this method to take care of cached information that depends on the
20950      * resolved layout direction, or to inform child views that inherit their layout direction.
20951      *
20952      * The default implementation does nothing.
20953      *
20954      * @param layoutDirection the direction of the layout
20955      *
20956      * @see #LAYOUT_DIRECTION_LTR
20957      * @see #LAYOUT_DIRECTION_RTL
20958      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)20959     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
20960     }
20961 
20962     /**
20963      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
20964      * that the parent directionality can and will be resolved before its children.
20965      *
20966      * @return true if resolution has been done, false otherwise.
20967      *
20968      * @hide
20969      */
resolveLayoutDirection()20970     public boolean resolveLayoutDirection() {
20971         // Clear any previous layout direction resolution
20972         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20973 
20974         if (hasRtlSupport()) {
20975             // Set resolved depending on layout direction
20976             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
20977                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
20978                 case LAYOUT_DIRECTION_INHERIT:
20979                     // We cannot resolve yet. LTR is by default and let the resolution happen again
20980                     // later to get the correct resolved value
20981                     if (!canResolveLayoutDirection()) return false;
20982 
20983                     // Parent has not yet resolved, LTR is still the default
20984                     try {
20985                         if (!mParent.isLayoutDirectionResolved()) return false;
20986 
20987                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
20988                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20989                         }
20990                     } catch (AbstractMethodError e) {
20991                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20992                                 " does not fully implement ViewParent", e);
20993                     }
20994                     break;
20995                 case LAYOUT_DIRECTION_RTL:
20996                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20997                     break;
20998                 case LAYOUT_DIRECTION_LOCALE:
20999                     if((LAYOUT_DIRECTION_RTL ==
21000                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
21001                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
21002                     }
21003                     break;
21004                 default:
21005                     // Nothing to do, LTR by default
21006             }
21007         }
21008 
21009         // Set to resolved
21010         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
21011         return true;
21012     }
21013 
21014     /**
21015      * Check if layout direction resolution can be done.
21016      *
21017      * @return true if layout direction resolution can be done otherwise return false.
21018      */
canResolveLayoutDirection()21019     public boolean canResolveLayoutDirection() {
21020         switch (getRawLayoutDirection()) {
21021             case LAYOUT_DIRECTION_INHERIT:
21022                 if (mParent != null) {
21023                     try {
21024                         return mParent.canResolveLayoutDirection();
21025                     } catch (AbstractMethodError e) {
21026                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21027                                 " does not fully implement ViewParent", e);
21028                     }
21029                 }
21030                 return false;
21031 
21032             default:
21033                 return true;
21034         }
21035     }
21036 
21037     /**
21038      * Reset the resolved layout direction. Layout direction will be resolved during a call to
21039      * {@link #onMeasure(int, int)}.
21040      *
21041      * @hide
21042      */
21043     @TestApi
resetResolvedLayoutDirection()21044     public void resetResolvedLayoutDirection() {
21045         // Reset the current resolved bits
21046         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
21047     }
21048 
21049     /**
21050      * @return true if the layout direction is inherited.
21051      *
21052      * @hide
21053      */
isLayoutDirectionInherited()21054     public boolean isLayoutDirectionInherited() {
21055         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
21056     }
21057 
21058     /**
21059      * @return true if layout direction has been resolved.
21060      */
isLayoutDirectionResolved()21061     public boolean isLayoutDirectionResolved() {
21062         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
21063     }
21064 
21065     /**
21066      * Return if padding has been resolved
21067      *
21068      * @hide
21069      */
21070     @UnsupportedAppUsage
isPaddingResolved()21071     boolean isPaddingResolved() {
21072         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
21073     }
21074 
21075     /**
21076      * Resolves padding depending on layout direction, if applicable, and
21077      * recomputes internal padding values to adjust for scroll bars.
21078      *
21079      * @hide
21080      */
21081     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resolvePadding()21082     public void resolvePadding() {
21083         final int resolvedLayoutDirection = getLayoutDirection();
21084 
21085         if (!isRtlCompatibilityMode()) {
21086             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
21087             // If start / end padding are defined, they will be resolved (hence overriding) to
21088             // left / right or right / left depending on the resolved layout direction.
21089             // If start / end padding are not defined, use the left / right ones.
21090             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
21091                 Rect padding = sThreadLocal.get();
21092                 if (padding == null) {
21093                     padding = new Rect();
21094                     sThreadLocal.set(padding);
21095                 }
21096                 mBackground.getPadding(padding);
21097                 if (!mLeftPaddingDefined) {
21098                     mUserPaddingLeftInitial = padding.left;
21099                 }
21100                 if (!mRightPaddingDefined) {
21101                     mUserPaddingRightInitial = padding.right;
21102                 }
21103             }
21104             switch (resolvedLayoutDirection) {
21105                 case LAYOUT_DIRECTION_RTL:
21106                     if (mUserPaddingStart != UNDEFINED_PADDING) {
21107                         mUserPaddingRight = mUserPaddingStart;
21108                     } else {
21109                         mUserPaddingRight = mUserPaddingRightInitial;
21110                     }
21111                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
21112                         mUserPaddingLeft = mUserPaddingEnd;
21113                     } else {
21114                         mUserPaddingLeft = mUserPaddingLeftInitial;
21115                     }
21116                     break;
21117                 case LAYOUT_DIRECTION_LTR:
21118                 default:
21119                     if (mUserPaddingStart != UNDEFINED_PADDING) {
21120                         mUserPaddingLeft = mUserPaddingStart;
21121                     } else {
21122                         mUserPaddingLeft = mUserPaddingLeftInitial;
21123                     }
21124                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
21125                         mUserPaddingRight = mUserPaddingEnd;
21126                     } else {
21127                         mUserPaddingRight = mUserPaddingRightInitial;
21128                     }
21129             }
21130 
21131             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
21132         }
21133 
21134         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
21135         onRtlPropertiesChanged(resolvedLayoutDirection);
21136 
21137         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
21138     }
21139 
21140     /**
21141      * Reset the resolved layout direction.
21142      *
21143      * @hide
21144      */
21145     @TestApi
resetResolvedPadding()21146     public void resetResolvedPadding() {
21147         resetResolvedPaddingInternal();
21148     }
21149 
21150     /**
21151      * Used when we only want to reset *this* view's padding and not trigger overrides
21152      * in ViewGroup that reset children too.
21153      */
resetResolvedPaddingInternal()21154     void resetResolvedPaddingInternal() {
21155         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
21156     }
21157 
21158     /**
21159      * This is called when the view is detached from a window.  At this point it
21160      * no longer has a surface for drawing.
21161      *
21162      * @see #onAttachedToWindow()
21163      */
21164     @CallSuper
onDetachedFromWindow()21165     protected void onDetachedFromWindow() {
21166     }
21167 
21168     /**
21169      * This is a framework-internal mirror of onDetachedFromWindow() that's called
21170      * after onDetachedFromWindow().
21171      *
21172      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
21173      * The super method should be called at the end of the overridden method to ensure
21174      * subclasses are destroyed first
21175      *
21176      * @hide
21177      */
21178     @CallSuper
21179     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDetachedFromWindowInternal()21180     protected void onDetachedFromWindowInternal() {
21181         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
21182         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
21183         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
21184 
21185         removeUnsetPressCallback();
21186         removeLongPressCallback();
21187         removePerformClickCallback();
21188         clearAccessibilityThrottles();
21189         stopNestedScroll();
21190 
21191         // Anything that started animating right before detach should already
21192         // be in its final state when re-attached.
21193         jumpDrawablesToCurrentState();
21194 
21195         destroyDrawingCache();
21196 
21197         cleanupDraw();
21198         mCurrentAnimation = null;
21199 
21200         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
21201             hideTooltip();
21202         }
21203 
21204         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
21205 
21206         if (mBackgroundRenderNode != null) {
21207             mBackgroundRenderNode.forceEndAnimators();
21208         }
21209         mRenderNode.forceEndAnimators();
21210     }
21211 
cleanupDraw()21212     private void cleanupDraw() {
21213         resetDisplayList();
21214         if (mAttachInfo != null) {
21215             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
21216         }
21217     }
21218 
invalidateInheritedLayoutMode(int layoutModeOfRoot)21219     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
21220     }
21221 
21222     /**
21223      * @return The number of times this view has been attached to a window
21224      */
getWindowAttachCount()21225     protected int getWindowAttachCount() {
21226         return mWindowAttachCount;
21227     }
21228 
21229     /**
21230      * Retrieve a unique token identifying the window this view is attached to.
21231      * @return Return the window's token for use in
21232      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
21233      */
getWindowToken()21234     public IBinder getWindowToken() {
21235         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
21236     }
21237 
21238     /**
21239      * Retrieve the {@link WindowId} for the window this view is
21240      * currently attached to.
21241      */
getWindowId()21242     public WindowId getWindowId() {
21243         AttachInfo ai = mAttachInfo;
21244         if (ai == null) {
21245             return null;
21246         }
21247         if (ai.mWindowId == null) {
21248             try {
21249                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
21250                 if (ai.mIWindowId != null) {
21251                     ai.mWindowId = new WindowId(ai.mIWindowId);
21252                 }
21253             } catch (RemoteException e) {
21254             }
21255         }
21256         return ai.mWindowId;
21257     }
21258 
21259     /**
21260      * Retrieve a unique token identifying the top-level "real" window of
21261      * the window that this view is attached to.  That is, this is like
21262      * {@link #getWindowToken}, except if the window this view in is a panel
21263      * window (attached to another containing window), then the token of
21264      * the containing window is returned instead.
21265      *
21266      * @return Returns the associated window token, either
21267      * {@link #getWindowToken()} or the containing window's token.
21268      */
getApplicationWindowToken()21269     public IBinder getApplicationWindowToken() {
21270         AttachInfo ai = mAttachInfo;
21271         if (ai != null) {
21272             IBinder appWindowToken = ai.mPanelParentWindowToken;
21273             if (appWindowToken == null) {
21274                 appWindowToken = ai.mWindowToken;
21275             }
21276             return appWindowToken;
21277         }
21278         return null;
21279     }
21280 
21281     /**
21282      * Gets the logical display to which the view's window has been attached.
21283      *
21284      * @return The logical display, or null if the view is not currently attached to a window.
21285      */
getDisplay()21286     public Display getDisplay() {
21287         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
21288     }
21289 
21290     /**
21291      * Retrieve private session object this view hierarchy is using to
21292      * communicate with the window manager.
21293      * @return the session object to communicate with the window manager
21294      */
21295     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()21296     /*package*/ IWindowSession getWindowSession() {
21297         return mAttachInfo != null ? mAttachInfo.mSession : null;
21298     }
21299 
21300     /**
21301      * Return the window this view is currently attached to.
21302      * @hide
21303      */
getWindow()21304     protected IWindow getWindow() {
21305         return mAttachInfo != null ? mAttachInfo.mWindow : null;
21306     }
21307 
21308     /**
21309      * Return the visibility value of the least visible component passed.
21310      */
combineVisibility(int vis1, int vis2)21311     int combineVisibility(int vis1, int vis2) {
21312         // This works because VISIBLE < INVISIBLE < GONE.
21313         return Math.max(vis1, vis2);
21314     }
21315 
21316     private boolean mShouldFakeFocus = false;
21317 
21318     /**
21319      * Fake send a focus event after attaching to window.
21320      * See {@link android.view.ViewRootImpl#dispatchCompatFakeFocus()} for details.
21321      * @hide
21322      */
fakeFocusAfterAttachingToWindow()21323     public void fakeFocusAfterAttachingToWindow() {
21324         mShouldFakeFocus = true;
21325     }
21326 
21327     /**
21328      * @param info the {@link android.view.View.AttachInfo} to associated with
21329      *        this view
21330      */
21331     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)21332     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
21333         mAttachInfo = info;
21334         if (mOverlay != null) {
21335             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
21336         }
21337         mWindowAttachCount++;
21338         // We will need to evaluate the drawable state at least once.
21339         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
21340         if (mFloatingTreeObserver != null) {
21341             info.mTreeObserver.merge(mFloatingTreeObserver);
21342             mFloatingTreeObserver = null;
21343         }
21344 
21345         registerPendingFrameMetricsObservers();
21346 
21347         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
21348             mAttachInfo.mScrollContainers.add(this);
21349             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
21350         }
21351         // Transfer all pending runnables.
21352         if (mRunQueue != null) {
21353             mRunQueue.executeActions(info.mHandler);
21354             mRunQueue = null;
21355         }
21356         performCollectViewAttributes(mAttachInfo, visibility);
21357         onAttachedToWindow();
21358 
21359         ListenerInfo li = mListenerInfo;
21360         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
21361                 li != null ? li.mOnAttachStateChangeListeners : null;
21362         if (listeners != null && listeners.size() > 0) {
21363             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
21364             // perform the dispatching. The iterator is a safe guard against listeners that
21365             // could mutate the list by calling the various add/remove methods. This prevents
21366             // the array from being modified while we iterate it.
21367             for (OnAttachStateChangeListener listener : listeners) {
21368                 listener.onViewAttachedToWindow(this);
21369             }
21370         }
21371 
21372         int vis = info.mWindowVisibility;
21373         if (vis != GONE) {
21374             onWindowVisibilityChanged(vis);
21375             if (isShown()) {
21376                 // Calling onVisibilityAggregated directly here since the subtree will also
21377                 // receive dispatchAttachedToWindow and this same call
21378                 onVisibilityAggregated(vis == VISIBLE);
21379             }
21380         }
21381 
21382         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
21383         // As all views in the subtree will already receive dispatchAttachedToWindow
21384         // traversing the subtree again here is not desired.
21385         onVisibilityChanged(this, visibility);
21386 
21387         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
21388             // If nobody has evaluated the drawable state yet, then do it now.
21389             refreshDrawableState();
21390         }
21391         needGlobalAttributesUpdate(false);
21392 
21393         notifyEnterOrExitForAutoFillIfNeeded(true);
21394         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
21395 
21396         if (mShouldFakeFocus) {
21397             getViewRootImpl().dispatchCompatFakeFocus();
21398             mShouldFakeFocus = false;
21399         }
21400     }
21401 
21402     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()21403     void dispatchDetachedFromWindow() {
21404         AttachInfo info = mAttachInfo;
21405         if (info != null) {
21406             int vis = info.mWindowVisibility;
21407             if (vis != GONE) {
21408                 onWindowVisibilityChanged(GONE);
21409                 if (isShown()) {
21410                     // Invoking onVisibilityAggregated directly here since the subtree
21411                     // will also receive detached from window
21412                     onVisibilityAggregated(false);
21413                 }
21414             }
21415         }
21416 
21417         onDetachedFromWindow();
21418         onDetachedFromWindowInternal();
21419 
21420         if (info != null) {
21421             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
21422         }
21423 
21424         ListenerInfo li = mListenerInfo;
21425         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
21426                 li != null ? li.mOnAttachStateChangeListeners : null;
21427         if (listeners != null && listeners.size() > 0) {
21428             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
21429             // perform the dispatching. The iterator is a safe guard against listeners that
21430             // could mutate the list by calling the various add/remove methods. This prevents
21431             // the array from being modified while we iterate it.
21432             for (OnAttachStateChangeListener listener : listeners) {
21433                 listener.onViewDetachedFromWindow(this);
21434             }
21435         }
21436 
21437         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
21438             mAttachInfo.mScrollContainers.remove(this);
21439             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
21440         }
21441 
21442         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
21443 
21444         mAttachInfo = null;
21445         if (mOverlay != null) {
21446             mOverlay.getOverlayView().dispatchDetachedFromWindow();
21447         }
21448 
21449         notifyEnterOrExitForAutoFillIfNeeded(false);
21450 
21451         if (info != null && !collectPreferKeepClearRects().isEmpty()) {
21452             info.mViewRootImpl.updateKeepClearRectsForView(this);
21453         }
21454     }
21455 
21456     /**
21457      * Cancel any deferred high-level input events that were previously posted to the event queue.
21458      *
21459      * <p>Many views post high-level events such as click handlers to the event queue
21460      * to run deferred in order to preserve a desired user experience - clearing visible
21461      * pressed states before executing, etc. This method will abort any events of this nature
21462      * that are currently in flight.</p>
21463      *
21464      * <p>Custom views that generate their own high-level deferred input events should override
21465      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
21466      *
21467      * <p>This will also cancel pending input events for any child views.</p>
21468      *
21469      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
21470      * This will not impact newer events posted after this call that may occur as a result of
21471      * lower-level input events still waiting in the queue. If you are trying to prevent
21472      * double-submitted  events for the duration of some sort of asynchronous transaction
21473      * you should also take other steps to protect against unexpected double inputs e.g. calling
21474      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
21475      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
21476      */
cancelPendingInputEvents()21477     public final void cancelPendingInputEvents() {
21478         dispatchCancelPendingInputEvents();
21479     }
21480 
21481     /**
21482      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
21483      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
21484      */
dispatchCancelPendingInputEvents()21485     void dispatchCancelPendingInputEvents() {
21486         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
21487         onCancelPendingInputEvents();
21488         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
21489             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
21490                     " did not call through to super.onCancelPendingInputEvents()");
21491         }
21492     }
21493 
21494     /**
21495      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
21496      * a parent view.
21497      *
21498      * <p>This method is responsible for removing any pending high-level input events that were
21499      * posted to the event queue to run later. Custom view classes that post their own deferred
21500      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
21501      * {@link android.os.Handler} should override this method, call
21502      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
21503      * </p>
21504      */
onCancelPendingInputEvents()21505     public void onCancelPendingInputEvents() {
21506         removePerformClickCallback();
21507         cancelLongPress();
21508         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
21509     }
21510 
21511     /**
21512      * Store this view hierarchy's frozen state into the given container.
21513      *
21514      * @param container The SparseArray in which to save the view's state.
21515      *
21516      * @see #restoreHierarchyState(android.util.SparseArray)
21517      * @see #dispatchSaveInstanceState(android.util.SparseArray)
21518      * @see #onSaveInstanceState()
21519      */
saveHierarchyState(SparseArray<Parcelable> container)21520     public void saveHierarchyState(SparseArray<Parcelable> container) {
21521         dispatchSaveInstanceState(container);
21522     }
21523 
21524     /**
21525      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
21526      * this view and its children. May be overridden to modify how freezing happens to a
21527      * view's children; for example, some views may want to not store state for their children.
21528      *
21529      * @param container The SparseArray in which to save the view's state.
21530      *
21531      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
21532      * @see #saveHierarchyState(android.util.SparseArray)
21533      * @see #onSaveInstanceState()
21534      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)21535     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
21536         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
21537             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
21538             Parcelable state = onSaveInstanceState();
21539             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
21540                 throw new IllegalStateException(
21541                         "Derived class did not call super.onSaveInstanceState()");
21542             }
21543             if (state != null) {
21544                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
21545                 // + ": " + state);
21546                 container.put(mID, state);
21547             }
21548         }
21549     }
21550 
21551     /**
21552      * Hook allowing a view to generate a representation of its internal state
21553      * that can later be used to create a new instance with that same state.
21554      * This state should only contain information that is not persistent or can
21555      * not be reconstructed later. For example, you will never store your
21556      * current position on screen because that will be computed again when a
21557      * new instance of the view is placed in its view hierarchy.
21558      * <p>
21559      * Some examples of things you may store here: the current cursor position
21560      * in a text view (but usually not the text itself since that is stored in a
21561      * content provider or other persistent storage), the currently selected
21562      * item in a list view.
21563      *
21564      * @return Returns a Parcelable object containing the view's current dynamic
21565      *         state, or null if there is nothing interesting to save.
21566      * @see #onRestoreInstanceState(Parcelable)
21567      * @see #saveHierarchyState(SparseArray)
21568      * @see #dispatchSaveInstanceState(SparseArray)
21569      * @see #setSaveEnabled(boolean)
21570      */
21571     @CallSuper
onSaveInstanceState()21572     @Nullable protected Parcelable onSaveInstanceState() {
21573         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
21574         if (mStartActivityRequestWho != null || isAutofilled()
21575                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
21576             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
21577 
21578             if (mStartActivityRequestWho != null) {
21579                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
21580             }
21581 
21582             if (isAutofilled()) {
21583                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
21584             }
21585 
21586             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
21587                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
21588             }
21589 
21590             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
21591             state.mIsAutofilled = isAutofilled();
21592             state.mHideHighlight = hideAutofillHighlight();
21593             state.mAutofillViewId = mAutofillViewId;
21594             return state;
21595         }
21596         return BaseSavedState.EMPTY_STATE;
21597     }
21598 
21599     /**
21600      * Restore this view hierarchy's frozen state from the given container.
21601      *
21602      * @param container The SparseArray which holds previously frozen states.
21603      *
21604      * @see #saveHierarchyState(android.util.SparseArray)
21605      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
21606      * @see #onRestoreInstanceState(android.os.Parcelable)
21607      */
restoreHierarchyState(SparseArray<Parcelable> container)21608     public void restoreHierarchyState(SparseArray<Parcelable> container) {
21609         dispatchRestoreInstanceState(container);
21610     }
21611 
21612     /**
21613      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
21614      * state for this view and its children. May be overridden to modify how restoring
21615      * happens to a view's children; for example, some views may want to not store state
21616      * for their children.
21617      *
21618      * @param container The SparseArray which holds previously saved state.
21619      *
21620      * @see #dispatchSaveInstanceState(android.util.SparseArray)
21621      * @see #restoreHierarchyState(android.util.SparseArray)
21622      * @see #onRestoreInstanceState(android.os.Parcelable)
21623      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)21624     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
21625         if (mID != NO_ID) {
21626             Parcelable state = container.get(mID);
21627             if (state != null) {
21628                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
21629                 // + ": " + state);
21630                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
21631                 onRestoreInstanceState(state);
21632                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
21633                     throw new IllegalStateException(
21634                             "Derived class did not call super.onRestoreInstanceState()");
21635                 }
21636             }
21637         }
21638     }
21639 
21640     /**
21641      * Hook allowing a view to re-apply a representation of its internal state that had previously
21642      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
21643      * null state.
21644      *
21645      * @param state The frozen state that had previously been returned by
21646      *        {@link #onSaveInstanceState}.
21647      *
21648      * @see #onSaveInstanceState()
21649      * @see #restoreHierarchyState(android.util.SparseArray)
21650      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
21651      */
21652     @CallSuper
onRestoreInstanceState(Parcelable state)21653     protected void onRestoreInstanceState(Parcelable state) {
21654         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
21655         if (state != null && !(state instanceof AbsSavedState)) {
21656             throw new IllegalArgumentException("Wrong state class, expecting View State but "
21657                     + "received " + state.getClass().toString() + " instead. This usually happens "
21658                     + "when two views of different type have the same id in the same hierarchy. "
21659                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
21660                     + "other views do not use the same id.");
21661         }
21662         if (state != null && state instanceof BaseSavedState) {
21663             BaseSavedState baseState = (BaseSavedState) state;
21664 
21665             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
21666                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
21667             }
21668             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
21669                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
21670             }
21671             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
21672                 // It can happen that views have the same view id and the restoration path will not
21673                 // be able to distinguish between them. The autofill id needs to be unique though.
21674                 // Hence prevent the same autofill view id from being restored multiple times.
21675                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
21676 
21677                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
21678                     // Ignore when view already set it through setAutofillId();
21679                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
21680                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
21681                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
21682                                 + " it to " + mAutofillId);
21683                     }
21684                 } else {
21685                     mAutofillViewId = baseState.mAutofillViewId;
21686                     mAutofillId = null; // will be set on demand by getAutofillId()
21687                 }
21688             }
21689         }
21690     }
21691 
21692     /**
21693      * <p>Return the time at which the drawing of the view hierarchy started.</p>
21694      *
21695      * @return the drawing start time in milliseconds
21696      */
getDrawingTime()21697     public long getDrawingTime() {
21698         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
21699     }
21700 
21701     /**
21702      * <p>Enables or disables the duplication of the parent's state into this view. When
21703      * duplication is enabled, this view gets its drawable state from its parent rather
21704      * than from its own internal properties.</p>
21705      *
21706      * <p>Note: in the current implementation, setting this property to true after the
21707      * view was added to a ViewGroup might have no effect at all. This property should
21708      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
21709      *
21710      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
21711      * property is enabled, an exception will be thrown.</p>
21712      *
21713      * <p>Note: if the child view uses and updates additional states which are unknown to the
21714      * parent, these states should not be affected by this method.</p>
21715      *
21716      * @param enabled True to enable duplication of the parent's drawable state, false
21717      *                to disable it.
21718      *
21719      * @see #getDrawableState()
21720      * @see #isDuplicateParentStateEnabled()
21721      */
setDuplicateParentStateEnabled(boolean enabled)21722     public void setDuplicateParentStateEnabled(boolean enabled) {
21723         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
21724     }
21725 
21726     /**
21727      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
21728      *
21729      * @return True if this view's drawable state is duplicated from the parent,
21730      *         false otherwise
21731      *
21732      * @see #getDrawableState()
21733      * @see #setDuplicateParentStateEnabled(boolean)
21734      */
21735     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()21736     public boolean isDuplicateParentStateEnabled() {
21737         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
21738     }
21739 
21740     /**
21741      * <p>Specifies the type of layer backing this view. The layer can be
21742      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21743      * {@link #LAYER_TYPE_HARDWARE}.</p>
21744      *
21745      * <p>A layer is associated with an optional {@link android.graphics.Paint}
21746      * instance that controls how the layer is composed on screen. The following
21747      * properties of the paint are taken into account when composing the layer:</p>
21748      * <ul>
21749      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
21750      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
21751      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
21752      * </ul>
21753      *
21754      * <p>If this view has an alpha value set to < 1.0 by calling
21755      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
21756      * by this view's alpha value.</p>
21757      *
21758      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
21759      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
21760      * for more information on when and how to use layers.</p>
21761      *
21762      * @param layerType The type of layer to use with this view, must be one of
21763      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21764      *        {@link #LAYER_TYPE_HARDWARE}
21765      * @param paint The paint used to compose the layer. This argument is optional
21766      *        and can be null. It is ignored when the layer type is
21767      *        {@link #LAYER_TYPE_NONE}
21768      *
21769      * @see #getLayerType()
21770      * @see #LAYER_TYPE_NONE
21771      * @see #LAYER_TYPE_SOFTWARE
21772      * @see #LAYER_TYPE_HARDWARE
21773      * @see #setAlpha(float)
21774      *
21775      * @attr ref android.R.styleable#View_layerType
21776      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)21777     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
21778         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
21779             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
21780                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
21781         }
21782 
21783         boolean typeChanged = mRenderNode.setLayerType(layerType);
21784 
21785         if (!typeChanged) {
21786             setLayerPaint(paint);
21787             return;
21788         }
21789 
21790         if (layerType != LAYER_TYPE_SOFTWARE) {
21791             // Destroy any previous software drawing cache if present
21792             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
21793             // drawing cache created in View#draw when drawing to a SW canvas.
21794             destroyDrawingCache();
21795         }
21796 
21797         mLayerType = layerType;
21798         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
21799         mRenderNode.setLayerPaint(mLayerPaint);
21800 
21801         // draw() behaves differently if we are on a layer, so we need to
21802         // invalidate() here
21803         invalidateParentCaches();
21804         invalidate(true);
21805     }
21806 
21807     /**
21808      * Configure the {@link android.graphics.RenderEffect} to apply to this View.
21809      * This will apply a visual effect to the results of the View before it is drawn. For example if
21810      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
21811      * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
21812      * when this View is drawn.
21813      * @param renderEffect to be applied to the View. Passing null clears the previously configured
21814      *                     {@link RenderEffect}
21815      */
setRenderEffect(@ullable RenderEffect renderEffect)21816     public void setRenderEffect(@Nullable RenderEffect renderEffect) {
21817         if (mRenderNode.setRenderEffect(renderEffect)) {
21818             invalidateViewProperty(true, true);
21819         }
21820     }
21821 
21822     /**
21823      * Updates the {@link Paint} object used with the current layer (used only if the current
21824      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
21825      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
21826      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
21827      * ensure that the view gets redrawn immediately.
21828      *
21829      * <p>A layer is associated with an optional {@link android.graphics.Paint}
21830      * instance that controls how the layer is composed on screen. The following
21831      * properties of the paint are taken into account when composing the layer:</p>
21832      * <ul>
21833      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
21834      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
21835      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
21836      * </ul>
21837      *
21838      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
21839      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
21840      *
21841      * @param paint The paint used to compose the layer. This argument is optional
21842      *        and can be null. It is ignored when the layer type is
21843      *        {@link #LAYER_TYPE_NONE}
21844      *
21845      * @see #setLayerType(int, android.graphics.Paint)
21846      */
setLayerPaint(@ullable Paint paint)21847     public void setLayerPaint(@Nullable Paint paint) {
21848         int layerType = getLayerType();
21849         if (layerType != LAYER_TYPE_NONE) {
21850             mLayerPaint = paint;
21851             if (layerType == LAYER_TYPE_HARDWARE) {
21852                 if (mRenderNode.setLayerPaint(paint)) {
21853                     invalidateViewProperty(false, false);
21854                 }
21855             } else {
21856                 invalidate();
21857             }
21858         }
21859     }
21860 
21861     /**
21862      * Indicates what type of layer is currently associated with this view. By default
21863      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
21864      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
21865      * for more information on the different types of layers.
21866      *
21867      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21868      *         {@link #LAYER_TYPE_HARDWARE}
21869      *
21870      * @see #setLayerType(int, android.graphics.Paint)
21871      * @see #buildLayer()
21872      * @see #LAYER_TYPE_NONE
21873      * @see #LAYER_TYPE_SOFTWARE
21874      * @see #LAYER_TYPE_HARDWARE
21875      */
21876     @InspectableProperty(enumMapping = {
21877             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
21878             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
21879             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
21880     })
21881     @LayerType
getLayerType()21882     public int getLayerType() {
21883         return mLayerType;
21884     }
21885 
21886     /**
21887      * Forces this view's layer to be created and this view to be rendered
21888      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
21889      * invoking this method will have no effect.
21890      *
21891      * This method can for instance be used to render a view into its layer before
21892      * starting an animation. If this view is complex, rendering into the layer
21893      * before starting the animation will avoid skipping frames.
21894      *
21895      * @throws IllegalStateException If this view is not attached to a window
21896      *
21897      * @see #setLayerType(int, android.graphics.Paint)
21898      */
buildLayer()21899     public void buildLayer() {
21900         if (mLayerType == LAYER_TYPE_NONE) return;
21901 
21902         final AttachInfo attachInfo = mAttachInfo;
21903         if (attachInfo == null) {
21904             throw new IllegalStateException("This view must be attached to a window first");
21905         }
21906 
21907         if (getWidth() == 0 || getHeight() == 0) {
21908             return;
21909         }
21910 
21911         switch (mLayerType) {
21912             case LAYER_TYPE_HARDWARE:
21913                 updateDisplayListIfDirty();
21914                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
21915                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
21916                 }
21917                 break;
21918             case LAYER_TYPE_SOFTWARE:
21919                 buildDrawingCache(true);
21920                 break;
21921         }
21922     }
21923 
21924     /**
21925      * Destroys all hardware rendering resources. This method is invoked
21926      * when the system needs to reclaim resources. Upon execution of this
21927      * method, you should free any OpenGL resources created by the view.
21928      *
21929      * Note: you <strong>must</strong> call
21930      * <code>super.destroyHardwareResources()</code> when overriding
21931      * this method.
21932      *
21933      * @hide
21934      */
21935     @CallSuper
21936     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
destroyHardwareResources()21937     protected void destroyHardwareResources() {
21938         if (mOverlay != null) {
21939             mOverlay.getOverlayView().destroyHardwareResources();
21940         }
21941         if (mGhostView != null) {
21942             mGhostView.destroyHardwareResources();
21943         }
21944     }
21945 
21946     /**
21947      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
21948      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
21949      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
21950      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
21951      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
21952      * null.</p>
21953      *
21954      * <p>Enabling the drawing cache is similar to
21955      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
21956      * acceleration is turned off. When hardware acceleration is turned on, enabling the
21957      * drawing cache has no effect on rendering because the system uses a different mechanism
21958      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
21959      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
21960      * for information on how to enable software and hardware layers.</p>
21961      *
21962      * <p>This API can be used to manually generate
21963      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
21964      * {@link #getDrawingCache()}.</p>
21965      *
21966      * @param enabled true to enable the drawing cache, false otherwise
21967      *
21968      * @see #isDrawingCacheEnabled()
21969      * @see #getDrawingCache()
21970      * @see #buildDrawingCache()
21971      * @see #setLayerType(int, android.graphics.Paint)
21972      *
21973      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21974      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21975      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21976      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21977      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21978      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21979      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21980      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21981      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21982      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21983      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21984      * reports or unit testing the {@link PixelCopy} API is recommended.
21985      */
21986     @Deprecated
setDrawingCacheEnabled(boolean enabled)21987     public void setDrawingCacheEnabled(boolean enabled) {
21988         mCachingFailed = false;
21989         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
21990     }
21991 
21992     /**
21993      * <p>Indicates whether the drawing cache is enabled for this view.</p>
21994      *
21995      * @return true if the drawing cache is enabled
21996      *
21997      * @see #setDrawingCacheEnabled(boolean)
21998      * @see #getDrawingCache()
21999      *
22000      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22001      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22002      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22003      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22004      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22005      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22006      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22007      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22008      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22009      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22010      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22011      * reports or unit testing the {@link PixelCopy} API is recommended.
22012      */
22013     @Deprecated
22014     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()22015     public boolean isDrawingCacheEnabled() {
22016         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
22017     }
22018 
22019     /**
22020      * Debugging utility which recursively outputs the dirty state of a view and its
22021      * descendants.
22022      *
22023      * @hide
22024      */
22025     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)22026     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
22027         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
22028                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
22029                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
22030                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
22031                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
22032         if (clear) {
22033             mPrivateFlags &= clearMask;
22034         }
22035         if (this instanceof ViewGroup) {
22036             ViewGroup parent = (ViewGroup) this;
22037             final int count = parent.getChildCount();
22038             for (int i = 0; i < count; i++) {
22039                 final View child = parent.getChildAt(i);
22040                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
22041             }
22042         }
22043     }
22044 
22045     /**
22046      * This method is used by ViewGroup to cause its children to restore or recreate their
22047      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
22048      * to recreate its own display list, which would happen if it went through the normal
22049      * draw/dispatchDraw mechanisms.
22050      *
22051      * @hide
22052      */
dispatchGetDisplayList()22053     protected void dispatchGetDisplayList() {}
22054 
22055     /**
22056      * A view that is not attached or hardware accelerated cannot create a display list.
22057      * This method checks these conditions and returns the appropriate result.
22058      *
22059      * @return true if view has the ability to create a display list, false otherwise.
22060      *
22061      * @hide
22062      */
canHaveDisplayList()22063     public boolean canHaveDisplayList() {
22064         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
22065     }
22066 
22067     /**
22068      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
22069      * @hide
22070      */
22071     @NonNull
22072     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateDisplayListIfDirty()22073     public RenderNode updateDisplayListIfDirty() {
22074         final RenderNode renderNode = mRenderNode;
22075         if (!canHaveDisplayList()) {
22076             // can't populate RenderNode, don't try
22077             return renderNode;
22078         }
22079 
22080         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
22081                 || !renderNode.hasDisplayList()
22082                 || (mRecreateDisplayList)) {
22083             // Don't need to recreate the display list, just need to tell our
22084             // children to restore/recreate theirs
22085             if (renderNode.hasDisplayList()
22086                     && !mRecreateDisplayList) {
22087                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
22088                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22089                 dispatchGetDisplayList();
22090 
22091                 return renderNode; // no work needed
22092             }
22093 
22094             // If we got here, we're recreating it. Mark it as such to ensure that
22095             // we copy in child display lists into ours in drawChild()
22096             mRecreateDisplayList = true;
22097 
22098             int width = mRight - mLeft;
22099             int height = mBottom - mTop;
22100             int layerType = getLayerType();
22101 
22102             // Hacky hack: Reset any stretch effects as those are applied during the draw pass
22103             // instead of being "stateful" like other RenderNode properties
22104             renderNode.clearStretch();
22105 
22106             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
22107 
22108             try {
22109                 if (layerType == LAYER_TYPE_SOFTWARE) {
22110                     buildDrawingCache(true);
22111                     Bitmap cache = getDrawingCache(true);
22112                     if (cache != null) {
22113                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
22114                     }
22115                 } else {
22116                     computeScroll();
22117 
22118                     canvas.translate(-mScrollX, -mScrollY);
22119                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
22120                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22121 
22122                     // Fast path for layouts with no backgrounds
22123                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22124                         dispatchDraw(canvas);
22125                         drawAutofilledHighlight(canvas);
22126                         if (mOverlay != null && !mOverlay.isEmpty()) {
22127                             mOverlay.getOverlayView().draw(canvas);
22128                         }
22129                         if (isShowingLayoutBounds()) {
22130                             debugDrawFocus(canvas);
22131                         }
22132                     } else {
22133                         draw(canvas);
22134                     }
22135                 }
22136             } finally {
22137                 renderNode.endRecording();
22138                 setDisplayListProperties(renderNode);
22139             }
22140         } else {
22141             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
22142             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22143         }
22144         return renderNode;
22145     }
22146 
22147     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resetDisplayList()22148     private void resetDisplayList() {
22149         mRenderNode.discardDisplayList();
22150         if (mBackgroundRenderNode != null) {
22151             mBackgroundRenderNode.discardDisplayList();
22152         }
22153     }
22154 
22155     /**
22156      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
22157      *
22158      * @return A non-scaled bitmap representing this view or null if cache is disabled.
22159      *
22160      * @see #getDrawingCache(boolean)
22161      *
22162      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22163      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22164      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22165      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22166      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22167      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22168      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22169      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22170      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22171      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22172      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22173      * reports or unit testing the {@link PixelCopy} API is recommended.
22174      */
22175     @Deprecated
getDrawingCache()22176     public Bitmap getDrawingCache() {
22177         return getDrawingCache(false);
22178     }
22179 
22180     /**
22181      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
22182      * is null when caching is disabled. If caching is enabled and the cache is not ready,
22183      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
22184      * draw from the cache when the cache is enabled. To benefit from the cache, you must
22185      * request the drawing cache by calling this method and draw it on screen if the
22186      * returned bitmap is not null.</p>
22187      *
22188      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
22189      * this method will create a bitmap of the same size as this view. Because this bitmap
22190      * will be drawn scaled by the parent ViewGroup, the result on screen might show
22191      * scaling artifacts. To avoid such artifacts, you should call this method by setting
22192      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
22193      * size than the view. This implies that your application must be able to handle this
22194      * size.</p>
22195      *
22196      * @param autoScale Indicates whether the generated bitmap should be scaled based on
22197      *        the current density of the screen when the application is in compatibility
22198      *        mode.
22199      *
22200      * @return A bitmap representing this view or null if cache is disabled.
22201      *
22202      * @see #setDrawingCacheEnabled(boolean)
22203      * @see #isDrawingCacheEnabled()
22204      * @see #buildDrawingCache(boolean)
22205      * @see #destroyDrawingCache()
22206      *
22207      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22208      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22209      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22210      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22211      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22212      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22213      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22214      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22215      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22216      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22217      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22218      * reports or unit testing the {@link PixelCopy} API is recommended.
22219      */
22220     @Deprecated
getDrawingCache(boolean autoScale)22221     public Bitmap getDrawingCache(boolean autoScale) {
22222         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
22223             return null;
22224         }
22225         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
22226             buildDrawingCache(autoScale);
22227         }
22228         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
22229     }
22230 
22231     /**
22232      * <p>Frees the resources used by the drawing cache. If you call
22233      * {@link #buildDrawingCache()} manually without calling
22234      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
22235      * should cleanup the cache with this method afterwards.</p>
22236      *
22237      * @see #setDrawingCacheEnabled(boolean)
22238      * @see #buildDrawingCache()
22239      * @see #getDrawingCache()
22240      *
22241      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22242      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22243      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22244      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22245      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22246      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22247      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22248      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22249      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22250      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22251      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22252      * reports or unit testing the {@link PixelCopy} API is recommended.
22253      */
22254     @Deprecated
destroyDrawingCache()22255     public void destroyDrawingCache() {
22256         if (mDrawingCache != null) {
22257             mDrawingCache.recycle();
22258             mDrawingCache = null;
22259         }
22260         if (mUnscaledDrawingCache != null) {
22261             mUnscaledDrawingCache.recycle();
22262             mUnscaledDrawingCache = null;
22263         }
22264     }
22265 
22266     /**
22267      * Setting a solid background color for the drawing cache's bitmaps will improve
22268      * performance and memory usage. Note, though that this should only be used if this
22269      * view will always be drawn on top of a solid color.
22270      *
22271      * @param color The background color to use for the drawing cache's bitmap
22272      *
22273      * @see #setDrawingCacheEnabled(boolean)
22274      * @see #buildDrawingCache()
22275      * @see #getDrawingCache()
22276      *
22277      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22278      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22279      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22280      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22281      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22282      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22283      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22284      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22285      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22286      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22287      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22288      * reports or unit testing the {@link PixelCopy} API is recommended.
22289      */
22290     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)22291     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
22292         if (color != mDrawingCacheBackgroundColor) {
22293             mDrawingCacheBackgroundColor = color;
22294             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
22295         }
22296     }
22297 
22298     /**
22299      * @see #setDrawingCacheBackgroundColor(int)
22300      *
22301      * @return The background color to used for the drawing cache's bitmap
22302      *
22303      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22304      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22305      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22306      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22307      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22308      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22309      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22310      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22311      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22312      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22313      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22314      * reports or unit testing the {@link PixelCopy} API is recommended.
22315      */
22316     @Deprecated
22317     @ColorInt
getDrawingCacheBackgroundColor()22318     public int getDrawingCacheBackgroundColor() {
22319         return mDrawingCacheBackgroundColor;
22320     }
22321 
22322     /**
22323      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
22324      *
22325      * @see #buildDrawingCache(boolean)
22326      *
22327      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22328      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22329      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22330      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22331      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22332      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22333      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22334      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22335      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22336      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22337      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22338      * reports or unit testing the {@link PixelCopy} API is recommended.
22339      */
22340     @Deprecated
buildDrawingCache()22341     public void buildDrawingCache() {
22342         buildDrawingCache(false);
22343     }
22344 
22345     /**
22346      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
22347      *
22348      * <p>If you call {@link #buildDrawingCache()} manually without calling
22349      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
22350      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
22351      *
22352      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
22353      * this method will create a bitmap of the same size as this view. Because this bitmap
22354      * will be drawn scaled by the parent ViewGroup, the result on screen might show
22355      * scaling artifacts. To avoid such artifacts, you should call this method by setting
22356      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
22357      * size than the view. This implies that your application must be able to handle this
22358      * size.</p>
22359      *
22360      * <p>You should avoid calling this method when hardware acceleration is enabled. If
22361      * you do not need the drawing cache bitmap, calling this method will increase memory
22362      * usage and cause the view to be rendered in software once, thus negatively impacting
22363      * performance.</p>
22364      *
22365      * @see #getDrawingCache()
22366      * @see #destroyDrawingCache()
22367      *
22368      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22369      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22370      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22371      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22372      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22373      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22374      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22375      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22376      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22377      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22378      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22379      * reports or unit testing the {@link PixelCopy} API is recommended.
22380      */
22381     @Deprecated
buildDrawingCache(boolean autoScale)22382     public void buildDrawingCache(boolean autoScale) {
22383         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
22384                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
22385             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
22386                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
22387                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
22388             }
22389             try {
22390                 buildDrawingCacheImpl(autoScale);
22391             } finally {
22392                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
22393             }
22394         }
22395     }
22396 
22397     /**
22398      * private, internal implementation of buildDrawingCache, used to enable tracing
22399      */
buildDrawingCacheImpl(boolean autoScale)22400     private void buildDrawingCacheImpl(boolean autoScale) {
22401         mCachingFailed = false;
22402 
22403         int width = mRight - mLeft;
22404         int height = mBottom - mTop;
22405 
22406         final AttachInfo attachInfo = mAttachInfo;
22407         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
22408 
22409         if (autoScale && scalingRequired) {
22410             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
22411             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
22412         }
22413 
22414         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
22415         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
22416         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
22417 
22418         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
22419         final long drawingCacheSize =
22420                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
22421         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
22422             if (width > 0 && height > 0) {
22423                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
22424                         + " too large to fit into a software layer (or drawing cache), needs "
22425                         + projectedBitmapSize + " bytes, only "
22426                         + drawingCacheSize + " available");
22427             }
22428             destroyDrawingCache();
22429             mCachingFailed = true;
22430             return;
22431         }
22432 
22433         boolean clear = true;
22434         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
22435 
22436         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
22437             Bitmap.Config quality;
22438             if (!opaque) {
22439                 // Never pick ARGB_4444 because it looks awful
22440                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
22441                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
22442                     case DRAWING_CACHE_QUALITY_AUTO:
22443                     case DRAWING_CACHE_QUALITY_LOW:
22444                     case DRAWING_CACHE_QUALITY_HIGH:
22445                     default:
22446                         quality = Bitmap.Config.ARGB_8888;
22447                         break;
22448                 }
22449             } else {
22450                 // Optimization for translucent windows
22451                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
22452                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
22453             }
22454 
22455             // Try to cleanup memory
22456             if (bitmap != null) bitmap.recycle();
22457 
22458             try {
22459                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
22460                         width, height, quality);
22461                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
22462                 if (autoScale) {
22463                     mDrawingCache = bitmap;
22464                 } else {
22465                     mUnscaledDrawingCache = bitmap;
22466                 }
22467                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
22468             } catch (OutOfMemoryError e) {
22469                 // If there is not enough memory to create the bitmap cache, just
22470                 // ignore the issue as bitmap caches are not required to draw the
22471                 // view hierarchy
22472                 if (autoScale) {
22473                     mDrawingCache = null;
22474                 } else {
22475                     mUnscaledDrawingCache = null;
22476                 }
22477                 mCachingFailed = true;
22478                 return;
22479             }
22480 
22481             clear = drawingCacheBackgroundColor != 0;
22482         }
22483 
22484         Canvas canvas;
22485         if (attachInfo != null) {
22486             canvas = attachInfo.mCanvas;
22487             if (canvas == null) {
22488                 canvas = new Canvas();
22489             }
22490             canvas.setBitmap(bitmap);
22491             // Temporarily clobber the cached Canvas in case one of our children
22492             // is also using a drawing cache. Without this, the children would
22493             // steal the canvas by attaching their own bitmap to it and bad, bad
22494             // thing would happen (invisible views, corrupted drawings, etc.)
22495             attachInfo.mCanvas = null;
22496         } else {
22497             // This case should hopefully never or seldom happen
22498             canvas = new Canvas(bitmap);
22499         }
22500 
22501         if (clear) {
22502             bitmap.eraseColor(drawingCacheBackgroundColor);
22503         }
22504 
22505         computeScroll();
22506         final int restoreCount = canvas.save();
22507 
22508         if (autoScale && scalingRequired) {
22509             final float scale = attachInfo.mApplicationScale;
22510             canvas.scale(scale, scale);
22511         }
22512 
22513         canvas.translate(-mScrollX, -mScrollY);
22514 
22515         mPrivateFlags |= PFLAG_DRAWN;
22516         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
22517                 mLayerType != LAYER_TYPE_NONE) {
22518             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
22519         }
22520 
22521         // Fast path for layouts with no backgrounds
22522         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22523             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22524             dispatchDraw(canvas);
22525             drawAutofilledHighlight(canvas);
22526             if (mOverlay != null && !mOverlay.isEmpty()) {
22527                 mOverlay.getOverlayView().draw(canvas);
22528             }
22529         } else {
22530             draw(canvas);
22531         }
22532 
22533         canvas.restoreToCount(restoreCount);
22534         canvas.setBitmap(null);
22535 
22536         if (attachInfo != null) {
22537             // Restore the cached Canvas for our siblings
22538             attachInfo.mCanvas = canvas;
22539         }
22540     }
22541 
22542     /**
22543      * Create a snapshot of the view into a bitmap.  We should probably make
22544      * some form of this public, but should think about the API.
22545      *
22546      * @hide
22547      */
22548     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)22549     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
22550         int width = mRight - mLeft;
22551         int height = mBottom - mTop;
22552 
22553         final AttachInfo attachInfo = mAttachInfo;
22554         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
22555         width = (int) ((width * scale) + 0.5f);
22556         height = (int) ((height * scale) + 0.5f);
22557 
22558         Canvas oldCanvas = null;
22559         try {
22560             Canvas canvas = canvasProvider.getCanvas(this,
22561                     width > 0 ? width : 1, height > 0 ? height : 1);
22562 
22563             if (attachInfo != null) {
22564                 oldCanvas = attachInfo.mCanvas;
22565                 // Temporarily clobber the cached Canvas in case one of our children
22566                 // is also using a drawing cache. Without this, the children would
22567                 // steal the canvas by attaching their own bitmap to it and bad, bad
22568                 // things would happen (invisible views, corrupted drawings, etc.)
22569                 attachInfo.mCanvas = null;
22570             }
22571 
22572             computeScroll();
22573             final int restoreCount = canvas.save();
22574             canvas.scale(scale, scale);
22575             canvas.translate(-mScrollX, -mScrollY);
22576 
22577             // Temporarily remove the dirty mask
22578             int flags = mPrivateFlags;
22579             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22580 
22581             // Fast path for layouts with no backgrounds
22582             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22583                 dispatchDraw(canvas);
22584                 drawAutofilledHighlight(canvas);
22585                 if (mOverlay != null && !mOverlay.isEmpty()) {
22586                     mOverlay.getOverlayView().draw(canvas);
22587                 }
22588             } else {
22589                 draw(canvas);
22590             }
22591 
22592             mPrivateFlags = flags;
22593             canvas.restoreToCount(restoreCount);
22594             return canvasProvider.createBitmap();
22595         } finally {
22596             if (oldCanvas != null) {
22597                 attachInfo.mCanvas = oldCanvas;
22598             }
22599         }
22600     }
22601 
22602     /**
22603      * Indicates whether this View is currently in edit mode. A View is usually
22604      * in edit mode when displayed within a developer tool. For instance, if
22605      * this View is being drawn by a visual user interface builder, this method
22606      * should return true.
22607      *
22608      * Subclasses should check the return value of this method to provide
22609      * different behaviors if their normal behavior might interfere with the
22610      * host environment. For instance: the class spawns a thread in its
22611      * constructor, the drawing code relies on device-specific features, etc.
22612      *
22613      * This method is usually checked in the drawing code of custom widgets.
22614      *
22615      * @return True if this View is in edit mode, false otherwise.
22616      */
isInEditMode()22617     public boolean isInEditMode() {
22618         return false;
22619     }
22620 
22621     /**
22622      * If the View draws content inside its padding and enables fading edges,
22623      * it needs to support padding offsets. Padding offsets are added to the
22624      * fading edges to extend the length of the fade so that it covers pixels
22625      * drawn inside the padding.
22626      *
22627      * Subclasses of this class should override this method if they need
22628      * to draw content inside the padding.
22629      *
22630      * @return True if padding offset must be applied, false otherwise.
22631      *
22632      * @see #getLeftPaddingOffset()
22633      * @see #getRightPaddingOffset()
22634      * @see #getTopPaddingOffset()
22635      * @see #getBottomPaddingOffset()
22636      *
22637      * @since CURRENT
22638      */
isPaddingOffsetRequired()22639     protected boolean isPaddingOffsetRequired() {
22640         return false;
22641     }
22642 
22643     /**
22644      * Amount by which to extend the left fading region. Called only when
22645      * {@link #isPaddingOffsetRequired()} returns true.
22646      *
22647      * @return The left padding offset in pixels.
22648      *
22649      * @see #isPaddingOffsetRequired()
22650      *
22651      * @since CURRENT
22652      */
getLeftPaddingOffset()22653     protected int getLeftPaddingOffset() {
22654         return 0;
22655     }
22656 
22657     /**
22658      * Amount by which to extend the right fading region. Called only when
22659      * {@link #isPaddingOffsetRequired()} returns true.
22660      *
22661      * @return The right padding offset in pixels.
22662      *
22663      * @see #isPaddingOffsetRequired()
22664      *
22665      * @since CURRENT
22666      */
getRightPaddingOffset()22667     protected int getRightPaddingOffset() {
22668         return 0;
22669     }
22670 
22671     /**
22672      * Amount by which to extend the top fading region. Called only when
22673      * {@link #isPaddingOffsetRequired()} returns true.
22674      *
22675      * @return The top padding offset in pixels.
22676      *
22677      * @see #isPaddingOffsetRequired()
22678      *
22679      * @since CURRENT
22680      */
getTopPaddingOffset()22681     protected int getTopPaddingOffset() {
22682         return 0;
22683     }
22684 
22685     /**
22686      * Amount by which to extend the bottom fading region. Called only when
22687      * {@link #isPaddingOffsetRequired()} returns true.
22688      *
22689      * @return The bottom padding offset in pixels.
22690      *
22691      * @see #isPaddingOffsetRequired()
22692      *
22693      * @since CURRENT
22694      */
getBottomPaddingOffset()22695     protected int getBottomPaddingOffset() {
22696         return 0;
22697     }
22698 
22699     /**
22700      * @hide
22701      * @param offsetRequired
22702      */
getFadeTop(boolean offsetRequired)22703     protected int getFadeTop(boolean offsetRequired) {
22704         int top = mPaddingTop;
22705         if (offsetRequired) top += getTopPaddingOffset();
22706         return top;
22707     }
22708 
22709     /**
22710      * @hide
22711      * @param offsetRequired
22712      */
getFadeHeight(boolean offsetRequired)22713     protected int getFadeHeight(boolean offsetRequired) {
22714         int padding = mPaddingTop;
22715         if (offsetRequired) padding += getTopPaddingOffset();
22716         return mBottom - mTop - mPaddingBottom - padding;
22717     }
22718 
22719     /**
22720      * <p>Indicates whether this view is attached to a hardware accelerated
22721      * window or not.</p>
22722      *
22723      * <p>Even if this method returns true, it does not mean that every call
22724      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
22725      * accelerated {@link android.graphics.Canvas}. For instance, if this view
22726      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
22727      * window is hardware accelerated,
22728      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
22729      * return false, and this method will return true.</p>
22730      *
22731      * @return True if the view is attached to a window and the window is
22732      *         hardware accelerated; false in any other case.
22733      */
22734     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()22735     public boolean isHardwareAccelerated() {
22736         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
22737     }
22738 
22739     /**
22740      * Sets a rectangular area on this view to which the view will be clipped
22741      * when it is drawn. Setting the value to null will remove the clip bounds
22742      * and the view will draw normally, using its full bounds.
22743      *
22744      * @param clipBounds The rectangular area, in the local coordinates of
22745      * this view, to which future drawing operations will be clipped.
22746      */
setClipBounds(Rect clipBounds)22747     public void setClipBounds(Rect clipBounds) {
22748         if (clipBounds == mClipBounds
22749                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
22750             return;
22751         }
22752         if (clipBounds != null) {
22753             if (mClipBounds == null) {
22754                 mClipBounds = new Rect(clipBounds);
22755             } else {
22756                 mClipBounds.set(clipBounds);
22757             }
22758         } else {
22759             mClipBounds = null;
22760         }
22761         mRenderNode.setClipRect(mClipBounds);
22762         invalidateViewProperty(false, false);
22763     }
22764 
22765     /**
22766      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
22767      *
22768      * @return A copy of the current clip bounds if clip bounds are set,
22769      * otherwise null.
22770      */
getClipBounds()22771     public Rect getClipBounds() {
22772         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
22773     }
22774 
22775 
22776     /**
22777      * Populates an output rectangle with the clip bounds of the view,
22778      * returning {@code true} if successful or {@code false} if the view's
22779      * clip bounds are {@code null}.
22780      *
22781      * @param outRect rectangle in which to place the clip bounds of the view
22782      * @return {@code true} if successful or {@code false} if the view's
22783      *         clip bounds are {@code null}
22784      */
getClipBounds(Rect outRect)22785     public boolean getClipBounds(Rect outRect) {
22786         if (mClipBounds != null) {
22787             outRect.set(mClipBounds);
22788             return true;
22789         }
22790         return false;
22791     }
22792 
22793     /**
22794      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
22795      * case of an active Animation being run on the view.
22796      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)22797     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
22798             Animation a, boolean scalingRequired) {
22799         Transformation invalidationTransform;
22800         final int flags = parent.mGroupFlags;
22801         final boolean initialized = a.isInitialized();
22802         if (!initialized) {
22803             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
22804             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
22805             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
22806             onAnimationStart();
22807         }
22808 
22809         final Transformation t = parent.getChildTransformation();
22810         boolean more = a.getTransformation(drawingTime, t, 1f);
22811         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
22812             if (parent.mInvalidationTransformation == null) {
22813                 parent.mInvalidationTransformation = new Transformation();
22814             }
22815             invalidationTransform = parent.mInvalidationTransformation;
22816             a.getTransformation(drawingTime, invalidationTransform, 1f);
22817         } else {
22818             invalidationTransform = t;
22819         }
22820 
22821         if (more) {
22822             if (!a.willChangeBounds()) {
22823                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
22824                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
22825                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
22826                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
22827                     // The child need to draw an animation, potentially offscreen, so
22828                     // make sure we do not cancel invalidate requests
22829                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
22830                     parent.invalidate(mLeft, mTop, mRight, mBottom);
22831                 }
22832             } else {
22833                 if (parent.mInvalidateRegion == null) {
22834                     parent.mInvalidateRegion = new RectF();
22835                 }
22836                 final RectF region = parent.mInvalidateRegion;
22837                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
22838                         invalidationTransform);
22839 
22840                 // The child need to draw an animation, potentially offscreen, so
22841                 // make sure we do not cancel invalidate requests
22842                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
22843 
22844                 final int left = mLeft + (int) region.left;
22845                 final int top = mTop + (int) region.top;
22846                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
22847                         top + (int) (region.height() + .5f));
22848             }
22849         }
22850         return more;
22851     }
22852 
22853     /**
22854      * This method is called by getDisplayList() when a display list is recorded for a View.
22855      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
22856      */
setDisplayListProperties(RenderNode renderNode)22857     void setDisplayListProperties(RenderNode renderNode) {
22858         if (renderNode != null) {
22859             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
22860             renderNode.setClipToBounds(mParent instanceof ViewGroup
22861                     && ((ViewGroup) mParent).getClipChildren());
22862 
22863             float alpha = 1;
22864             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
22865                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22866                 ViewGroup parentVG = (ViewGroup) mParent;
22867                 final Transformation t = parentVG.getChildTransformation();
22868                 if (parentVG.getChildStaticTransformation(this, t)) {
22869                     final int transformType = t.getTransformationType();
22870                     if (transformType != Transformation.TYPE_IDENTITY) {
22871                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
22872                             alpha = t.getAlpha();
22873                         }
22874                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
22875                             renderNode.setStaticMatrix(t.getMatrix());
22876                         }
22877                     }
22878                 }
22879             }
22880             if (mTransformationInfo != null) {
22881                 alpha *= getFinalAlpha();
22882                 if (alpha < 1) {
22883                     final int multipliedAlpha = (int) (255 * alpha);
22884                     if (onSetAlpha(multipliedAlpha)) {
22885                         alpha = 1;
22886                     }
22887                 }
22888                 renderNode.setAlpha(alpha);
22889             } else if (alpha < 1) {
22890                 renderNode.setAlpha(alpha);
22891             }
22892         }
22893     }
22894 
22895     /**
22896      * If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
22897      *
22898      * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
22899      * HW accelerated, it can't handle drawing RenderNodes.
22900      *
22901      * @hide
22902      */
drawsWithRenderNode(Canvas canvas)22903     protected final boolean drawsWithRenderNode(Canvas canvas) {
22904         return mAttachInfo != null
22905                 && mAttachInfo.mHardwareAccelerated
22906                 && canvas.isHardwareAccelerated();
22907     }
22908 
22909     /**
22910      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
22911      *
22912      * This is where the View specializes rendering behavior based on layer type,
22913      * and hardware acceleration.
22914      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)22915     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
22916 
22917         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
22918 
22919         boolean drawingWithRenderNode = drawsWithRenderNode(canvas);
22920 
22921         boolean more = false;
22922         final boolean childHasIdentityMatrix = hasIdentityMatrix();
22923         final int parentFlags = parent.mGroupFlags;
22924 
22925         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
22926             parent.getChildTransformation().clear();
22927             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22928         }
22929 
22930         Transformation transformToApply = null;
22931         boolean concatMatrix = false;
22932         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
22933         final Animation a = getAnimation();
22934         if (a != null) {
22935             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
22936             concatMatrix = a.willChangeTransformationMatrix();
22937             if (concatMatrix) {
22938                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22939             }
22940             transformToApply = parent.getChildTransformation();
22941         } else {
22942             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
22943                 // No longer animating: clear out old animation matrix
22944                 mRenderNode.setAnimationMatrix(null);
22945                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22946             }
22947             if (!drawingWithRenderNode
22948                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22949                 final Transformation t = parent.getChildTransformation();
22950                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
22951                 if (hasTransform) {
22952                     final int transformType = t.getTransformationType();
22953                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
22954                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
22955                 }
22956             }
22957         }
22958 
22959         concatMatrix |= !childHasIdentityMatrix;
22960 
22961         // Sets the flag as early as possible to allow draw() implementations
22962         // to call invalidate() successfully when doing animations
22963         mPrivateFlags |= PFLAG_DRAWN;
22964 
22965         if (!concatMatrix &&
22966                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
22967                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
22968                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
22969                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
22970             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
22971             return more;
22972         }
22973         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
22974 
22975         if (hardwareAcceleratedCanvas) {
22976             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
22977             // retain the flag's value temporarily in the mRecreateDisplayList flag
22978             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
22979             mPrivateFlags &= ~PFLAG_INVALIDATED;
22980         }
22981 
22982         RenderNode renderNode = null;
22983         Bitmap cache = null;
22984         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
22985         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
22986              if (layerType != LAYER_TYPE_NONE) {
22987                  // If not drawing with RenderNode, treat HW layers as SW
22988                  layerType = LAYER_TYPE_SOFTWARE;
22989                  buildDrawingCache(true);
22990             }
22991             cache = getDrawingCache(true);
22992         }
22993 
22994         if (drawingWithRenderNode) {
22995             // Delay getting the display list until animation-driven alpha values are
22996             // set up and possibly passed on to the view
22997             renderNode = updateDisplayListIfDirty();
22998             if (!renderNode.hasDisplayList()) {
22999                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
23000                 // to getDisplayList(), the display list will be marked invalid and we should not
23001                 // try to use it again.
23002                 renderNode = null;
23003                 drawingWithRenderNode = false;
23004             }
23005         }
23006 
23007         int sx = 0;
23008         int sy = 0;
23009         if (!drawingWithRenderNode) {
23010             computeScroll();
23011             sx = mScrollX;
23012             sy = mScrollY;
23013         }
23014 
23015         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
23016         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
23017 
23018         int restoreTo = -1;
23019         if (!drawingWithRenderNode || transformToApply != null) {
23020             restoreTo = canvas.save();
23021         }
23022         if (offsetForScroll) {
23023             canvas.translate(mLeft - sx, mTop - sy);
23024         } else {
23025             if (!drawingWithRenderNode) {
23026                 canvas.translate(mLeft, mTop);
23027             }
23028             if (scalingRequired) {
23029                 if (drawingWithRenderNode) {
23030                     // TODO: Might not need this if we put everything inside the DL
23031                     restoreTo = canvas.save();
23032                 }
23033                 // mAttachInfo cannot be null, otherwise scalingRequired == false
23034                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
23035                 canvas.scale(scale, scale);
23036             }
23037         }
23038 
23039         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
23040         if (transformToApply != null
23041                 || alpha < 1
23042                 || !hasIdentityMatrix()
23043                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
23044             if (transformToApply != null || !childHasIdentityMatrix) {
23045                 int transX = 0;
23046                 int transY = 0;
23047 
23048                 if (offsetForScroll) {
23049                     transX = -sx;
23050                     transY = -sy;
23051                 }
23052 
23053                 if (transformToApply != null) {
23054                     if (concatMatrix) {
23055                         if (drawingWithRenderNode) {
23056                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
23057                         } else {
23058                             // Undo the scroll translation, apply the transformation matrix,
23059                             // then redo the scroll translate to get the correct result.
23060                             canvas.translate(-transX, -transY);
23061                             canvas.concat(transformToApply.getMatrix());
23062                             canvas.translate(transX, transY);
23063                         }
23064                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23065                     }
23066 
23067                     float transformAlpha = transformToApply.getAlpha();
23068                     if (transformAlpha < 1) {
23069                         alpha *= transformAlpha;
23070                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23071                     }
23072                 }
23073 
23074                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
23075                     canvas.translate(-transX, -transY);
23076                     canvas.concat(getMatrix());
23077                     canvas.translate(transX, transY);
23078                 }
23079             }
23080 
23081             // Deal with alpha if it is or used to be <1
23082             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
23083                 if (alpha < 1) {
23084                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
23085                 } else {
23086                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
23087                 }
23088                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23089                 if (!drawingWithDrawingCache) {
23090                     final int multipliedAlpha = (int) (255 * alpha);
23091                     if (!onSetAlpha(multipliedAlpha)) {
23092                         if (drawingWithRenderNode) {
23093                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
23094                         } else if (layerType == LAYER_TYPE_NONE) {
23095                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
23096                                     multipliedAlpha);
23097                         }
23098                     } else {
23099                         // Alpha is handled by the child directly, clobber the layer's alpha
23100                         mPrivateFlags |= PFLAG_ALPHA_SET;
23101                     }
23102                 }
23103             }
23104         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
23105             onSetAlpha(255);
23106             mPrivateFlags &= ~PFLAG_ALPHA_SET;
23107         }
23108 
23109         if (!drawingWithRenderNode) {
23110             // apply clips directly, since RenderNode won't do it for this draw
23111             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
23112                 if (offsetForScroll) {
23113                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
23114                 } else {
23115                     if (!scalingRequired || cache == null) {
23116                         canvas.clipRect(0, 0, getWidth(), getHeight());
23117                     } else {
23118                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
23119                     }
23120                 }
23121             }
23122 
23123             if (mClipBounds != null) {
23124                 // clip bounds ignore scroll
23125                 canvas.clipRect(mClipBounds);
23126             }
23127         }
23128 
23129         if (!drawingWithDrawingCache) {
23130             if (drawingWithRenderNode) {
23131                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23132                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
23133             } else {
23134                 // Fast path for layouts with no backgrounds
23135                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
23136                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23137                     dispatchDraw(canvas);
23138                 } else {
23139                     draw(canvas);
23140                 }
23141             }
23142         } else if (cache != null) {
23143             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23144             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
23145                 // no layer paint, use temporary paint to draw bitmap
23146                 Paint cachePaint = parent.mCachePaint;
23147                 if (cachePaint == null) {
23148                     cachePaint = new Paint();
23149                     cachePaint.setDither(false);
23150                     parent.mCachePaint = cachePaint;
23151                 }
23152                 cachePaint.setAlpha((int) (alpha * 255));
23153                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
23154             } else {
23155                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
23156                 int layerPaintAlpha = mLayerPaint.getAlpha();
23157                 if (alpha < 1) {
23158                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
23159                 }
23160                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
23161                 if (alpha < 1) {
23162                     mLayerPaint.setAlpha(layerPaintAlpha);
23163                 }
23164             }
23165         }
23166 
23167         if (restoreTo >= 0) {
23168             canvas.restoreToCount(restoreTo);
23169         }
23170 
23171         if (a != null && !more) {
23172             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
23173                 onSetAlpha(255);
23174             }
23175             parent.finishAnimatingView(this, a);
23176         }
23177 
23178         if (more && hardwareAcceleratedCanvas) {
23179             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
23180                 // alpha animations should cause the child to recreate its display list
23181                 invalidate(true);
23182             }
23183         }
23184 
23185         mRecreateDisplayList = false;
23186 
23187         return more;
23188     }
23189 
getDebugPaint()23190     static Paint getDebugPaint() {
23191         if (sDebugPaint == null) {
23192             sDebugPaint = new Paint();
23193             sDebugPaint.setAntiAlias(false);
23194         }
23195         return sDebugPaint;
23196     }
23197 
dipsToPixels(int dips)23198     final int dipsToPixels(int dips) {
23199         float scale = getContext().getResources().getDisplayMetrics().density;
23200         return (int) (dips * scale + 0.5f);
23201     }
23202 
debugDrawFocus(Canvas canvas)23203     final private void debugDrawFocus(Canvas canvas) {
23204         if (isFocused()) {
23205             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
23206             final int l = mScrollX;
23207             final int r = l + mRight - mLeft;
23208             final int t = mScrollY;
23209             final int b = t + mBottom - mTop;
23210 
23211             final Paint paint = getDebugPaint();
23212             paint.setColor(DEBUG_CORNERS_COLOR);
23213 
23214             // Draw squares in corners.
23215             paint.setStyle(Paint.Style.FILL);
23216             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
23217             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
23218             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
23219             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
23220 
23221             // Draw big X across the view.
23222             paint.setStyle(Paint.Style.STROKE);
23223             canvas.drawLine(l, t, r, b, paint);
23224             canvas.drawLine(l, b, r, t, paint);
23225         }
23226     }
23227 
23228     /**
23229      * Manually render this view (and all of its children) to the given Canvas.
23230      * The view must have already done a full layout before this function is
23231      * called.  When implementing a view, implement
23232      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
23233      * If you do need to override this method, call the superclass version.
23234      *
23235      * @param canvas The Canvas to which the View is rendered.
23236      */
23237     @CallSuper
draw(Canvas canvas)23238     public void draw(Canvas canvas) {
23239         final int privateFlags = mPrivateFlags;
23240         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
23241 
23242         /*
23243          * Draw traversal performs several drawing steps which must be executed
23244          * in the appropriate order:
23245          *
23246          *      1. Draw the background
23247          *      2. If necessary, save the canvas' layers to prepare for fading
23248          *      3. Draw view's content
23249          *      4. Draw children
23250          *      5. If necessary, draw the fading edges and restore layers
23251          *      6. Draw decorations (scrollbars for instance)
23252          *      7. If necessary, draw the default focus highlight
23253          */
23254 
23255         // Step 1, draw the background, if needed
23256         int saveCount;
23257 
23258         drawBackground(canvas);
23259 
23260         // skip step 2 & 5 if possible (common case)
23261         final int viewFlags = mViewFlags;
23262         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
23263         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
23264         if (!verticalEdges && !horizontalEdges) {
23265             // Step 3, draw the content
23266             onDraw(canvas);
23267 
23268             // Step 4, draw the children
23269             dispatchDraw(canvas);
23270 
23271             drawAutofilledHighlight(canvas);
23272 
23273             // Overlay is part of the content and draws beneath Foreground
23274             if (mOverlay != null && !mOverlay.isEmpty()) {
23275                 mOverlay.getOverlayView().dispatchDraw(canvas);
23276             }
23277 
23278             // Step 6, draw decorations (foreground, scrollbars)
23279             onDrawForeground(canvas);
23280 
23281             // Step 7, draw the default focus highlight
23282             drawDefaultFocusHighlight(canvas);
23283 
23284             if (isShowingLayoutBounds()) {
23285                 debugDrawFocus(canvas);
23286             }
23287 
23288             // we're done...
23289             return;
23290         }
23291 
23292         /*
23293          * Here we do the full fledged routine...
23294          * (this is an uncommon case where speed matters less,
23295          * this is why we repeat some of the tests that have been
23296          * done above)
23297          */
23298 
23299         boolean drawTop = false;
23300         boolean drawBottom = false;
23301         boolean drawLeft = false;
23302         boolean drawRight = false;
23303 
23304         float topFadeStrength = 0.0f;
23305         float bottomFadeStrength = 0.0f;
23306         float leftFadeStrength = 0.0f;
23307         float rightFadeStrength = 0.0f;
23308 
23309         // Step 2, save the canvas' layers
23310         int paddingLeft = mPaddingLeft;
23311 
23312         final boolean offsetRequired = isPaddingOffsetRequired();
23313         if (offsetRequired) {
23314             paddingLeft += getLeftPaddingOffset();
23315         }
23316 
23317         int left = mScrollX + paddingLeft;
23318         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
23319         int top = mScrollY + getFadeTop(offsetRequired);
23320         int bottom = top + getFadeHeight(offsetRequired);
23321 
23322         if (offsetRequired) {
23323             right += getRightPaddingOffset();
23324             bottom += getBottomPaddingOffset();
23325         }
23326 
23327         final ScrollabilityCache scrollabilityCache = mScrollCache;
23328         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
23329         int length = (int) fadeHeight;
23330 
23331         // clip the fade length if top and bottom fades overlap
23332         // overlapping fades produce odd-looking artifacts
23333         if (verticalEdges && (top + length > bottom - length)) {
23334             length = (bottom - top) / 2;
23335         }
23336 
23337         // also clip horizontal fades if necessary
23338         if (horizontalEdges && (left + length > right - length)) {
23339             length = (right - left) / 2;
23340         }
23341 
23342         if (verticalEdges) {
23343             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
23344             drawTop = topFadeStrength * fadeHeight > 1.0f;
23345             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
23346             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
23347         }
23348 
23349         if (horizontalEdges) {
23350             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
23351             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
23352             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
23353             drawRight = rightFadeStrength * fadeHeight > 1.0f;
23354         }
23355 
23356         saveCount = canvas.getSaveCount();
23357         int topSaveCount = -1;
23358         int bottomSaveCount = -1;
23359         int leftSaveCount = -1;
23360         int rightSaveCount = -1;
23361 
23362         int solidColor = getSolidColor();
23363         if (solidColor == 0) {
23364             if (drawTop) {
23365                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
23366             }
23367 
23368             if (drawBottom) {
23369                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
23370             }
23371 
23372             if (drawLeft) {
23373                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
23374             }
23375 
23376             if (drawRight) {
23377                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
23378             }
23379         } else {
23380             scrollabilityCache.setFadeColor(solidColor);
23381         }
23382 
23383         // Step 3, draw the content
23384         onDraw(canvas);
23385 
23386         // Step 4, draw the children
23387         dispatchDraw(canvas);
23388 
23389         // Step 5, draw the fade effect and restore layers
23390         final Paint p = scrollabilityCache.paint;
23391         final Matrix matrix = scrollabilityCache.matrix;
23392         final Shader fade = scrollabilityCache.shader;
23393 
23394         // must be restored in the reverse order that they were saved
23395         if (drawRight) {
23396             matrix.setScale(1, fadeHeight * rightFadeStrength);
23397             matrix.postRotate(90);
23398             matrix.postTranslate(right, top);
23399             fade.setLocalMatrix(matrix);
23400             p.setShader(fade);
23401             if (solidColor == 0) {
23402                 canvas.restoreUnclippedLayer(rightSaveCount, p);
23403 
23404             } else {
23405                 canvas.drawRect(right - length, top, right, bottom, p);
23406             }
23407         }
23408 
23409         if (drawLeft) {
23410             matrix.setScale(1, fadeHeight * leftFadeStrength);
23411             matrix.postRotate(-90);
23412             matrix.postTranslate(left, top);
23413             fade.setLocalMatrix(matrix);
23414             p.setShader(fade);
23415             if (solidColor == 0) {
23416                 canvas.restoreUnclippedLayer(leftSaveCount, p);
23417             } else {
23418                 canvas.drawRect(left, top, left + length, bottom, p);
23419             }
23420         }
23421 
23422         if (drawBottom) {
23423             matrix.setScale(1, fadeHeight * bottomFadeStrength);
23424             matrix.postRotate(180);
23425             matrix.postTranslate(left, bottom);
23426             fade.setLocalMatrix(matrix);
23427             p.setShader(fade);
23428             if (solidColor == 0) {
23429                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
23430             } else {
23431                 canvas.drawRect(left, bottom - length, right, bottom, p);
23432             }
23433         }
23434 
23435         if (drawTop) {
23436             matrix.setScale(1, fadeHeight * topFadeStrength);
23437             matrix.postTranslate(left, top);
23438             fade.setLocalMatrix(matrix);
23439             p.setShader(fade);
23440             if (solidColor == 0) {
23441                 canvas.restoreUnclippedLayer(topSaveCount, p);
23442             } else {
23443                 canvas.drawRect(left, top, right, top + length, p);
23444             }
23445         }
23446 
23447         canvas.restoreToCount(saveCount);
23448 
23449         drawAutofilledHighlight(canvas);
23450 
23451         // Overlay is part of the content and draws beneath Foreground
23452         if (mOverlay != null && !mOverlay.isEmpty()) {
23453             mOverlay.getOverlayView().dispatchDraw(canvas);
23454         }
23455 
23456         // Step 6, draw decorations (foreground, scrollbars)
23457         onDrawForeground(canvas);
23458 
23459         // Step 7, draw the default focus highlight
23460         drawDefaultFocusHighlight(canvas);
23461 
23462         if (isShowingLayoutBounds()) {
23463             debugDrawFocus(canvas);
23464         }
23465     }
23466 
23467     /**
23468      * Draws the background onto the specified canvas.
23469      *
23470      * @param canvas Canvas on which to draw the background
23471      */
23472     @UnsupportedAppUsage
drawBackground(Canvas canvas)23473     private void drawBackground(Canvas canvas) {
23474         final Drawable background = mBackground;
23475         if (background == null) {
23476             return;
23477         }
23478 
23479         setBackgroundBounds();
23480 
23481         // Attempt to use a display list if requested.
23482         if (canvas.isHardwareAccelerated() && mAttachInfo != null
23483                 && mAttachInfo.mThreadedRenderer != null) {
23484             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
23485 
23486             final RenderNode renderNode = mBackgroundRenderNode;
23487             if (renderNode != null && renderNode.hasDisplayList()) {
23488                 setBackgroundRenderNodeProperties(renderNode);
23489                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
23490                 return;
23491             }
23492         }
23493 
23494         final int scrollX = mScrollX;
23495         final int scrollY = mScrollY;
23496         if ((scrollX | scrollY) == 0) {
23497             background.draw(canvas);
23498         } else {
23499             canvas.translate(scrollX, scrollY);
23500             background.draw(canvas);
23501             canvas.translate(-scrollX, -scrollY);
23502         }
23503     }
23504 
23505     /**
23506      * Sets the correct background bounds and rebuilds the outline, if needed.
23507      * <p/>
23508      * This is called by LayoutLib.
23509      */
setBackgroundBounds()23510     void setBackgroundBounds() {
23511         if (mBackgroundSizeChanged && mBackground != null) {
23512             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
23513             mBackgroundSizeChanged = false;
23514             rebuildOutline();
23515         }
23516     }
23517 
setBackgroundRenderNodeProperties(RenderNode renderNode)23518     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
23519         renderNode.setTranslationX(mScrollX);
23520         renderNode.setTranslationY(mScrollY);
23521     }
23522 
23523     /**
23524      * Creates a new display list or updates the existing display list for the
23525      * specified Drawable.
23526      *
23527      * @param drawable Drawable for which to create a display list
23528      * @param renderNode Existing RenderNode, or {@code null}
23529      * @return A valid display list for the specified drawable
23530      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)23531     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
23532         if (renderNode == null) {
23533             renderNode = RenderNode.create(drawable.getClass().getName(),
23534                     new ViewAnimationHostBridge(this));
23535             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
23536         }
23537 
23538         final Rect bounds = drawable.getBounds();
23539         final int width = bounds.width();
23540         final int height = bounds.height();
23541 
23542         // Hacky hack: Reset any stretch effects as those are applied during the draw pass
23543         // instead of being "stateful" like other RenderNode properties
23544         renderNode.clearStretch();
23545 
23546         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
23547 
23548         // Reverse left/top translation done by drawable canvas, which will
23549         // instead be applied by rendernode's LTRB bounds below. This way, the
23550         // drawable's bounds match with its rendernode bounds and its content
23551         // will lie within those bounds in the rendernode tree.
23552         canvas.translate(-bounds.left, -bounds.top);
23553 
23554         try {
23555             drawable.draw(canvas);
23556         } finally {
23557             renderNode.endRecording();
23558         }
23559 
23560         // Set up drawable properties that are view-independent.
23561         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
23562         renderNode.setProjectBackwards(drawable.isProjected());
23563         renderNode.setProjectionReceiver(true);
23564         renderNode.setClipToBounds(false);
23565         return renderNode;
23566     }
23567 
23568     /**
23569      * Returns the overlay for this view, creating it if it does not yet exist.
23570      * Adding drawables to the overlay will cause them to be displayed whenever
23571      * the view itself is redrawn. Objects in the overlay should be actively
23572      * managed: remove them when they should not be displayed anymore. The
23573      * overlay will always have the same size as its host view.
23574      *
23575      * <p>Note: Overlays do not currently work correctly with {@link
23576      * SurfaceView} or {@link TextureView}; contents in overlays for these
23577      * types of views may not display correctly.</p>
23578      *
23579      * @return The ViewOverlay object for this view.
23580      * @see ViewOverlay
23581      */
getOverlay()23582     public ViewOverlay getOverlay() {
23583         if (mOverlay == null) {
23584             mOverlay = new ViewOverlay(mContext, this);
23585         }
23586         return mOverlay;
23587     }
23588 
23589     /**
23590      * Override this if your view is known to always be drawn on top of a solid color background,
23591      * and needs to draw fading edges. Returning a non-zero color enables the view system to
23592      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
23593      * should be set to 0xFF.
23594      *
23595      * @see #setVerticalFadingEdgeEnabled(boolean)
23596      * @see #setHorizontalFadingEdgeEnabled(boolean)
23597      *
23598      * @return The known solid color background for this view, or 0 if the color may vary
23599      */
23600     @ViewDebug.ExportedProperty(category = "drawing")
23601     @InspectableProperty
23602     @ColorInt
getSolidColor()23603     public int getSolidColor() {
23604         return 0;
23605     }
23606 
23607     /**
23608      * Build a human readable string representation of the specified view flags.
23609      *
23610      * @param flags the view flags to convert to a string
23611      * @return a String representing the supplied flags
23612      */
printFlags(int flags)23613     private static String printFlags(int flags) {
23614         String output = "";
23615         int numFlags = 0;
23616         if ((flags & FOCUSABLE) == FOCUSABLE) {
23617             output += "TAKES_FOCUS";
23618             numFlags++;
23619         }
23620 
23621         switch (flags & VISIBILITY_MASK) {
23622         case INVISIBLE:
23623             if (numFlags > 0) {
23624                 output += " ";
23625             }
23626             output += "INVISIBLE";
23627             // USELESS HERE numFlags++;
23628             break;
23629         case GONE:
23630             if (numFlags > 0) {
23631                 output += " ";
23632             }
23633             output += "GONE";
23634             // USELESS HERE numFlags++;
23635             break;
23636         default:
23637             break;
23638         }
23639         return output;
23640     }
23641 
23642     /**
23643      * Build a human readable string representation of the specified private
23644      * view flags.
23645      *
23646      * @param privateFlags the private view flags to convert to a string
23647      * @return a String representing the supplied flags
23648      */
printPrivateFlags(int privateFlags)23649     private static String printPrivateFlags(int privateFlags) {
23650         String output = "";
23651         int numFlags = 0;
23652 
23653         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
23654             output += "WANTS_FOCUS";
23655             numFlags++;
23656         }
23657 
23658         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
23659             if (numFlags > 0) {
23660                 output += " ";
23661             }
23662             output += "FOCUSED";
23663             numFlags++;
23664         }
23665 
23666         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
23667             if (numFlags > 0) {
23668                 output += " ";
23669             }
23670             output += "SELECTED";
23671             numFlags++;
23672         }
23673 
23674         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
23675             if (numFlags > 0) {
23676                 output += " ";
23677             }
23678             output += "IS_ROOT_NAMESPACE";
23679             numFlags++;
23680         }
23681 
23682         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
23683             if (numFlags > 0) {
23684                 output += " ";
23685             }
23686             output += "HAS_BOUNDS";
23687             numFlags++;
23688         }
23689 
23690         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
23691             if (numFlags > 0) {
23692                 output += " ";
23693             }
23694             output += "DRAWN";
23695             // USELESS HERE numFlags++;
23696         }
23697         return output;
23698     }
23699 
23700     /**
23701      * <p>Indicates whether or not this view's layout will be requested during
23702      * the next hierarchy layout pass.</p>
23703      *
23704      * @return true if the layout will be forced during next layout pass
23705      */
isLayoutRequested()23706     public boolean isLayoutRequested() {
23707         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
23708     }
23709 
23710     /**
23711      * Return true if o is a ViewGroup that is laying out using optical bounds.
23712      * @hide
23713      */
isLayoutModeOptical(Object o)23714     public static boolean isLayoutModeOptical(Object o) {
23715         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
23716     }
23717 
23718     /**
23719      * Enable measure/layout debugging on traces.
23720      *
23721      * @see Trace
23722      * @hide
23723      */
setTraceLayoutSteps(boolean traceLayoutSteps)23724     public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
23725         sTraceLayoutSteps = traceLayoutSteps;
23726     }
23727 
23728     /**
23729      * Enable request layout tracing classes with {@code s} simple name.
23730      * <p>
23731      * When set, a {@link Trace} instant event and a log with the stacktrace is emitted every
23732      * time a requestLayout of a class matching {@code s} name happens.
23733      * This applies only to views attached from this point onwards.
23734      *
23735      * @see Trace#instant(long, String)
23736      * @hide
23737      */
setTracedRequestLayoutClassClass(String s)23738     public static void setTracedRequestLayoutClassClass(String s) {
23739         sTraceRequestLayoutClass = s;
23740     }
23741 
setOpticalFrame(int left, int top, int right, int bottom)23742     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
23743         Insets parentInsets = mParent instanceof View ?
23744                 ((View) mParent).getOpticalInsets() : Insets.NONE;
23745         Insets childInsets = getOpticalInsets();
23746         return setFrame(
23747                 left   + parentInsets.left - childInsets.left,
23748                 top    + parentInsets.top  - childInsets.top,
23749                 right  + parentInsets.left + childInsets.right,
23750                 bottom + parentInsets.top  + childInsets.bottom);
23751     }
23752 
23753     /**
23754      * Assign a size and position to a view and all of its
23755      * descendants
23756      *
23757      * <p>This is the second phase of the layout mechanism.
23758      * (The first is measuring). In this phase, each parent calls
23759      * layout on all of its children to position them.
23760      * This is typically done using the child measurements
23761      * that were stored in the measure pass().</p>
23762      *
23763      * <p>Derived classes should not override this method.
23764      * Derived classes with children should override
23765      * onLayout. In that method, they should
23766      * call layout on each of their children.</p>
23767      *
23768      * @param l Left position, relative to parent
23769      * @param t Top position, relative to parent
23770      * @param r Right position, relative to parent
23771      * @param b Bottom position, relative to parent
23772      */
23773     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)23774     public void layout(int l, int t, int r, int b) {
23775         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
23776             if (isTraversalTracingEnabled()) {
23777                 Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
23778             }
23779             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
23780             if (isTraversalTracingEnabled()) {
23781                 Trace.endSection();
23782             }
23783             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
23784         }
23785 
23786         int oldL = mLeft;
23787         int oldT = mTop;
23788         int oldB = mBottom;
23789         int oldR = mRight;
23790 
23791         boolean changed = isLayoutModeOptical(mParent) ?
23792                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
23793 
23794         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
23795             if (isTraversalTracingEnabled()) {
23796                 Trace.beginSection(mTracingStrings.onLayout);
23797             }
23798             onLayout(changed, l, t, r, b);
23799             if (isTraversalTracingEnabled()) {
23800                 Trace.endSection();
23801             }
23802 
23803             if (shouldDrawRoundScrollbar()) {
23804                 if(mRoundScrollbarRenderer == null) {
23805                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
23806                 }
23807             } else {
23808                 mRoundScrollbarRenderer = null;
23809             }
23810 
23811             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
23812 
23813             ListenerInfo li = mListenerInfo;
23814             if (li != null && li.mOnLayoutChangeListeners != null) {
23815                 ArrayList<OnLayoutChangeListener> listenersCopy =
23816                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
23817                 int numListeners = listenersCopy.size();
23818                 for (int i = 0; i < numListeners; ++i) {
23819                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
23820                 }
23821             }
23822         }
23823 
23824         final boolean wasLayoutValid = isLayoutValid();
23825 
23826         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
23827         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
23828 
23829         if (!wasLayoutValid && isFocused()) {
23830             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
23831             if (canTakeFocus()) {
23832                 // We have a robust focus, so parents should no longer be wanting focus.
23833                 clearParentsWantFocus();
23834             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
23835                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
23836                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
23837                 // and thus the safest action is to clear focus here.
23838                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23839                 clearParentsWantFocus();
23840             } else if (!hasParentWantsFocus()) {
23841                 // original requestFocus was likely on this view directly, so just clear focus
23842                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23843             }
23844             // otherwise, we let parents handle re-assigning focus during their layout passes.
23845         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
23846             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
23847             View focused = findFocus();
23848             if (focused != null) {
23849                 // Try to restore focus as close as possible to our starting focus.
23850                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
23851                     // Give up and clear focus once we've reached the top-most parent which wants
23852                     // focus.
23853                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23854                 }
23855             }
23856         }
23857 
23858         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
23859             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
23860             notifyEnterOrExitForAutoFillIfNeeded(true);
23861         }
23862 
23863         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
23864     }
23865 
hasParentWantsFocus()23866     private boolean hasParentWantsFocus() {
23867         ViewParent parent = mParent;
23868         while (parent instanceof ViewGroup) {
23869             ViewGroup pv = (ViewGroup) parent;
23870             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
23871                 return true;
23872             }
23873             parent = pv.mParent;
23874         }
23875         return false;
23876     }
23877 
23878     /**
23879      * Called from layout when this view should
23880      * assign a size and position to each of its children.
23881      *
23882      * Derived classes with children should override
23883      * this method and call layout on each of
23884      * their children.
23885      * @param changed This is a new size or position for this view
23886      * @param left Left position, relative to parent
23887      * @param top Top position, relative to parent
23888      * @param right Right position, relative to parent
23889      * @param bottom Bottom position, relative to parent
23890      */
onLayout(boolean changed, int left, int top, int right, int bottom)23891     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
23892     }
23893 
23894     /**
23895      * Assign a size and position to this view.
23896      *
23897      * This is called from layout.
23898      *
23899      * @param left Left position, relative to parent
23900      * @param top Top position, relative to parent
23901      * @param right Right position, relative to parent
23902      * @param bottom Bottom position, relative to parent
23903      * @return true if the new size and position are different than the
23904      *         previous ones
23905      * {@hide}
23906      */
23907     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)23908     protected boolean setFrame(int left, int top, int right, int bottom) {
23909         boolean changed = false;
23910 
23911         if (DBG) {
23912             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
23913                     + right + "," + bottom + ")");
23914         }
23915 
23916         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
23917             changed = true;
23918 
23919             // Remember our drawn bit
23920             int drawn = mPrivateFlags & PFLAG_DRAWN;
23921 
23922             int oldWidth = mRight - mLeft;
23923             int oldHeight = mBottom - mTop;
23924             int newWidth = right - left;
23925             int newHeight = bottom - top;
23926             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
23927 
23928             // Invalidate our old position
23929             invalidate(sizeChanged);
23930 
23931             mLeft = left;
23932             mTop = top;
23933             mRight = right;
23934             mBottom = bottom;
23935             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
23936 
23937             mPrivateFlags |= PFLAG_HAS_BOUNDS;
23938 
23939 
23940             if (sizeChanged) {
23941                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
23942             }
23943 
23944             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
23945                 // If we are visible, force the DRAWN bit to on so that
23946                 // this invalidate will go through (at least to our parent).
23947                 // This is because someone may have invalidated this view
23948                 // before this call to setFrame came in, thereby clearing
23949                 // the DRAWN bit.
23950                 mPrivateFlags |= PFLAG_DRAWN;
23951                 invalidate(sizeChanged);
23952                 // parent display list may need to be recreated based on a change in the bounds
23953                 // of any child
23954                 invalidateParentCaches();
23955             }
23956 
23957             // Reset drawn bit to original value (invalidate turns it off)
23958             mPrivateFlags |= drawn;
23959 
23960             mBackgroundSizeChanged = true;
23961             mDefaultFocusHighlightSizeChanged = true;
23962             if (mForegroundInfo != null) {
23963                 mForegroundInfo.mBoundsChanged = true;
23964             }
23965 
23966             notifySubtreeAccessibilityStateChangedIfNeeded();
23967         }
23968         return changed;
23969     }
23970 
23971     /**
23972      * Assign a size and position to this view.
23973      *
23974      * This method is meant to be used in animations only as it applies this position and size
23975      * for the view only temporary and it can be changed back at any time by the layout.
23976      *
23977      * @param left Left position, relative to parent
23978      * @param top Top position, relative to parent
23979      * @param right Right position, relative to parent
23980      * @param bottom Bottom position, relative to parent
23981      *
23982      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
23983      */
setLeftTopRightBottom(int left, int top, int right, int bottom)23984     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
23985         setFrame(left, top, right, bottom);
23986     }
23987 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)23988     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
23989         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
23990         if (mOverlay != null) {
23991             mOverlay.getOverlayView().setRight(newWidth);
23992             mOverlay.getOverlayView().setBottom(newHeight);
23993         }
23994         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
23995         // backtracking" of requestFocus during layout, so don't touch focus here.
23996         if (!sCanFocusZeroSized && isLayoutValid()
23997                 // Don't touch focus if animating
23998                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
23999             if (newWidth <= 0 || newHeight <= 0) {
24000                 if (hasFocus()) {
24001                     clearFocus();
24002                     if (mParent instanceof ViewGroup) {
24003                         ((ViewGroup) mParent).clearFocusedInCluster();
24004                     }
24005                 }
24006                 clearAccessibilityFocus();
24007             } else if (oldWidth <= 0 || oldHeight <= 0) {
24008                 if (mParent != null && canTakeFocus()) {
24009                     mParent.focusableViewAvailable(this);
24010                 }
24011             }
24012         }
24013         rebuildOutline();
24014     }
24015 
24016     /**
24017      * Finalize inflating a view from XML.  This is called as the last phase
24018      * of inflation, after all child views have been added.
24019      *
24020      * <p>Even if the subclass overrides onFinishInflate, they should always be
24021      * sure to call the super method, so that we get called.
24022      */
24023     @CallSuper
onFinishInflate()24024     protected void onFinishInflate() {
24025     }
24026 
24027     /**
24028      * Returns the resources associated with this view.
24029      *
24030      * @return Resources object.
24031      */
getResources()24032     public Resources getResources() {
24033         return mResources;
24034     }
24035 
24036     /**
24037      * Invalidates the specified Drawable.
24038      *
24039      * @param drawable the drawable to invalidate
24040      */
24041     @Override
invalidateDrawable(@onNull Drawable drawable)24042     public void invalidateDrawable(@NonNull Drawable drawable) {
24043         if (verifyDrawable(drawable)) {
24044             final Rect dirty = drawable.getDirtyBounds();
24045             final int scrollX = mScrollX;
24046             final int scrollY = mScrollY;
24047 
24048             invalidate(dirty.left + scrollX, dirty.top + scrollY,
24049                     dirty.right + scrollX, dirty.bottom + scrollY);
24050             rebuildOutline();
24051         }
24052     }
24053 
24054     /**
24055      * Schedules an action on a drawable to occur at a specified time.
24056      *
24057      * @param who the recipient of the action
24058      * @param what the action to run on the drawable
24059      * @param when the time at which the action must occur. Uses the
24060      *        {@link SystemClock#uptimeMillis} timebase.
24061      */
24062     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)24063     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
24064         if (verifyDrawable(who) && what != null) {
24065             final long delay = when - SystemClock.uptimeMillis();
24066             if (mAttachInfo != null) {
24067                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
24068                         Choreographer.CALLBACK_ANIMATION, what, who,
24069                         Choreographer.subtractFrameDelay(delay));
24070             } else {
24071                 // Postpone the runnable until we know
24072                 // on which thread it needs to run.
24073                 getRunQueue().postDelayed(what, delay);
24074             }
24075         }
24076     }
24077 
24078     /**
24079      * Cancels a scheduled action on a drawable.
24080      *
24081      * @param who the recipient of the action
24082      * @param what the action to cancel
24083      */
24084     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)24085     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
24086         if (verifyDrawable(who) && what != null) {
24087             if (mAttachInfo != null) {
24088                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
24089                         Choreographer.CALLBACK_ANIMATION, what, who);
24090             }
24091             getRunQueue().removeCallbacks(what);
24092         }
24093     }
24094 
24095     /**
24096      * Unschedule any events associated with the given Drawable.  This can be
24097      * used when selecting a new Drawable into a view, so that the previous
24098      * one is completely unscheduled.
24099      *
24100      * @param who The Drawable to unschedule.
24101      *
24102      * @see #drawableStateChanged
24103      */
unscheduleDrawable(Drawable who)24104     public void unscheduleDrawable(Drawable who) {
24105         if (mAttachInfo != null && who != null) {
24106             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
24107                     Choreographer.CALLBACK_ANIMATION, null, who);
24108         }
24109     }
24110 
24111     /**
24112      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
24113      * that the View directionality can and will be resolved before its Drawables.
24114      *
24115      * Will call {@link View#onResolveDrawables} when resolution is done.
24116      *
24117      * @hide
24118      */
resolveDrawables()24119     protected void resolveDrawables() {
24120         // Drawables resolution may need to happen before resolving the layout direction (which is
24121         // done only during the measure() call).
24122         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
24123         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
24124         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
24125         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
24126         // direction to be resolved as its resolved value will be the same as its raw value.
24127         if (!isLayoutDirectionResolved() &&
24128                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
24129             return;
24130         }
24131 
24132         final int layoutDirection = isLayoutDirectionResolved() ?
24133                 getLayoutDirection() : getRawLayoutDirection();
24134 
24135         if (mBackground != null) {
24136             mBackground.setLayoutDirection(layoutDirection);
24137         }
24138         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
24139             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
24140         }
24141         if (mDefaultFocusHighlight != null) {
24142             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
24143         }
24144         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
24145         onResolveDrawables(layoutDirection);
24146     }
24147 
areDrawablesResolved()24148     boolean areDrawablesResolved() {
24149         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
24150     }
24151 
24152     /**
24153      * Called when layout direction has been resolved.
24154      *
24155      * The default implementation does nothing.
24156      *
24157      * @param layoutDirection The resolved layout direction.
24158      *
24159      * @see #LAYOUT_DIRECTION_LTR
24160      * @see #LAYOUT_DIRECTION_RTL
24161      *
24162      * @hide
24163      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)24164     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
24165     }
24166 
24167     /**
24168      * @hide
24169      */
24170     @TestApi
resetResolvedDrawables()24171     protected void resetResolvedDrawables() {
24172         resetResolvedDrawablesInternal();
24173     }
24174 
resetResolvedDrawablesInternal()24175     void resetResolvedDrawablesInternal() {
24176         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
24177     }
24178 
24179     /**
24180      * If your view subclass is displaying its own Drawable objects, it should
24181      * override this function and return true for any Drawable it is
24182      * displaying.  This allows animations for those drawables to be
24183      * scheduled.
24184      *
24185      * <p>Be sure to call through to the super class when overriding this
24186      * function.
24187      *
24188      * @param who The Drawable to verify.  Return true if it is one you are
24189      *            displaying, else return the result of calling through to the
24190      *            super class.
24191      *
24192      * @return boolean If true then the Drawable is being displayed in the
24193      *         view; else false and it is not allowed to animate.
24194      *
24195      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
24196      * @see #drawableStateChanged()
24197      */
24198     @CallSuper
verifyDrawable(@onNull Drawable who)24199     protected boolean verifyDrawable(@NonNull Drawable who) {
24200         // Avoid verifying the scroll bar drawable so that we don't end up in
24201         // an invalidation loop. This effectively prevents the scroll bar
24202         // drawable from triggering invalidations and scheduling runnables.
24203         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
24204                 || (mDefaultFocusHighlight == who);
24205     }
24206 
24207     /**
24208      * This function is called whenever the state of the view changes in such
24209      * a way that it impacts the state of drawables being shown.
24210      * <p>
24211      * If the View has a StateListAnimator, it will also be called to run necessary state
24212      * change animations.
24213      * <p>
24214      * Be sure to call through to the superclass when overriding this function.
24215      *
24216      * @see Drawable#setState(int[])
24217      */
24218     @CallSuper
drawableStateChanged()24219     protected void drawableStateChanged() {
24220         final int[] state = getDrawableState();
24221         boolean changed = false;
24222 
24223         final Drawable bg = mBackground;
24224         if (bg != null && bg.isStateful()) {
24225             changed |= bg.setState(state);
24226         }
24227 
24228         final Drawable hl = mDefaultFocusHighlight;
24229         if (hl != null && hl.isStateful()) {
24230             changed |= hl.setState(state);
24231         }
24232 
24233         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24234         if (fg != null && fg.isStateful()) {
24235             changed |= fg.setState(state);
24236         }
24237 
24238         if (mScrollCache != null) {
24239             final Drawable scrollBar = mScrollCache.scrollBar;
24240             if (scrollBar != null && scrollBar.isStateful()) {
24241                 changed |= scrollBar.setState(state)
24242                         && mScrollCache.state != ScrollabilityCache.OFF;
24243             }
24244         }
24245 
24246         if (mStateListAnimator != null) {
24247             mStateListAnimator.setState(state);
24248         }
24249 
24250         if (!isAggregatedVisible()) {
24251             // If we're not visible, skip any animated changes
24252             jumpDrawablesToCurrentState();
24253         }
24254 
24255         if (changed) {
24256             invalidate();
24257         }
24258     }
24259 
24260     /**
24261      * This function is called whenever the view hotspot changes and needs to
24262      * be propagated to drawables or child views managed by the view.
24263      * <p>
24264      * Dispatching to child views is handled by
24265      * {@link #dispatchDrawableHotspotChanged(float, float)}.
24266      * <p>
24267      * Be sure to call through to the superclass when overriding this function.
24268      *
24269      * @param x hotspot x coordinate
24270      * @param y hotspot y coordinate
24271      */
24272     @CallSuper
drawableHotspotChanged(float x, float y)24273     public void drawableHotspotChanged(float x, float y) {
24274         if (mBackground != null) {
24275             mBackground.setHotspot(x, y);
24276         }
24277         if (mDefaultFocusHighlight != null) {
24278             mDefaultFocusHighlight.setHotspot(x, y);
24279         }
24280         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
24281             mForegroundInfo.mDrawable.setHotspot(x, y);
24282         }
24283 
24284         dispatchDrawableHotspotChanged(x, y);
24285     }
24286 
24287     /**
24288      * Dispatches drawableHotspotChanged to all of this View's children.
24289      *
24290      * @param x hotspot x coordinate
24291      * @param y hotspot y coordinate
24292      * @see #drawableHotspotChanged(float, float)
24293      */
dispatchDrawableHotspotChanged(float x, float y)24294     public void dispatchDrawableHotspotChanged(float x, float y) {
24295     }
24296 
24297     /**
24298      * Call this to force a view to update its drawable state. This will cause
24299      * drawableStateChanged to be called on this view. Views that are interested
24300      * in the new state should call getDrawableState.
24301      *
24302      * @see #drawableStateChanged
24303      * @see #getDrawableState
24304      */
refreshDrawableState()24305     public void refreshDrawableState() {
24306         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
24307         drawableStateChanged();
24308 
24309         ViewParent parent = mParent;
24310         if (parent != null) {
24311             parent.childDrawableStateChanged(this);
24312         }
24313     }
24314 
24315     /**
24316      * Create a default focus highlight if it doesn't exist.
24317      * @return a default focus highlight.
24318      */
getDefaultFocusHighlightDrawable()24319     private Drawable getDefaultFocusHighlightDrawable() {
24320         if (mDefaultFocusHighlightCache == null) {
24321             if (mContext != null) {
24322                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
24323                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
24324                 mDefaultFocusHighlightCache = ta.getDrawable(0);
24325                 ta.recycle();
24326             }
24327         }
24328         return mDefaultFocusHighlightCache;
24329     }
24330 
24331     /**
24332      * Set the current default focus highlight.
24333      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
24334      */
setDefaultFocusHighlight(Drawable highlight)24335     private void setDefaultFocusHighlight(Drawable highlight) {
24336         mDefaultFocusHighlight = highlight;
24337         mDefaultFocusHighlightSizeChanged = true;
24338         if (highlight != null) {
24339             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24340                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24341             }
24342             highlight.setLayoutDirection(getLayoutDirection());
24343             if (highlight.isStateful()) {
24344                 highlight.setState(getDrawableState());
24345             }
24346             if (isAttachedToWindow()) {
24347                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24348             }
24349             // Set callback last, since the view may still be initializing.
24350             highlight.setCallback(this);
24351         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
24352                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
24353             mPrivateFlags |= PFLAG_SKIP_DRAW;
24354         }
24355         invalidate();
24356     }
24357 
24358     /**
24359      * Check whether we need to draw a default focus highlight when this view gets focused,
24360      * which requires:
24361      * <ul>
24362      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
24363      *         is not defined.</li>
24364      *     <li>This view is not in touch mode.</li>
24365      *     <li>This view doesn't opt out for a default focus highlight, via
24366      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
24367      *     <li>This view is attached to window.</li>
24368      * </ul>
24369      * @return {@code true} if a default focus highlight is needed.
24370      * @hide
24371      */
24372     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)24373     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
24374         final boolean lackFocusState = (background == null || !background.isStateful()
24375                 || !background.hasFocusStateSpecified())
24376                 && (foreground == null || !foreground.isStateful()
24377                 || !foreground.hasFocusStateSpecified());
24378         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
24379                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
24380     }
24381 
24382     /**
24383      * When this view is focused, switches on/off the default focused highlight.
24384      * <p>
24385      * This always happens when this view is focused, and only at this moment the default focus
24386      * highlight can be visible.
24387      */
switchDefaultFocusHighlight()24388     private void switchDefaultFocusHighlight() {
24389         if (isFocused()) {
24390             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
24391                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
24392             final boolean active = mDefaultFocusHighlight != null;
24393             if (needed && !active) {
24394                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
24395             } else if (!needed && active) {
24396                 // The highlight is no longer needed, so tear it down.
24397                 setDefaultFocusHighlight(null);
24398             }
24399         }
24400     }
24401 
24402     /**
24403      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
24404      * @param canvas the canvas where we're drawing the highlight.
24405      */
drawDefaultFocusHighlight(Canvas canvas)24406     private void drawDefaultFocusHighlight(Canvas canvas) {
24407         if (mDefaultFocusHighlight != null && isFocused()) {
24408             if (mDefaultFocusHighlightSizeChanged) {
24409                 mDefaultFocusHighlightSizeChanged = false;
24410                 final int l = mScrollX;
24411                 final int r = l + mRight - mLeft;
24412                 final int t = mScrollY;
24413                 final int b = t + mBottom - mTop;
24414                 mDefaultFocusHighlight.setBounds(l, t, r, b);
24415             }
24416             mDefaultFocusHighlight.draw(canvas);
24417         }
24418     }
24419 
24420     /**
24421      * Return an array of resource IDs of the drawable states representing the
24422      * current state of the view.
24423      *
24424      * @return The current drawable state
24425      *
24426      * @see Drawable#setState(int[])
24427      * @see #drawableStateChanged()
24428      * @see #onCreateDrawableState(int)
24429      */
getDrawableState()24430     public final int[] getDrawableState() {
24431         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
24432             return mDrawableState;
24433         } else {
24434             mDrawableState = onCreateDrawableState(0);
24435             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
24436             return mDrawableState;
24437         }
24438     }
24439 
24440     /**
24441      * Generate the new {@link android.graphics.drawable.Drawable} state for
24442      * this view. This is called by the view
24443      * system when the cached Drawable state is determined to be invalid.  To
24444      * retrieve the current state, you should use {@link #getDrawableState}.
24445      *
24446      * @param extraSpace if non-zero, this is the number of extra entries you
24447      * would like in the returned array in which you can place your own
24448      * states.
24449      *
24450      * @return Returns an array holding the current {@link Drawable} state of
24451      * the view.
24452      *
24453      * @see #mergeDrawableStates(int[], int[])
24454      */
onCreateDrawableState(int extraSpace)24455     protected int[] onCreateDrawableState(int extraSpace) {
24456         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
24457                 mParent instanceof View) {
24458             return ((View) mParent).onCreateDrawableState(extraSpace);
24459         }
24460 
24461         int[] drawableState;
24462 
24463         int privateFlags = mPrivateFlags;
24464 
24465         int viewStateIndex = 0;
24466         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
24467         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
24468         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
24469         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
24470         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
24471         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
24472         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
24473             // This is set if HW acceleration is requested, even if the current
24474             // process doesn't allow it.  This is just to allow app preview
24475             // windows to better match their app.
24476             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
24477         }
24478         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
24479 
24480         final int privateFlags2 = mPrivateFlags2;
24481         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
24482             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
24483         }
24484         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
24485             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
24486         }
24487 
24488         drawableState = StateSet.get(viewStateIndex);
24489 
24490         //noinspection ConstantIfStatement
24491         if (false) {
24492             Log.i("View", "drawableStateIndex=" + viewStateIndex);
24493             Log.i("View", toString()
24494                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
24495                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
24496                     + " fo=" + hasFocus()
24497                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
24498                     + " wf=" + hasWindowFocus()
24499                     + ": " + Arrays.toString(drawableState));
24500         }
24501 
24502         if (extraSpace == 0) {
24503             return drawableState;
24504         }
24505 
24506         final int[] fullState;
24507         if (drawableState != null) {
24508             fullState = new int[drawableState.length + extraSpace];
24509             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
24510         } else {
24511             fullState = new int[extraSpace];
24512         }
24513 
24514         return fullState;
24515     }
24516 
24517     /**
24518      * Merge your own state values in <var>additionalState</var> into the base
24519      * state values <var>baseState</var> that were returned by
24520      * {@link #onCreateDrawableState(int)}.
24521      *
24522      * @param baseState The base state values returned by
24523      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
24524      * own additional state values.
24525      *
24526      * @param additionalState The additional state values you would like
24527      * added to <var>baseState</var>; this array is not modified.
24528      *
24529      * @return As a convenience, the <var>baseState</var> array you originally
24530      * passed into the function is returned.
24531      *
24532      * @see #onCreateDrawableState(int)
24533      */
mergeDrawableStates(int[] baseState, int[] additionalState)24534     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
24535         final int N = baseState.length;
24536         int i = N - 1;
24537         while (i >= 0 && baseState[i] == 0) {
24538             i--;
24539         }
24540         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
24541         return baseState;
24542     }
24543 
24544     /**
24545      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
24546      * on all Drawable objects associated with this view.
24547      * <p>
24548      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
24549      * attached to this view.
24550      */
24551     @CallSuper
jumpDrawablesToCurrentState()24552     public void jumpDrawablesToCurrentState() {
24553         if (mBackground != null) {
24554             mBackground.jumpToCurrentState();
24555         }
24556         if (mStateListAnimator != null) {
24557             mStateListAnimator.jumpToCurrentState();
24558         }
24559         if (mDefaultFocusHighlight != null) {
24560             mDefaultFocusHighlight.jumpToCurrentState();
24561         }
24562         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
24563             mForegroundInfo.mDrawable.jumpToCurrentState();
24564         }
24565     }
24566 
24567     /**
24568      * Sets the background color for this view.
24569      * @param color the color of the background
24570      */
24571     @RemotableViewMethod
setBackgroundColor(@olorInt int color)24572     public void setBackgroundColor(@ColorInt int color) {
24573         if (mBackground instanceof ColorDrawable) {
24574             ((ColorDrawable) mBackground.mutate()).setColor(color);
24575             computeOpaqueFlags();
24576             mBackgroundResource = 0;
24577         } else {
24578             setBackground(new ColorDrawable(color));
24579         }
24580     }
24581 
24582     /**
24583      * Set the background to a given resource. The resource should refer to
24584      * a Drawable object or 0 to remove the background.
24585      * @param resid The identifier of the resource.
24586      *
24587      * @attr ref android.R.styleable#View_background
24588      */
24589     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)24590     public void setBackgroundResource(@DrawableRes int resid) {
24591         if (resid != 0 && resid == mBackgroundResource) {
24592             return;
24593         }
24594 
24595         Drawable d = null;
24596         if (resid != 0) {
24597             d = mContext.getDrawable(resid);
24598         }
24599         setBackground(d);
24600 
24601         mBackgroundResource = resid;
24602     }
24603 
24604     /**
24605      * Set the background to a given Drawable, or remove the background. If the
24606      * background has padding, this View's padding is set to the background's
24607      * padding. However, when a background is removed, this View's padding isn't
24608      * touched. If setting the padding is desired, please use
24609      * {@link #setPadding(int, int, int, int)}.
24610      *
24611      * @param background The Drawable to use as the background, or null to remove the
24612      *        background
24613      */
setBackground(Drawable background)24614     public void setBackground(Drawable background) {
24615         //noinspection deprecation
24616         setBackgroundDrawable(background);
24617     }
24618 
24619     /**
24620      * @deprecated use {@link #setBackground(Drawable)} instead
24621      */
24622     @Deprecated
setBackgroundDrawable(Drawable background)24623     public void setBackgroundDrawable(Drawable background) {
24624         computeOpaqueFlags();
24625 
24626         if (background == mBackground) {
24627             return;
24628         }
24629 
24630         boolean requestLayout = false;
24631 
24632         mBackgroundResource = 0;
24633 
24634         /*
24635          * Regardless of whether we're setting a new background or not, we want
24636          * to clear the previous drawable. setVisible first while we still have the callback set.
24637          */
24638         if (mBackground != null) {
24639             if (isAttachedToWindow()) {
24640                 mBackground.setVisible(false, false);
24641             }
24642             mBackground.setCallback(null);
24643             unscheduleDrawable(mBackground);
24644         }
24645 
24646         if (background != null) {
24647             Rect padding = sThreadLocal.get();
24648             if (padding == null) {
24649                 padding = new Rect();
24650                 sThreadLocal.set(padding);
24651             }
24652             resetResolvedDrawablesInternal();
24653             background.setLayoutDirection(getLayoutDirection());
24654             if (background.getPadding(padding)) {
24655                 resetResolvedPaddingInternal();
24656                 switch (background.getLayoutDirection()) {
24657                     case LAYOUT_DIRECTION_RTL:
24658                         mUserPaddingLeftInitial = padding.right;
24659                         mUserPaddingRightInitial = padding.left;
24660                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
24661                         break;
24662                     case LAYOUT_DIRECTION_LTR:
24663                     default:
24664                         mUserPaddingLeftInitial = padding.left;
24665                         mUserPaddingRightInitial = padding.right;
24666                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
24667                 }
24668                 mLeftPaddingDefined = false;
24669                 mRightPaddingDefined = false;
24670             }
24671 
24672             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
24673             // if it has a different minimum size, we should layout again
24674             if (mBackground == null
24675                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
24676                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
24677                 requestLayout = true;
24678             }
24679 
24680             // Set mBackground before we set this as the callback and start making other
24681             // background drawable state change calls. In particular, the setVisible call below
24682             // can result in drawables attempting to start animations or otherwise invalidate,
24683             // which requires the view set as the callback (us) to recognize the drawable as
24684             // belonging to it as per verifyDrawable.
24685             mBackground = background;
24686             if (background.isStateful()) {
24687                 background.setState(getDrawableState());
24688             }
24689             if (isAttachedToWindow()) {
24690                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24691             }
24692 
24693             applyBackgroundTint();
24694 
24695             // Set callback last, since the view may still be initializing.
24696             background.setCallback(this);
24697 
24698             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24699                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24700                 requestLayout = true;
24701             }
24702         } else {
24703             /* Remove the background */
24704             mBackground = null;
24705             if ((mViewFlags & WILL_NOT_DRAW) != 0
24706                     && (mDefaultFocusHighlight == null)
24707                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
24708                 mPrivateFlags |= PFLAG_SKIP_DRAW;
24709             }
24710 
24711             /*
24712              * When the background is set, we try to apply its padding to this
24713              * View. When the background is removed, we don't touch this View's
24714              * padding. This is noted in the Javadocs. Hence, we don't need to
24715              * requestLayout(), the invalidate() below is sufficient.
24716              */
24717 
24718             // The old background's minimum size could have affected this
24719             // View's layout, so let's requestLayout
24720             requestLayout = true;
24721         }
24722 
24723         computeOpaqueFlags();
24724 
24725         if (requestLayout) {
24726             requestLayout();
24727         }
24728 
24729         mBackgroundSizeChanged = true;
24730         invalidate(true);
24731         invalidateOutline();
24732     }
24733 
24734     /**
24735      * Gets the background drawable
24736      *
24737      * @return The drawable used as the background for this view, if any.
24738      *
24739      * @see #setBackground(Drawable)
24740      *
24741      * @attr ref android.R.styleable#View_background
24742      */
24743     @InspectableProperty
getBackground()24744     public Drawable getBackground() {
24745         return mBackground;
24746     }
24747 
24748     /**
24749      * Applies a tint to the background drawable. Does not modify the current tint
24750      * mode, which is {@link BlendMode#SRC_IN} by default.
24751      * <p>
24752      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
24753      * mutate the drawable and apply the specified tint and tint mode using
24754      * {@link Drawable#setTintList(ColorStateList)}.
24755      *
24756      * @param tint the tint to apply, may be {@code null} to clear tint
24757      *
24758      * @attr ref android.R.styleable#View_backgroundTint
24759      * @see #getBackgroundTintList()
24760      * @see Drawable#setTintList(ColorStateList)
24761      */
24762     @RemotableViewMethod
setBackgroundTintList(@ullable ColorStateList tint)24763     public void setBackgroundTintList(@Nullable ColorStateList tint) {
24764         if (mBackgroundTint == null) {
24765             mBackgroundTint = new TintInfo();
24766         }
24767         mBackgroundTint.mTintList = tint;
24768         mBackgroundTint.mHasTintList = true;
24769 
24770         applyBackgroundTint();
24771     }
24772 
24773     /**
24774      * Return the tint applied to the background drawable, if specified.
24775      *
24776      * @return the tint applied to the background drawable
24777      * @attr ref android.R.styleable#View_backgroundTint
24778      * @see #setBackgroundTintList(ColorStateList)
24779      */
24780     @InspectableProperty(name = "backgroundTint")
24781     @Nullable
getBackgroundTintList()24782     public ColorStateList getBackgroundTintList() {
24783         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
24784     }
24785 
24786     /**
24787      * Specifies the blending mode used to apply the tint specified by
24788      * {@link #setBackgroundTintList(ColorStateList)}} to the background
24789      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
24790      *
24791      * @param tintMode the blending mode used to apply the tint, may be
24792      *                 {@code null} to clear tint
24793      * @attr ref android.R.styleable#View_backgroundTintMode
24794      * @see #getBackgroundTintMode()
24795      * @see Drawable#setTintMode(PorterDuff.Mode)
24796      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)24797     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
24798         BlendMode mode = null;
24799         if (tintMode != null) {
24800             mode = BlendMode.fromValue(tintMode.nativeInt);
24801         }
24802 
24803         setBackgroundTintBlendMode(mode);
24804     }
24805 
24806     /**
24807      * Specifies the blending mode used to apply the tint specified by
24808      * {@link #setBackgroundTintList(ColorStateList)}} to the background
24809      * drawable. The default mode is {@link BlendMode#SRC_IN}.
24810      *
24811      * @param blendMode the blending mode used to apply the tint, may be
24812      *                 {@code null} to clear tint
24813      * @attr ref android.R.styleable#View_backgroundTintMode
24814      * @see #getBackgroundTintMode()
24815      * @see Drawable#setTintBlendMode(BlendMode)
24816      */
24817     @RemotableViewMethod
setBackgroundTintBlendMode(@ullable BlendMode blendMode)24818     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
24819         if (mBackgroundTint == null) {
24820             mBackgroundTint = new TintInfo();
24821         }
24822 
24823         mBackgroundTint.mBlendMode = blendMode;
24824         mBackgroundTint.mHasTintMode = true;
24825 
24826         applyBackgroundTint();
24827     }
24828 
24829     /**
24830      * Return the blending mode used to apply the tint to the background
24831      * drawable, if specified.
24832      *
24833      * @return the blending mode used to apply the tint to the background
24834      *         drawable
24835      * @attr ref android.R.styleable#View_backgroundTintMode
24836      * @see #setBackgroundTintBlendMode(BlendMode)
24837      *
24838      */
24839     @Nullable
24840     @InspectableProperty
getBackgroundTintMode()24841     public PorterDuff.Mode getBackgroundTintMode() {
24842         PorterDuff.Mode porterDuffMode;
24843         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
24844             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
24845         } else {
24846             porterDuffMode = null;
24847         }
24848         return porterDuffMode;
24849     }
24850 
24851     /**
24852      * Return the blending mode used to apply the tint to the background
24853      * drawable, if specified.
24854      *
24855      * @return the blending mode used to apply the tint to the background
24856      *         drawable, null if no blend has previously been configured
24857      * @attr ref android.R.styleable#View_backgroundTintMode
24858      * @see #setBackgroundTintBlendMode(BlendMode)
24859      */
getBackgroundTintBlendMode()24860     public @Nullable BlendMode getBackgroundTintBlendMode() {
24861         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
24862     }
24863 
applyBackgroundTint()24864     private void applyBackgroundTint() {
24865         if (mBackground != null && mBackgroundTint != null) {
24866             final TintInfo tintInfo = mBackgroundTint;
24867             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
24868                 mBackground = mBackground.mutate();
24869 
24870                 if (tintInfo.mHasTintList) {
24871                     mBackground.setTintList(tintInfo.mTintList);
24872                 }
24873 
24874                 if (tintInfo.mHasTintMode) {
24875                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
24876                 }
24877 
24878                 // The drawable (or one of its children) may not have been
24879                 // stateful before applying the tint, so let's try again.
24880                 if (mBackground.isStateful()) {
24881                     mBackground.setState(getDrawableState());
24882                 }
24883             }
24884         }
24885     }
24886 
24887     /**
24888      * Returns the drawable used as the foreground of this View. The
24889      * foreground drawable, if non-null, is always drawn on top of the view's content.
24890      *
24891      * @return a Drawable or null if no foreground was set
24892      *
24893      * @see #onDrawForeground(Canvas)
24894      */
24895     @InspectableProperty
getForeground()24896     public Drawable getForeground() {
24897         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24898     }
24899 
24900     /**
24901      * Supply a Drawable that is to be rendered on top of all of the content in the view.
24902      *
24903      * @param foreground the Drawable to be drawn on top of the children
24904      *
24905      * @attr ref android.R.styleable#View_foreground
24906      */
setForeground(Drawable foreground)24907     public void setForeground(Drawable foreground) {
24908         if (mForegroundInfo == null) {
24909             if (foreground == null) {
24910                 // Nothing to do.
24911                 return;
24912             }
24913             mForegroundInfo = new ForegroundInfo();
24914         }
24915 
24916         if (foreground == mForegroundInfo.mDrawable) {
24917             // Nothing to do
24918             return;
24919         }
24920 
24921         if (mForegroundInfo.mDrawable != null) {
24922             if (isAttachedToWindow()) {
24923                 mForegroundInfo.mDrawable.setVisible(false, false);
24924             }
24925             mForegroundInfo.mDrawable.setCallback(null);
24926             unscheduleDrawable(mForegroundInfo.mDrawable);
24927         }
24928 
24929         mForegroundInfo.mDrawable = foreground;
24930         mForegroundInfo.mBoundsChanged = true;
24931         if (foreground != null) {
24932             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24933                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24934             }
24935             foreground.setLayoutDirection(getLayoutDirection());
24936             if (foreground.isStateful()) {
24937                 foreground.setState(getDrawableState());
24938             }
24939             applyForegroundTint();
24940             if (isAttachedToWindow()) {
24941                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24942             }
24943             // Set callback last, since the view may still be initializing.
24944             foreground.setCallback(this);
24945         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
24946                 && (mDefaultFocusHighlight == null)) {
24947             mPrivateFlags |= PFLAG_SKIP_DRAW;
24948         }
24949         requestLayout();
24950         invalidate();
24951     }
24952 
24953     /**
24954      * Magic bit used to support features of framework-internal window decor implementation details.
24955      * This used to live exclusively in FrameLayout.
24956      *
24957      * @return true if the foreground should draw inside the padding region or false
24958      *         if it should draw inset by the view's padding
24959      * @hide internal use only; only used by FrameLayout and internal screen layouts.
24960      */
isForegroundInsidePadding()24961     public boolean isForegroundInsidePadding() {
24962         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
24963     }
24964 
24965     /**
24966      * Describes how the foreground is positioned.
24967      *
24968      * @return foreground gravity.
24969      *
24970      * @see #setForegroundGravity(int)
24971      *
24972      * @attr ref android.R.styleable#View_foregroundGravity
24973      */
24974     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()24975     public int getForegroundGravity() {
24976         return mForegroundInfo != null ? mForegroundInfo.mGravity
24977                 : Gravity.START | Gravity.TOP;
24978     }
24979 
24980     /**
24981      * Describes how the foreground is positioned. Defaults to START and TOP.
24982      *
24983      * @param gravity see {@link android.view.Gravity}
24984      *
24985      * @see #getForegroundGravity()
24986      *
24987      * @attr ref android.R.styleable#View_foregroundGravity
24988      */
setForegroundGravity(int gravity)24989     public void setForegroundGravity(int gravity) {
24990         if (mForegroundInfo == null) {
24991             mForegroundInfo = new ForegroundInfo();
24992         }
24993 
24994         if (mForegroundInfo.mGravity != gravity) {
24995             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
24996                 gravity |= Gravity.START;
24997             }
24998 
24999             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
25000                 gravity |= Gravity.TOP;
25001             }
25002 
25003             mForegroundInfo.mGravity = gravity;
25004             requestLayout();
25005         }
25006     }
25007 
25008     /**
25009      * Applies a tint to the foreground drawable. Does not modify the current tint
25010      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
25011      * <p>
25012      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
25013      * mutate the drawable and apply the specified tint and tint mode using
25014      * {@link Drawable#setTintList(ColorStateList)}.
25015      *
25016      * @param tint the tint to apply, may be {@code null} to clear tint
25017      *
25018      * @attr ref android.R.styleable#View_foregroundTint
25019      * @see #getForegroundTintList()
25020      * @see Drawable#setTintList(ColorStateList)
25021      */
25022     @RemotableViewMethod
setForegroundTintList(@ullable ColorStateList tint)25023     public void setForegroundTintList(@Nullable ColorStateList tint) {
25024         if (mForegroundInfo == null) {
25025             mForegroundInfo = new ForegroundInfo();
25026         }
25027         if (mForegroundInfo.mTintInfo == null) {
25028             mForegroundInfo.mTintInfo = new TintInfo();
25029         }
25030         mForegroundInfo.mTintInfo.mTintList = tint;
25031         mForegroundInfo.mTintInfo.mHasTintList = true;
25032 
25033         applyForegroundTint();
25034     }
25035 
25036     /**
25037      * Return the tint applied to the foreground drawable, if specified.
25038      *
25039      * @return the tint applied to the foreground drawable
25040      * @attr ref android.R.styleable#View_foregroundTint
25041      * @see #setForegroundTintList(ColorStateList)
25042      */
25043     @InspectableProperty(name = "foregroundTint")
25044     @Nullable
getForegroundTintList()25045     public ColorStateList getForegroundTintList() {
25046         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
25047                 ? mForegroundInfo.mTintInfo.mTintList : null;
25048     }
25049 
25050     /**
25051      * Specifies the blending mode used to apply the tint specified by
25052      * {@link #setForegroundTintList(ColorStateList)}} to the background
25053      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
25054      *
25055      * @param tintMode the blending mode used to apply the tint, may be
25056      *                 {@code null} to clear tint
25057      * @attr ref android.R.styleable#View_foregroundTintMode
25058      * @see #getForegroundTintMode()
25059      * @see Drawable#setTintMode(PorterDuff.Mode)
25060      *
25061      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)25062     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
25063         BlendMode mode = null;
25064         if (tintMode != null) {
25065             mode = BlendMode.fromValue(tintMode.nativeInt);
25066         }
25067         setForegroundTintBlendMode(mode);
25068     }
25069 
25070     /**
25071      * Specifies the blending mode used to apply the tint specified by
25072      * {@link #setForegroundTintList(ColorStateList)}} to the background
25073      * drawable. The default mode is {@link BlendMode#SRC_IN}.
25074      *
25075      * @param blendMode the blending mode used to apply the tint, may be
25076      *                 {@code null} to clear tint
25077      * @attr ref android.R.styleable#View_foregroundTintMode
25078      * @see #getForegroundTintMode()
25079      * @see Drawable#setTintBlendMode(BlendMode)
25080      */
25081     @RemotableViewMethod
setForegroundTintBlendMode(@ullable BlendMode blendMode)25082     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
25083         if (mForegroundInfo == null) {
25084             mForegroundInfo = new ForegroundInfo();
25085         }
25086         if (mForegroundInfo.mTintInfo == null) {
25087             mForegroundInfo.mTintInfo = new TintInfo();
25088         }
25089         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
25090         mForegroundInfo.mTintInfo.mHasTintMode = true;
25091 
25092         applyForegroundTint();
25093     }
25094 
25095     /**
25096      * Return the blending mode used to apply the tint to the foreground
25097      * drawable, if specified.
25098      *
25099      * @return the blending mode used to apply the tint to the foreground
25100      *         drawable
25101      * @attr ref android.R.styleable#View_foregroundTintMode
25102      * @see #setForegroundTintMode(PorterDuff.Mode)
25103      */
25104     @InspectableProperty
25105     @Nullable
getForegroundTintMode()25106     public PorterDuff.Mode getForegroundTintMode() {
25107         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
25108                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
25109         if (blendMode != null) {
25110             return BlendMode.blendModeToPorterDuffMode(blendMode);
25111         } else {
25112             return null;
25113         }
25114     }
25115 
25116     /**
25117      * Return the blending mode used to apply the tint to the foreground
25118      * drawable, if specified.
25119      *
25120      * @return the blending mode used to apply the tint to the foreground
25121      *         drawable
25122      * @attr ref android.R.styleable#View_foregroundTintMode
25123      * @see #setForegroundTintBlendMode(BlendMode)
25124      *
25125      */
getForegroundTintBlendMode()25126     public @Nullable BlendMode getForegroundTintBlendMode() {
25127         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
25128                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
25129     }
25130 
applyForegroundTint()25131     private void applyForegroundTint() {
25132         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
25133                 && mForegroundInfo.mTintInfo != null) {
25134             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
25135             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
25136                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
25137 
25138                 if (tintInfo.mHasTintList) {
25139                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
25140                 }
25141 
25142                 if (tintInfo.mHasTintMode) {
25143                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
25144                 }
25145 
25146                 // The drawable (or one of its children) may not have been
25147                 // stateful before applying the tint, so let's try again.
25148                 if (mForegroundInfo.mDrawable.isStateful()) {
25149                     mForegroundInfo.mDrawable.setState(getDrawableState());
25150                 }
25151             }
25152         }
25153     }
25154 
25155     /**
25156      * Get the drawable to be overlayed when a view is autofilled
25157      *
25158      * @return The drawable
25159      *
25160      * @throws IllegalStateException if the drawable could not be found.
25161      */
getAutofilledDrawable()25162     @Nullable private Drawable getAutofilledDrawable() {
25163         if (mAttachInfo == null) {
25164             return null;
25165         }
25166         // Lazily load the isAutofilled drawable.
25167         if (mAttachInfo.mAutofilledDrawable == null) {
25168             Context rootContext = getRootView().getContext();
25169             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
25170             int attributeResourceId = a.getResourceId(0, 0);
25171             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
25172             a.recycle();
25173         }
25174 
25175         return mAttachInfo.mAutofilledDrawable;
25176     }
25177 
25178     /**
25179      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
25180      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
25181      *
25182      * @param canvas The canvas to draw on
25183      */
drawAutofilledHighlight(@onNull Canvas canvas)25184     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
25185         if (isAutofilled() && !hideAutofillHighlight()) {
25186             Drawable autofilledHighlight = getAutofilledDrawable();
25187 
25188             if (autofilledHighlight != null) {
25189                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
25190                 autofilledHighlight.draw(canvas);
25191             }
25192         }
25193     }
25194 
25195     /**
25196      * Draw any foreground content for this view.
25197      *
25198      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
25199      * drawable or other view-specific decorations. The foreground is drawn on top of the
25200      * primary view content.</p>
25201      *
25202      * @param canvas canvas to draw into
25203      */
onDrawForeground(Canvas canvas)25204     public void onDrawForeground(Canvas canvas) {
25205         onDrawScrollIndicators(canvas);
25206         onDrawScrollBars(canvas);
25207 
25208         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
25209         if (foreground != null) {
25210             if (mForegroundInfo.mBoundsChanged) {
25211                 mForegroundInfo.mBoundsChanged = false;
25212                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
25213                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
25214 
25215                 if (mForegroundInfo.mInsidePadding) {
25216                     selfBounds.set(0, 0, getWidth(), getHeight());
25217                 } else {
25218                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
25219                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
25220                 }
25221 
25222                 final int ld = getLayoutDirection();
25223                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
25224                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
25225                 foreground.setBounds(overlayBounds);
25226             }
25227 
25228             foreground.draw(canvas);
25229         }
25230     }
25231 
25232     /**
25233      * Sets the padding. The view may add on the space required to display
25234      * the scrollbars, depending on the style and visibility of the scrollbars.
25235      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
25236      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
25237      * from the values set in this call.
25238      *
25239      * @attr ref android.R.styleable#View_padding
25240      * @attr ref android.R.styleable#View_paddingBottom
25241      * @attr ref android.R.styleable#View_paddingLeft
25242      * @attr ref android.R.styleable#View_paddingRight
25243      * @attr ref android.R.styleable#View_paddingTop
25244      * @param left the left padding in pixels
25245      * @param top the top padding in pixels
25246      * @param right the right padding in pixels
25247      * @param bottom the bottom padding in pixels
25248      */
setPadding(int left, int top, int right, int bottom)25249     public void setPadding(int left, int top, int right, int bottom) {
25250         resetResolvedPaddingInternal();
25251 
25252         mUserPaddingStart = UNDEFINED_PADDING;
25253         mUserPaddingEnd = UNDEFINED_PADDING;
25254 
25255         mUserPaddingLeftInitial = left;
25256         mUserPaddingRightInitial = right;
25257 
25258         mLeftPaddingDefined = true;
25259         mRightPaddingDefined = true;
25260 
25261         internalSetPadding(left, top, right, bottom);
25262     }
25263 
25264     /**
25265      * @hide
25266      */
25267     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)25268     protected void internalSetPadding(int left, int top, int right, int bottom) {
25269         mUserPaddingLeft = left;
25270         mUserPaddingRight = right;
25271         mUserPaddingBottom = bottom;
25272 
25273         final int viewFlags = mViewFlags;
25274         boolean changed = false;
25275 
25276         // Common case is there are no scroll bars.
25277         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
25278             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
25279                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
25280                         ? 0 : getVerticalScrollbarWidth();
25281                 switch (mVerticalScrollbarPosition) {
25282                     case SCROLLBAR_POSITION_DEFAULT:
25283                         if (isLayoutRtl()) {
25284                             left += offset;
25285                         } else {
25286                             right += offset;
25287                         }
25288                         break;
25289                     case SCROLLBAR_POSITION_RIGHT:
25290                         right += offset;
25291                         break;
25292                     case SCROLLBAR_POSITION_LEFT:
25293                         left += offset;
25294                         break;
25295                 }
25296             }
25297             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
25298                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
25299                         ? 0 : getHorizontalScrollbarHeight();
25300             }
25301         }
25302 
25303         if (mPaddingLeft != left) {
25304             changed = true;
25305             mPaddingLeft = left;
25306         }
25307         if (mPaddingTop != top) {
25308             changed = true;
25309             mPaddingTop = top;
25310         }
25311         if (mPaddingRight != right) {
25312             changed = true;
25313             mPaddingRight = right;
25314         }
25315         if (mPaddingBottom != bottom) {
25316             changed = true;
25317             mPaddingBottom = bottom;
25318         }
25319 
25320         if (changed) {
25321             requestLayout();
25322             invalidateOutline();
25323         }
25324     }
25325 
25326     /**
25327      * Sets the relative padding. The view may add on the space required to display
25328      * the scrollbars, depending on the style and visibility of the scrollbars.
25329      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
25330      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
25331      * from the values set in this call.
25332      *
25333      * @attr ref android.R.styleable#View_padding
25334      * @attr ref android.R.styleable#View_paddingBottom
25335      * @attr ref android.R.styleable#View_paddingStart
25336      * @attr ref android.R.styleable#View_paddingEnd
25337      * @attr ref android.R.styleable#View_paddingTop
25338      * @param start the start padding in pixels
25339      * @param top the top padding in pixels
25340      * @param end the end padding in pixels
25341      * @param bottom the bottom padding in pixels
25342      */
setPaddingRelative(int start, int top, int end, int bottom)25343     public void setPaddingRelative(int start, int top, int end, int bottom) {
25344         resetResolvedPaddingInternal();
25345 
25346         mUserPaddingStart = start;
25347         mUserPaddingEnd = end;
25348         mLeftPaddingDefined = true;
25349         mRightPaddingDefined = true;
25350 
25351         switch(getLayoutDirection()) {
25352             case LAYOUT_DIRECTION_RTL:
25353                 mUserPaddingLeftInitial = end;
25354                 mUserPaddingRightInitial = start;
25355                 internalSetPadding(end, top, start, bottom);
25356                 break;
25357             case LAYOUT_DIRECTION_LTR:
25358             default:
25359                 mUserPaddingLeftInitial = start;
25360                 mUserPaddingRightInitial = end;
25361                 internalSetPadding(start, top, end, bottom);
25362         }
25363     }
25364 
25365     /**
25366      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
25367      * resource ID of the source layout.
25368      *
25369      * @return The layout resource id if this view was inflated from XML, otherwise
25370      * {@link Resources#ID_NULL}.
25371      */
25372     @LayoutRes
getSourceLayoutResId()25373     public int getSourceLayoutResId() {
25374         return mSourceLayoutId;
25375     }
25376 
25377     /**
25378      * Returns the top padding of this view.
25379      *
25380      * @return the top padding in pixels
25381      */
25382     @InspectableProperty
getPaddingTop()25383     public int getPaddingTop() {
25384         return mPaddingTop;
25385     }
25386 
25387     /**
25388      * Returns the bottom padding of this view. If there are inset and enabled
25389      * scrollbars, this value may include the space required to display the
25390      * scrollbars as well.
25391      *
25392      * @return the bottom padding in pixels
25393      */
25394     @InspectableProperty
getPaddingBottom()25395     public int getPaddingBottom() {
25396         return mPaddingBottom;
25397     }
25398 
25399     /**
25400      * Returns the left padding of this view. If there are inset and enabled
25401      * scrollbars, this value may include the space required to display the
25402      * scrollbars as well.
25403      *
25404      * @return the left padding in pixels
25405      */
25406     @InspectableProperty
getPaddingLeft()25407     public int getPaddingLeft() {
25408         if (!isPaddingResolved()) {
25409             resolvePadding();
25410         }
25411         return mPaddingLeft;
25412     }
25413 
25414     /**
25415      * Returns the start padding of this view depending on its resolved layout direction.
25416      * If there are inset and enabled scrollbars, this value may include the space
25417      * required to display the scrollbars as well.
25418      *
25419      * @return the start padding in pixels
25420      */
getPaddingStart()25421     public int getPaddingStart() {
25422         if (!isPaddingResolved()) {
25423             resolvePadding();
25424         }
25425         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
25426                 mPaddingRight : mPaddingLeft;
25427     }
25428 
25429     /**
25430      * Returns the right padding of this view. If there are inset and enabled
25431      * scrollbars, this value may include the space required to display the
25432      * scrollbars as well.
25433      *
25434      * @return the right padding in pixels
25435      */
25436     @InspectableProperty
getPaddingRight()25437     public int getPaddingRight() {
25438         if (!isPaddingResolved()) {
25439             resolvePadding();
25440         }
25441         return mPaddingRight;
25442     }
25443 
25444     /**
25445      * Returns the end padding of this view depending on its resolved layout direction.
25446      * If there are inset and enabled scrollbars, this value may include the space
25447      * required to display the scrollbars as well.
25448      *
25449      * @return the end padding in pixels
25450      */
getPaddingEnd()25451     public int getPaddingEnd() {
25452         if (!isPaddingResolved()) {
25453             resolvePadding();
25454         }
25455         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
25456                 mPaddingLeft : mPaddingRight;
25457     }
25458 
25459     /**
25460      * Return if the padding has been set through relative values
25461      * {@link #setPaddingRelative(int, int, int, int)} or through
25462      * @attr ref android.R.styleable#View_paddingStart or
25463      * @attr ref android.R.styleable#View_paddingEnd
25464      *
25465      * @return true if the padding is relative or false if it is not.
25466      */
isPaddingRelative()25467     public boolean isPaddingRelative() {
25468         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
25469     }
25470 
computeOpticalInsets()25471     Insets computeOpticalInsets() {
25472         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
25473     }
25474 
25475     /**
25476      * @hide
25477      */
25478     @UnsupportedAppUsage
resetPaddingToInitialValues()25479     public void resetPaddingToInitialValues() {
25480         if (isRtlCompatibilityMode()) {
25481             mPaddingLeft = mUserPaddingLeftInitial;
25482             mPaddingRight = mUserPaddingRightInitial;
25483             return;
25484         }
25485         if (isLayoutRtl()) {
25486             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
25487             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
25488         } else {
25489             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
25490             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
25491         }
25492     }
25493 
25494     /**
25495      * @hide
25496      */
getOpticalInsets()25497     public Insets getOpticalInsets() {
25498         if (mLayoutInsets == null) {
25499             mLayoutInsets = computeOpticalInsets();
25500         }
25501         return mLayoutInsets;
25502     }
25503 
25504     /**
25505      * Set this view's optical insets.
25506      *
25507      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
25508      * property. Views that compute their own optical insets should call it as part of measurement.
25509      * This method does not request layout. If you are setting optical insets outside of
25510      * measure/layout itself you will want to call requestLayout() yourself.
25511      * </p>
25512      * @hide
25513      */
setOpticalInsets(Insets insets)25514     public void setOpticalInsets(Insets insets) {
25515         mLayoutInsets = insets;
25516     }
25517 
25518     /**
25519      * Changes the selection state of this view. A view can be selected or not.
25520      * Note that selection is not the same as focus. Views are typically
25521      * selected in the context of an AdapterView like ListView or GridView;
25522      * the selected view is the view that is highlighted.
25523      *
25524      * @param selected true if the view must be selected, false otherwise
25525      */
setSelected(boolean selected)25526     public void setSelected(boolean selected) {
25527         //noinspection DoubleNegation
25528         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
25529             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
25530             if (!selected) resetPressedState();
25531             invalidate(true);
25532             refreshDrawableState();
25533             dispatchSetSelected(selected);
25534             if (selected) {
25535                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
25536             } else {
25537                 notifyViewAccessibilityStateChangedIfNeeded(
25538                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
25539             }
25540         }
25541     }
25542 
25543     /**
25544      * Dispatch setSelected to all of this View's children.
25545      *
25546      * @see #setSelected(boolean)
25547      *
25548      * @param selected The new selected state
25549      */
dispatchSetSelected(boolean selected)25550     protected void dispatchSetSelected(boolean selected) {
25551     }
25552 
25553     /**
25554      * Indicates the selection state of this view.
25555      *
25556      * @return true if the view is selected, false otherwise
25557      */
25558     @ViewDebug.ExportedProperty
25559     @InspectableProperty(hasAttributeId = false)
isSelected()25560     public boolean isSelected() {
25561         return (mPrivateFlags & PFLAG_SELECTED) != 0;
25562     }
25563 
25564     /**
25565      * Changes the activated state of this view. A view can be activated or not.
25566      * Note that activation is not the same as selection.  Selection is
25567      * a transient property, representing the view (hierarchy) the user is
25568      * currently interacting with.  Activation is a longer-term state that the
25569      * user can move views in and out of.  For example, in a list view with
25570      * single or multiple selection enabled, the views in the current selection
25571      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
25572      * here.)  The activated state is propagated down to children of the view it
25573      * is set on.
25574      *
25575      * @param activated true if the view must be activated, false otherwise
25576      */
setActivated(boolean activated)25577     public void setActivated(boolean activated) {
25578         //noinspection DoubleNegation
25579         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
25580             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
25581             invalidate(true);
25582             refreshDrawableState();
25583             dispatchSetActivated(activated);
25584         }
25585     }
25586 
25587     /**
25588      * Dispatch setActivated to all of this View's children.
25589      *
25590      * @see #setActivated(boolean)
25591      *
25592      * @param activated The new activated state
25593      */
dispatchSetActivated(boolean activated)25594     protected void dispatchSetActivated(boolean activated) {
25595     }
25596 
25597     /**
25598      * Indicates the activation state of this view.
25599      *
25600      * @return true if the view is activated, false otherwise
25601      */
25602     @ViewDebug.ExportedProperty
25603     @InspectableProperty(hasAttributeId = false)
isActivated()25604     public boolean isActivated() {
25605         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
25606     }
25607 
25608     /**
25609      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
25610      * observer can be used to get notifications when global events, like
25611      * layout, happen.
25612      *
25613      * The returned ViewTreeObserver observer is not guaranteed to remain
25614      * valid for the lifetime of this View. If the caller of this method keeps
25615      * a long-lived reference to ViewTreeObserver, it should always check for
25616      * the return value of {@link ViewTreeObserver#isAlive()}.
25617      *
25618      * @return The ViewTreeObserver for this view's hierarchy.
25619      */
getViewTreeObserver()25620     public ViewTreeObserver getViewTreeObserver() {
25621         if (mAttachInfo != null) {
25622             return mAttachInfo.mTreeObserver;
25623         }
25624         if (mFloatingTreeObserver == null) {
25625             mFloatingTreeObserver = new ViewTreeObserver(mContext);
25626         }
25627         return mFloatingTreeObserver;
25628     }
25629 
25630     /**
25631      * <p>Finds the topmost view in the current view hierarchy.</p>
25632      *
25633      * @return the topmost view containing this view
25634      */
getRootView()25635     public View getRootView() {
25636         if (mAttachInfo != null) {
25637             final View v = mAttachInfo.mRootView;
25638             if (v != null) {
25639                 return v;
25640             }
25641         }
25642 
25643         View parent = this;
25644 
25645         while (parent.mParent instanceof View) {
25646             parent = (View) parent.mParent;
25647         }
25648 
25649         return parent;
25650     }
25651 
25652     /**
25653      * Transforms a motion event from view-local coordinates to on-screen
25654      * coordinates.
25655      *
25656      * @param ev the view-local motion event
25657      * @return false if the transformation could not be applied
25658      * @hide
25659      */
25660     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toGlobalMotionEvent(MotionEvent ev)25661     public boolean toGlobalMotionEvent(MotionEvent ev) {
25662         final AttachInfo info = mAttachInfo;
25663         if (info == null) {
25664             return false;
25665         }
25666 
25667         final Matrix m = info.mTmpMatrix;
25668         m.set(Matrix.IDENTITY_MATRIX);
25669         transformMatrixToGlobal(m);
25670         ev.transform(m);
25671         return true;
25672     }
25673 
25674     /**
25675      * Transforms a motion event from on-screen coordinates to view-local
25676      * coordinates.
25677      *
25678      * @param ev the on-screen motion event
25679      * @return false if the transformation could not be applied
25680      * @hide
25681      */
25682     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toLocalMotionEvent(MotionEvent ev)25683     public boolean toLocalMotionEvent(MotionEvent ev) {
25684         final AttachInfo info = mAttachInfo;
25685         if (info == null) {
25686             return false;
25687         }
25688 
25689         final Matrix m = info.mTmpMatrix;
25690         m.set(Matrix.IDENTITY_MATRIX);
25691         transformMatrixToLocal(m);
25692         ev.transform(m);
25693         return true;
25694     }
25695 
25696     /**
25697      * Modifies the input matrix such that it maps view-local coordinates to
25698      * on-screen coordinates.
25699      *
25700      * @param matrix input matrix to modify
25701      */
transformMatrixToGlobal(@onNull Matrix matrix)25702     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
25703         final ViewParent parent = mParent;
25704         if (parent instanceof View) {
25705             final View vp = (View) parent;
25706             vp.transformMatrixToGlobal(matrix);
25707             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
25708         } else if (parent instanceof ViewRootImpl) {
25709             final ViewRootImpl vr = (ViewRootImpl) parent;
25710             vr.transformMatrixToGlobal(matrix);
25711             matrix.preTranslate(0, -vr.mCurScrollY);
25712         }
25713 
25714         matrix.preTranslate(mLeft, mTop);
25715 
25716         if (!hasIdentityMatrix()) {
25717             matrix.preConcat(getMatrix());
25718         }
25719     }
25720 
25721     /**
25722      * Modifies the input matrix such that it maps on-screen coordinates to
25723      * view-local coordinates.
25724      *
25725      * @param matrix input matrix to modify
25726      */
transformMatrixToLocal(@onNull Matrix matrix)25727     public void transformMatrixToLocal(@NonNull Matrix matrix) {
25728         final ViewParent parent = mParent;
25729         if (parent instanceof View) {
25730             final View vp = (View) parent;
25731             vp.transformMatrixToLocal(matrix);
25732             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
25733         } else if (parent instanceof ViewRootImpl) {
25734             final ViewRootImpl vr = (ViewRootImpl) parent;
25735             vr.transformMatrixToLocal(matrix);
25736             matrix.postTranslate(0, vr.mCurScrollY);
25737         }
25738 
25739         matrix.postTranslate(-mLeft, -mTop);
25740 
25741         if (!hasIdentityMatrix()) {
25742             matrix.postConcat(getInverseMatrix());
25743         }
25744     }
25745 
25746     /**
25747      * @hide
25748      */
25749     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
25750             @ViewDebug.IntToString(from = 0, to = "x"),
25751             @ViewDebug.IntToString(from = 1, to = "y")
25752     })
25753     @UnsupportedAppUsage
getLocationOnScreen()25754     public int[] getLocationOnScreen() {
25755         int[] location = new int[2];
25756         getLocationOnScreen(location);
25757         return location;
25758     }
25759 
25760     /**
25761      * Gets the coordinates of this view in the coordinate space of the device
25762      * screen, irrespective of system decorations and whether the system is in
25763      * multi-window mode.
25764      *
25765      * <p>In multi-window mode, the coordinate space encompasses the entire
25766      * device screen, ignoring the bounds of the app window. For example, if the
25767      * view is in the bottom portion of a horizontal split screen, the top edge
25768      * of the screen&mdash;not the top edge of the window&mdash;is the origin
25769      * from which the y-coordinate is calculated.
25770      *
25771      * <p>In multiple-screen scenarios, the coordinate space can span screens.
25772      * For example, if the app is spanning both screens of a dual-screen device
25773      * and the view is located on the right-hand screen, the x-coordinate is
25774      * calculated from the left edge of the left-hand screen to the left edge of
25775      * the view. When the app is restricted to a single screen in a
25776      * multiple-screen environment, the coordinate space includes only the
25777      * screen on which the app is running.
25778      *
25779      * <p>After the method returns, the argument array contains the x and y
25780      * coordinates of the view relative to the view's left and top edges,
25781      * respectively.
25782      *
25783      * @param outLocation A two-element integer array in which the view
25784      *      coordinates are stored. The x-coordinate is at index 0; the
25785      *      y-coordinate, at index 1.
25786      */
getLocationOnScreen(@ize2) int[] outLocation)25787     public void getLocationOnScreen(@Size(2) int[] outLocation) {
25788         getLocationInWindow(outLocation);
25789 
25790         final AttachInfo info = mAttachInfo;
25791         if (info != null) {
25792             outLocation[0] += info.mWindowLeft;
25793             outLocation[1] += info.mWindowTop;
25794             // If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
25795             // applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
25796             info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
25797         }
25798     }
25799 
25800     /**
25801      * Gets the coordinates of this view in the coordinate space of the window
25802      * that contains the view, irrespective of system decorations.
25803      *
25804      * <p>In multi-window mode, the origin of the coordinate space is the
25805      * top left corner of the window that contains the view. In full screen
25806      * mode, the origin is the top left corner of the device screen.
25807      *
25808      * <p>In multiple-screen scenarios, if the app spans multiple screens, the
25809      * coordinate space also spans multiple screens. But if the app is
25810      * restricted to a single screen, the coordinate space includes only the
25811      * screen on which the app is running.
25812      *
25813      * <p>After the method returns, the argument array contains the x and y
25814      * coordinates of the view relative to the view's left and top edges,
25815      * respectively.
25816      *
25817      * @param outLocation A two-element integer array in which the view
25818      *      coordinates are stored. The x-coordinate is at index 0; the
25819      *      y-coordinate, at index 1.
25820      */
getLocationInWindow(@ize2) int[] outLocation)25821     public void getLocationInWindow(@Size(2) int[] outLocation) {
25822         if (outLocation == null || outLocation.length < 2) {
25823             throw new IllegalArgumentException("outLocation must be an array of two integers");
25824         }
25825 
25826         outLocation[0] = 0;
25827         outLocation[1] = 0;
25828 
25829         transformFromViewToWindowSpace(outLocation);
25830     }
25831 
25832     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)25833     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
25834         if (inOutLocation == null || inOutLocation.length < 2) {
25835             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
25836         }
25837 
25838         if (mAttachInfo == null) {
25839             // When the view is not attached to a window, this method does not make sense
25840             inOutLocation[0] = inOutLocation[1] = 0;
25841             return;
25842         }
25843 
25844         float position[] = mAttachInfo.mTmpTransformLocation;
25845         position[0] = inOutLocation[0];
25846         position[1] = inOutLocation[1];
25847 
25848         if (!hasIdentityMatrix()) {
25849             getMatrix().mapPoints(position);
25850         }
25851 
25852         position[0] += mLeft;
25853         position[1] += mTop;
25854 
25855         ViewParent viewParent = mParent;
25856         while (viewParent instanceof View) {
25857             final View view = (View) viewParent;
25858 
25859             position[0] -= view.mScrollX;
25860             position[1] -= view.mScrollY;
25861 
25862             if (!view.hasIdentityMatrix()) {
25863                 view.getMatrix().mapPoints(position);
25864             }
25865 
25866             position[0] += view.mLeft;
25867             position[1] += view.mTop;
25868 
25869             viewParent = view.mParent;
25870          }
25871 
25872         if (viewParent instanceof ViewRootImpl) {
25873             // *cough*
25874             final ViewRootImpl vr = (ViewRootImpl) viewParent;
25875             position[1] -= vr.mCurScrollY;
25876         }
25877 
25878         inOutLocation[0] = Math.round(position[0]);
25879         inOutLocation[1] = Math.round(position[1]);
25880     }
25881 
25882     /**
25883      * @param id the id of the view to be found
25884      * @return the view of the specified id, null if cannot be found
25885      * @hide
25886      */
findViewTraversal(@dRes int id)25887     protected <T extends View> T findViewTraversal(@IdRes int id) {
25888         if (id == mID) {
25889             return (T) this;
25890         }
25891         return null;
25892     }
25893 
25894     /**
25895      * @param tag the tag of the view to be found
25896      * @return the view of specified tag, null if cannot be found
25897      * @hide
25898      */
findViewWithTagTraversal(Object tag)25899     protected <T extends View> T findViewWithTagTraversal(Object tag) {
25900         if (tag != null && tag.equals(mTag)) {
25901             return (T) this;
25902         }
25903         return null;
25904     }
25905 
25906     /**
25907      * @param predicate The predicate to evaluate.
25908      * @param childToSkip If not null, ignores this child during the recursive traversal.
25909      * @return The first view that matches the predicate or null.
25910      * @hide
25911      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)25912     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
25913             View childToSkip) {
25914         if (predicate.test(this)) {
25915             return (T) this;
25916         }
25917         return null;
25918     }
25919 
25920     /**
25921      * Finds the first descendant view with the given ID, the view itself if
25922      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
25923      * (< 0) or there is no matching view in the hierarchy.
25924      * <p>
25925      * <strong>Note:</strong> In most cases -- depending on compiler support --
25926      * the resulting view is automatically cast to the target class type. If
25927      * the target class type is unconstrained, an explicit cast may be
25928      * necessary.
25929      *
25930      * @param id the ID to search for
25931      * @return a view with given ID if found, or {@code null} otherwise
25932      * @see View#requireViewById(int)
25933      */
25934     @Nullable
findViewById(@dRes int id)25935     public final <T extends View> T findViewById(@IdRes int id) {
25936         if (id == NO_ID) {
25937             return null;
25938         }
25939         return findViewTraversal(id);
25940     }
25941 
25942     /**
25943      * Finds the first descendant view with the given ID, the view itself if the ID matches
25944      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
25945      * matching view in the hierarchy.
25946      * <p>
25947      * <strong>Note:</strong> In most cases -- depending on compiler support --
25948      * the resulting view is automatically cast to the target class type. If
25949      * the target class type is unconstrained, an explicit cast may be
25950      * necessary.
25951      *
25952      * @param id the ID to search for
25953      * @return a view with given ID
25954      * @see View#findViewById(int)
25955      */
25956     @NonNull
requireViewById(@dRes int id)25957     public final <T extends View> T requireViewById(@IdRes int id) {
25958         T view = findViewById(id);
25959         if (view == null) {
25960             throw new IllegalArgumentException("ID does not reference a View inside this View");
25961         }
25962         return view;
25963     }
25964 
25965     /**
25966      * Performs the traversal to find a view by its unique and stable accessibility id.
25967      *
25968      * <strong>Note:</strong>This method does not stop at the root namespace
25969      * boundary since the user can touch the screen at an arbitrary location
25970      * potentially crossing the root namespace boundary which will send an
25971      * accessibility event to accessibility services and they should be able
25972      * to obtain the event source. Also accessibility ids are guaranteed to be
25973      * unique in the window.
25974      *
25975      * @param accessibilityId The accessibility id.
25976      * @return The found view.
25977      * @hide
25978      */
findViewByAccessibilityIdTraversal(int accessibilityId)25979     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
25980         if (getAccessibilityViewId() == accessibilityId) {
25981             return (T) this;
25982         }
25983         return null;
25984     }
25985 
25986     /**
25987      * Performs the traversal to find a view by its autofill id.
25988      *
25989      * <strong>Note:</strong>This method does not stop at the root namespace
25990      * boundary.
25991      *
25992      * @param autofillId The autofill id.
25993      * @return The found view.
25994      * @hide
25995      */
findViewByAutofillIdTraversal(int autofillId)25996     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
25997         if (getAutofillViewId() == autofillId) {
25998             return (T) this;
25999         }
26000         return null;
26001     }
26002 
26003     /**
26004      * Look for a child view with the given tag.  If this view has the given
26005      * tag, return this view.
26006      *
26007      * @param tag The tag to search for, using "tag.equals(getTag())".
26008      * @return The View that has the given tag in the hierarchy or null
26009      */
findViewWithTag(Object tag)26010     public final <T extends View> T findViewWithTag(Object tag) {
26011         if (tag == null) {
26012             return null;
26013         }
26014         return findViewWithTagTraversal(tag);
26015     }
26016 
26017     /**
26018      * Look for a child view that matches the specified predicate.
26019      * If this view matches the predicate, return this view.
26020      *
26021      * @param predicate The predicate to evaluate.
26022      * @return The first view that matches the predicate or null.
26023      * @hide
26024      */
findViewByPredicate(Predicate<View> predicate)26025     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
26026         return findViewByPredicateTraversal(predicate, null);
26027     }
26028 
26029     /**
26030      * Look for a child view that matches the specified predicate,
26031      * starting with the specified view and its descendents and then
26032      * recusively searching the ancestors and siblings of that view
26033      * until this view is reached.
26034      *
26035      * This method is useful in cases where the predicate does not match
26036      * a single unique view (perhaps multiple views use the same id)
26037      * and we are trying to find the view that is "closest" in scope to the
26038      * starting view.
26039      *
26040      * @param start The view to start from.
26041      * @param predicate The predicate to evaluate.
26042      * @return The first view that matches the predicate or null.
26043      * @hide
26044      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)26045     public final <T extends View> T findViewByPredicateInsideOut(
26046             View start, Predicate<View> predicate) {
26047         View childToSkip = null;
26048         for (;;) {
26049             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
26050             if (view != null || start == this) {
26051                 return view;
26052             }
26053 
26054             ViewParent parent = start.getParent();
26055             if (parent == null || !(parent instanceof View)) {
26056                 return null;
26057             }
26058 
26059             childToSkip = start;
26060             start = (View) parent;
26061         }
26062     }
26063 
26064     /**
26065      * Sets the identifier for this view. The identifier does not have to be
26066      * unique in this view's hierarchy. The identifier should be a positive
26067      * number.
26068      *
26069      * @see #NO_ID
26070      * @see #getId()
26071      * @see #findViewById(int)
26072      *
26073      * @param id a number used to identify the view
26074      *
26075      * @attr ref android.R.styleable#View_id
26076      */
setId(@dRes int id)26077     public void setId(@IdRes int id) {
26078         mID = id;
26079         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
26080             mID = generateViewId();
26081         }
26082     }
26083 
26084     /**
26085      * {@hide}
26086      *
26087      * @param isRoot true if the view belongs to the root namespace, false
26088      *        otherwise
26089      */
26090     @UnsupportedAppUsage
26091     @TestApi
setIsRootNamespace(boolean isRoot)26092     public void setIsRootNamespace(boolean isRoot) {
26093         if (isRoot) {
26094             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
26095         } else {
26096             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
26097         }
26098     }
26099 
26100     /**
26101      * {@hide}
26102      *
26103      * @return true if the view belongs to the root namespace, false otherwise
26104      */
26105     @UnsupportedAppUsage
isRootNamespace()26106     public boolean isRootNamespace() {
26107         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
26108     }
26109 
26110     /**
26111      * Returns this view's identifier.
26112      *
26113      * @return a positive integer used to identify the view or {@link #NO_ID}
26114      *         if the view has no ID
26115      *
26116      * @see #setId(int)
26117      * @see #findViewById(int)
26118      * @attr ref android.R.styleable#View_id
26119      */
26120     @IdRes
26121     @ViewDebug.CapturedViewProperty
26122     @InspectableProperty
getId()26123     public int getId() {
26124         return mID;
26125     }
26126 
26127     /**
26128      * Get the identifier used for this view by the drawing system.
26129      *
26130      * @see RenderNode#getUniqueId()
26131      * @return A long that uniquely identifies this view's drawing component
26132      */
getUniqueDrawingId()26133     public long getUniqueDrawingId() {
26134         return mRenderNode.getUniqueId();
26135     }
26136 
26137     /**
26138      * Returns this view's tag.
26139      *
26140      * @return the Object stored in this view as a tag, or {@code null} if not
26141      *         set
26142      *
26143      * @see #setTag(Object)
26144      * @see #getTag(int)
26145      */
26146     @ViewDebug.ExportedProperty
26147     @InspectableProperty
getTag()26148     public Object getTag() {
26149         return mTag;
26150     }
26151 
26152     /**
26153      * Sets the tag associated with this view. A tag can be used to mark
26154      * a view in its hierarchy and does not have to be unique within the
26155      * hierarchy. Tags can also be used to store data within a view without
26156      * resorting to another data structure.
26157      *
26158      * @param tag an Object to tag the view with
26159      *
26160      * @see #getTag()
26161      * @see #setTag(int, Object)
26162      */
setTag(final Object tag)26163     public void setTag(final Object tag) {
26164         mTag = tag;
26165     }
26166 
26167     /**
26168      * Returns the tag associated with this view and the specified key.
26169      *
26170      * @param key The key identifying the tag
26171      *
26172      * @return the Object stored in this view as a tag, or {@code null} if not
26173      *         set
26174      *
26175      * @see #setTag(int, Object)
26176      * @see #getTag()
26177      */
getTag(int key)26178     public Object getTag(int key) {
26179         if (mKeyedTags != null) return mKeyedTags.get(key);
26180         return null;
26181     }
26182 
26183     /**
26184      * Sets a tag associated with this view and a key. A tag can be used
26185      * to mark a view in its hierarchy and does not have to be unique within
26186      * the hierarchy. Tags can also be used to store data within a view
26187      * without resorting to another data structure.
26188      *
26189      * The specified key should be an id declared in the resources of the
26190      * application to ensure it is unique (see the <a
26191      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
26192      * Keys identified as belonging to
26193      * the Android framework or not associated with any package will cause
26194      * an {@link IllegalArgumentException} to be thrown.
26195      *
26196      * @param key The key identifying the tag
26197      * @param tag An Object to tag the view with
26198      *
26199      * @throws IllegalArgumentException If they specified key is not valid
26200      *
26201      * @see #setTag(Object)
26202      * @see #getTag(int)
26203      */
setTag(int key, final Object tag)26204     public void setTag(int key, final Object tag) {
26205         // If the package id is 0x00 or 0x01, it's either an undefined package
26206         // or a framework id
26207         if ((key >>> 24) < 2) {
26208             throw new IllegalArgumentException("The key must be an application-specific "
26209                     + "resource id.");
26210         }
26211 
26212         setKeyedTag(key, tag);
26213     }
26214 
26215     /**
26216      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
26217      * framework id.
26218      *
26219      * @hide
26220      */
26221     @UnsupportedAppUsage
setTagInternal(int key, Object tag)26222     public void setTagInternal(int key, Object tag) {
26223         if ((key >>> 24) != 0x1) {
26224             throw new IllegalArgumentException("The key must be a framework-specific "
26225                     + "resource id.");
26226         }
26227 
26228         setKeyedTag(key, tag);
26229     }
26230 
setKeyedTag(int key, Object tag)26231     private void setKeyedTag(int key, Object tag) {
26232         if (mKeyedTags == null) {
26233             mKeyedTags = new SparseArray<Object>(2);
26234         }
26235 
26236         mKeyedTags.put(key, tag);
26237     }
26238 
26239     /**
26240      * Prints information about this view in the log output, with the tag
26241      * {@link #VIEW_LOG_TAG}.
26242      *
26243      * @hide
26244      */
26245     @UnsupportedAppUsage
debug()26246     public void debug() {
26247         debug(0);
26248     }
26249 
26250     /**
26251      * Prints information about this view in the log output, with the tag
26252      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
26253      * indentation defined by the <code>depth</code>.
26254      *
26255      * @param depth the indentation level
26256      *
26257      * @hide
26258      */
26259     @UnsupportedAppUsage
debug(int depth)26260     protected void debug(int depth) {
26261         String output = debugIndent(depth - 1);
26262 
26263         output += "+ " + this;
26264         int id = getId();
26265         if (id != -1) {
26266             output += " (id=" + id + ")";
26267         }
26268         Object tag = getTag();
26269         if (tag != null) {
26270             output += " (tag=" + tag + ")";
26271         }
26272         Log.d(VIEW_LOG_TAG, output);
26273 
26274         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
26275             output = debugIndent(depth) + " FOCUSED";
26276             Log.d(VIEW_LOG_TAG, output);
26277         }
26278 
26279         output = debugIndent(depth);
26280         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
26281                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
26282                 + "} ";
26283         Log.d(VIEW_LOG_TAG, output);
26284 
26285         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
26286                 || mPaddingBottom != 0) {
26287             output = debugIndent(depth);
26288             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
26289                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
26290             Log.d(VIEW_LOG_TAG, output);
26291         }
26292 
26293         output = debugIndent(depth);
26294         output += "mMeasureWidth=" + mMeasuredWidth +
26295                 " mMeasureHeight=" + mMeasuredHeight;
26296         Log.d(VIEW_LOG_TAG, output);
26297 
26298         output = debugIndent(depth);
26299         if (mLayoutParams == null) {
26300             output += "BAD! no layout params";
26301         } else {
26302             output = mLayoutParams.debug(output);
26303         }
26304         Log.d(VIEW_LOG_TAG, output);
26305 
26306         output = debugIndent(depth);
26307         output += "flags={";
26308         output += View.printFlags(mViewFlags);
26309         output += "}";
26310         Log.d(VIEW_LOG_TAG, output);
26311 
26312         output = debugIndent(depth);
26313         output += "privateFlags={";
26314         output += View.printPrivateFlags(mPrivateFlags);
26315         output += "}";
26316         Log.d(VIEW_LOG_TAG, output);
26317     }
26318 
26319     /**
26320      * Creates a string of whitespaces used for indentation.
26321      *
26322      * @param depth the indentation level
26323      * @return a String containing (depth * 2 + 3) * 2 white spaces
26324      *
26325      * @hide
26326      */
debugIndent(int depth)26327     protected static String debugIndent(int depth) {
26328         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
26329         for (int i = 0; i < (depth * 2) + 3; i++) {
26330             spaces.append(' ').append(' ');
26331         }
26332         return spaces.toString();
26333     }
26334 
26335     /**
26336      * <p>Return the offset of the widget's text baseline from the widget's top
26337      * boundary. If this widget does not support baseline alignment, this
26338      * method returns -1. </p>
26339      *
26340      * @return the offset of the baseline within the widget's bounds or -1
26341      *         if baseline alignment is not supported
26342      */
26343     @ViewDebug.ExportedProperty(category = "layout")
26344     @InspectableProperty
getBaseline()26345     public int getBaseline() {
26346         return -1;
26347     }
26348 
26349     /**
26350      * Returns whether the view hierarchy is currently undergoing a layout pass. This
26351      * information is useful to avoid situations such as calling {@link #requestLayout()} during
26352      * a layout pass.
26353      *
26354      * @return whether the view hierarchy is currently undergoing a layout pass
26355      */
isInLayout()26356     public boolean isInLayout() {
26357         ViewRootImpl viewRoot = getViewRootImpl();
26358         return (viewRoot != null && viewRoot.isInLayout());
26359     }
26360 
26361     /** To be used only for debugging purposes. */
printStackStrace(String name)26362     private void printStackStrace(String name) {
26363         Log.d(VIEW_LOG_TAG, "---- ST:" + name);
26364 
26365         StringBuilder sb = new StringBuilder();
26366         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
26367         int startIndex = 1;
26368         int endIndex = Math.min(stackTraceElements.length, startIndex + 20); // max 20 entries.
26369         for (int i = startIndex; i < endIndex; i++) {
26370             StackTraceElement s = stackTraceElements[i];
26371             sb.append(s.getMethodName())
26372                     .append("(")
26373                     .append(s.getFileName())
26374                     .append(":")
26375                     .append(s.getLineNumber())
26376                     .append(") <- ");
26377         }
26378         Log.d(VIEW_LOG_TAG, name + ": " + sb);
26379     }
26380     /**
26381      * Call this when something has changed which has invalidated the
26382      * layout of this view. This will schedule a layout pass of the view
26383      * tree. This should not be called while the view hierarchy is currently in a layout
26384      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
26385      * end of the current layout pass (and then layout will run again) or after the current
26386      * frame is drawn and the next layout occurs.
26387      *
26388      * <p>Subclasses which override this method should call the superclass method to
26389      * handle possible request-during-layout errors correctly.</p>
26390      */
26391     @CallSuper
requestLayout()26392     public void requestLayout() {
26393         if (isRelayoutTracingEnabled()) {
26394             Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
26395                     mTracingStrings.classSimpleName);
26396             printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
26397         }
26398 
26399         if (mMeasureCache != null) mMeasureCache.clear();
26400 
26401         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
26402             // Only trigger request-during-layout logic if this is the view requesting it,
26403             // not the views in its parent hierarchy
26404             ViewRootImpl viewRoot = getViewRootImpl();
26405             if (viewRoot != null && viewRoot.isInLayout()) {
26406                 if (!viewRoot.requestLayoutDuringLayout(this)) {
26407                     return;
26408                 }
26409             }
26410             mAttachInfo.mViewRequestingLayout = this;
26411         }
26412 
26413         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
26414         mPrivateFlags |= PFLAG_INVALIDATED;
26415 
26416         if (mParent != null && !mParent.isLayoutRequested()) {
26417             mParent.requestLayout();
26418         }
26419         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
26420             mAttachInfo.mViewRequestingLayout = null;
26421         }
26422     }
26423 
26424     /**
26425      * Forces this view to be laid out during the next layout pass.
26426      * This method does not call requestLayout() or forceLayout()
26427      * on the parent.
26428      */
forceLayout()26429     public void forceLayout() {
26430         if (mMeasureCache != null) mMeasureCache.clear();
26431 
26432         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
26433         mPrivateFlags |= PFLAG_INVALIDATED;
26434     }
26435 
26436     /**
26437      * <p>
26438      * This is called to find out how big a view should be. The parent
26439      * supplies constraint information in the width and height parameters.
26440      * </p>
26441      *
26442      * <p>
26443      * The actual measurement work of a view is performed in
26444      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
26445      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
26446      * </p>
26447      *
26448      *
26449      * @param widthMeasureSpec Horizontal space requirements as imposed by the
26450      *        parent
26451      * @param heightMeasureSpec Vertical space requirements as imposed by the
26452      *        parent
26453      *
26454      * @see #onMeasure(int, int)
26455      */
measure(int widthMeasureSpec, int heightMeasureSpec)26456     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
26457         boolean optical = isLayoutModeOptical(this);
26458         if (optical != isLayoutModeOptical(mParent)) {
26459             Insets insets = getOpticalInsets();
26460             int oWidth  = insets.left + insets.right;
26461             int oHeight = insets.top  + insets.bottom;
26462             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
26463             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
26464         }
26465 
26466         // Suppress sign extension for the low bytes
26467         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
26468         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
26469 
26470         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
26471 
26472         // Optimize layout by avoiding an extra EXACTLY pass when the view is
26473         // already measured as the correct size. In API 23 and below, this
26474         // extra pass is required to make LinearLayout re-distribute weight.
26475         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
26476                 || heightMeasureSpec != mOldHeightMeasureSpec;
26477         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
26478                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
26479         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
26480                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
26481         final boolean needsLayout = specChanged
26482                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
26483 
26484         if (forceLayout || needsLayout) {
26485             // first clears the measured dimension flag
26486             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
26487 
26488             resolveRtlPropertiesIfNeeded();
26489 
26490             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
26491             if (cacheIndex < 0 || sIgnoreMeasureCache) {
26492                 if (isTraversalTracingEnabled()) {
26493                     Trace.beginSection(mTracingStrings.onMeasure);
26494                 }
26495                 // measure ourselves, this should set the measured dimension flag back
26496                 onMeasure(widthMeasureSpec, heightMeasureSpec);
26497                 if (isTraversalTracingEnabled()) {
26498                     Trace.endSection();
26499                 }
26500                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
26501             } else {
26502                 long value = mMeasureCache.valueAt(cacheIndex);
26503                 // Casting a long to int drops the high 32 bits, no mask needed
26504                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
26505                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
26506             }
26507 
26508             // flag not set, setMeasuredDimension() was not invoked, we raise
26509             // an exception to warn the developer
26510             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
26511                 throw new IllegalStateException("View with id " + getId() + ": "
26512                         + getClass().getName() + "#onMeasure() did not set the"
26513                         + " measured dimension by calling"
26514                         + " setMeasuredDimension()");
26515             }
26516 
26517             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
26518         }
26519 
26520         mOldWidthMeasureSpec = widthMeasureSpec;
26521         mOldHeightMeasureSpec = heightMeasureSpec;
26522 
26523         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
26524                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
26525     }
26526 
26527     /**
26528      * <p>
26529      * Measure the view and its content to determine the measured width and the
26530      * measured height. This method is invoked by {@link #measure(int, int)} and
26531      * should be overridden by subclasses to provide accurate and efficient
26532      * measurement of their contents.
26533      * </p>
26534      *
26535      * <p>
26536      * <strong>CONTRACT:</strong> When overriding this method, you
26537      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
26538      * measured width and height of this view. Failure to do so will trigger an
26539      * <code>IllegalStateException</code>, thrown by
26540      * {@link #measure(int, int)}. Calling the superclass'
26541      * {@link #onMeasure(int, int)} is a valid use.
26542      * </p>
26543      *
26544      * <p>
26545      * The base class implementation of measure defaults to the background size,
26546      * unless a larger size is allowed by the MeasureSpec. Subclasses should
26547      * override {@link #onMeasure(int, int)} to provide better measurements of
26548      * their content.
26549      * </p>
26550      *
26551      * <p>
26552      * If this method is overridden, it is the subclass's responsibility to make
26553      * sure the measured height and width are at least the view's minimum height
26554      * and width ({@link #getSuggestedMinimumHeight()} and
26555      * {@link #getSuggestedMinimumWidth()}).
26556      * </p>
26557      *
26558      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
26559      *                         The requirements are encoded with
26560      *                         {@link android.view.View.MeasureSpec}.
26561      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
26562      *                         The requirements are encoded with
26563      *                         {@link android.view.View.MeasureSpec}.
26564      *
26565      * @see #getMeasuredWidth()
26566      * @see #getMeasuredHeight()
26567      * @see #setMeasuredDimension(int, int)
26568      * @see #getSuggestedMinimumHeight()
26569      * @see #getSuggestedMinimumWidth()
26570      * @see android.view.View.MeasureSpec#getMode(int)
26571      * @see android.view.View.MeasureSpec#getSize(int)
26572      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)26573     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
26574         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
26575                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
26576     }
26577 
26578     /**
26579      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
26580      * measured width and measured height. Failing to do so will trigger an
26581      * exception at measurement time.</p>
26582      *
26583      * @param measuredWidth The measured width of this view.  May be a complex
26584      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
26585      * {@link #MEASURED_STATE_TOO_SMALL}.
26586      * @param measuredHeight The measured height of this view.  May be a complex
26587      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
26588      * {@link #MEASURED_STATE_TOO_SMALL}.
26589      */
setMeasuredDimension(int measuredWidth, int measuredHeight)26590     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
26591         boolean optical = isLayoutModeOptical(this);
26592         if (optical != isLayoutModeOptical(mParent)) {
26593             Insets insets = getOpticalInsets();
26594             int opticalWidth  = insets.left + insets.right;
26595             int opticalHeight = insets.top  + insets.bottom;
26596 
26597             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
26598             measuredHeight += optical ? opticalHeight : -opticalHeight;
26599         }
26600         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
26601     }
26602 
26603     /**
26604      * Sets the measured dimension without extra processing for things like optical bounds.
26605      * Useful for reapplying consistent values that have already been cooked with adjustments
26606      * for optical bounds, etc. such as those from the measurement cache.
26607      *
26608      * @param measuredWidth The measured width of this view.  May be a complex
26609      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
26610      * {@link #MEASURED_STATE_TOO_SMALL}.
26611      * @param measuredHeight The measured height of this view.  May be a complex
26612      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
26613      * {@link #MEASURED_STATE_TOO_SMALL}.
26614      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)26615     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
26616         mMeasuredWidth = measuredWidth;
26617         mMeasuredHeight = measuredHeight;
26618 
26619         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
26620     }
26621 
26622     /**
26623      * Merge two states as returned by {@link #getMeasuredState()}.
26624      * @param curState The current state as returned from a view or the result
26625      * of combining multiple views.
26626      * @param newState The new view state to combine.
26627      * @return Returns a new integer reflecting the combination of the two
26628      * states.
26629      */
combineMeasuredStates(int curState, int newState)26630     public static int combineMeasuredStates(int curState, int newState) {
26631         return curState | newState;
26632     }
26633 
26634     /**
26635      * Version of {@link #resolveSizeAndState(int, int, int)}
26636      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
26637      */
resolveSize(int size, int measureSpec)26638     public static int resolveSize(int size, int measureSpec) {
26639         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
26640     }
26641 
26642     /**
26643      * Utility to reconcile a desired size and state, with constraints imposed
26644      * by a MeasureSpec. Will take the desired size, unless a different size
26645      * is imposed by the constraints. The returned value is a compound integer,
26646      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
26647      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
26648      * resulting size is smaller than the size the view wants to be.
26649      *
26650      * @param size How big the view wants to be.
26651      * @param measureSpec Constraints imposed by the parent.
26652      * @param childMeasuredState Size information bit mask for the view's
26653      *                           children.
26654      * @return Size information bit mask as defined by
26655      *         {@link #MEASURED_SIZE_MASK} and
26656      *         {@link #MEASURED_STATE_TOO_SMALL}.
26657      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)26658     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
26659         final int specMode = MeasureSpec.getMode(measureSpec);
26660         final int specSize = MeasureSpec.getSize(measureSpec);
26661         final int result;
26662         switch (specMode) {
26663             case MeasureSpec.AT_MOST:
26664                 if (specSize < size) {
26665                     result = specSize | MEASURED_STATE_TOO_SMALL;
26666                 } else {
26667                     result = size;
26668                 }
26669                 break;
26670             case MeasureSpec.EXACTLY:
26671                 result = specSize;
26672                 break;
26673             case MeasureSpec.UNSPECIFIED:
26674             default:
26675                 result = size;
26676         }
26677         return result | (childMeasuredState & MEASURED_STATE_MASK);
26678     }
26679 
26680     /**
26681      * Utility to return a default size. Uses the supplied size if the
26682      * MeasureSpec imposed no constraints. Will get larger if allowed
26683      * by the MeasureSpec.
26684      *
26685      * @param size Default size for this view
26686      * @param measureSpec Constraints imposed by the parent
26687      * @return The size this view should be.
26688      */
getDefaultSize(int size, int measureSpec)26689     public static int getDefaultSize(int size, int measureSpec) {
26690         int result = size;
26691         int specMode = MeasureSpec.getMode(measureSpec);
26692         int specSize = MeasureSpec.getSize(measureSpec);
26693 
26694         switch (specMode) {
26695         case MeasureSpec.UNSPECIFIED:
26696             result = size;
26697             break;
26698         case MeasureSpec.AT_MOST:
26699         case MeasureSpec.EXACTLY:
26700             result = specSize;
26701             break;
26702         }
26703         return result;
26704     }
26705 
26706     /**
26707      * Returns the suggested minimum height that the view should use. This
26708      * returns the maximum of the view's minimum height
26709      * and the background's minimum height
26710      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
26711      * <p>
26712      * When being used in {@link #onMeasure(int, int)}, the caller should still
26713      * ensure the returned height is within the requirements of the parent.
26714      *
26715      * @return The suggested minimum height of the view.
26716      */
getSuggestedMinimumHeight()26717     protected int getSuggestedMinimumHeight() {
26718         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
26719 
26720     }
26721 
26722     /**
26723      * Returns the suggested minimum width that the view should use. This
26724      * returns the maximum of the view's minimum width
26725      * and the background's minimum width
26726      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
26727      * <p>
26728      * When being used in {@link #onMeasure(int, int)}, the caller should still
26729      * ensure the returned width is within the requirements of the parent.
26730      *
26731      * @return The suggested minimum width of the view.
26732      */
getSuggestedMinimumWidth()26733     protected int getSuggestedMinimumWidth() {
26734         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
26735     }
26736 
26737     /**
26738      * Returns the minimum height of the view.
26739      *
26740      * @return the minimum height the view will try to be, in pixels
26741      *
26742      * @see #setMinimumHeight(int)
26743      *
26744      * @attr ref android.R.styleable#View_minHeight
26745      */
26746     @InspectableProperty(name = "minHeight")
getMinimumHeight()26747     public int getMinimumHeight() {
26748         return mMinHeight;
26749     }
26750 
26751     /**
26752      * Sets the minimum height of the view. It is not guaranteed the view will
26753      * be able to achieve this minimum height (for example, if its parent layout
26754      * constrains it with less available height).
26755      *
26756      * @param minHeight The minimum height the view will try to be, in pixels
26757      *
26758      * @see #getMinimumHeight()
26759      *
26760      * @attr ref android.R.styleable#View_minHeight
26761      */
26762     @RemotableViewMethod
setMinimumHeight(int minHeight)26763     public void setMinimumHeight(int minHeight) {
26764         mMinHeight = minHeight;
26765         requestLayout();
26766     }
26767 
26768     /**
26769      * Returns the minimum width of the view.
26770      *
26771      * @return the minimum width the view will try to be, in pixels
26772      *
26773      * @see #setMinimumWidth(int)
26774      *
26775      * @attr ref android.R.styleable#View_minWidth
26776      */
26777     @InspectableProperty(name = "minWidth")
getMinimumWidth()26778     public int getMinimumWidth() {
26779         return mMinWidth;
26780     }
26781 
26782     /**
26783      * Sets the minimum width of the view. It is not guaranteed the view will
26784      * be able to achieve this minimum width (for example, if its parent layout
26785      * constrains it with less available width).
26786      *
26787      * @param minWidth The minimum width the view will try to be, in pixels
26788      *
26789      * @see #getMinimumWidth()
26790      *
26791      * @attr ref android.R.styleable#View_minWidth
26792      */
26793     @RemotableViewMethod
setMinimumWidth(int minWidth)26794     public void setMinimumWidth(int minWidth) {
26795         mMinWidth = minWidth;
26796         requestLayout();
26797 
26798     }
26799 
26800     /**
26801      * Get the animation currently associated with this view.
26802      *
26803      * @return The animation that is currently playing or
26804      *         scheduled to play for this view.
26805      */
getAnimation()26806     public Animation getAnimation() {
26807         return mCurrentAnimation;
26808     }
26809 
26810     /**
26811      * Start the specified animation now.
26812      *
26813      * @param animation the animation to start now
26814      */
startAnimation(Animation animation)26815     public void startAnimation(Animation animation) {
26816         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
26817         setAnimation(animation);
26818         invalidateParentCaches();
26819         invalidate(true);
26820     }
26821 
26822     /**
26823      * Cancels any animations for this view.
26824      */
clearAnimation()26825     public void clearAnimation() {
26826         if (mCurrentAnimation != null) {
26827             mCurrentAnimation.detach();
26828         }
26829         mCurrentAnimation = null;
26830         invalidateParentIfNeeded();
26831     }
26832 
26833     /**
26834      * Sets the next animation to play for this view.
26835      * If you want the animation to play immediately, use
26836      * {@link #startAnimation(android.view.animation.Animation)} instead.
26837      * This method provides allows fine-grained
26838      * control over the start time and invalidation, but you
26839      * must make sure that 1) the animation has a start time set, and
26840      * 2) the view's parent (which controls animations on its children)
26841      * will be invalidated when the animation is supposed to
26842      * start.
26843      *
26844      * @param animation The next animation, or null.
26845      */
setAnimation(Animation animation)26846     public void setAnimation(Animation animation) {
26847         mCurrentAnimation = animation;
26848 
26849         if (animation != null) {
26850             // If the screen is off assume the animation start time is now instead of
26851             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
26852             // would cause the animation to start when the screen turns back on
26853             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
26854                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
26855                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
26856             }
26857             animation.reset();
26858         }
26859     }
26860 
26861     /**
26862      * Invoked by a parent ViewGroup to notify the start of the animation
26863      * currently associated with this view. If you override this method,
26864      * always call super.onAnimationStart();
26865      *
26866      * @see #setAnimation(android.view.animation.Animation)
26867      * @see #getAnimation()
26868      */
26869     @CallSuper
onAnimationStart()26870     protected void onAnimationStart() {
26871         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
26872     }
26873 
26874     /**
26875      * Invoked by a parent ViewGroup to notify the end of the animation
26876      * currently associated with this view. If you override this method,
26877      * always call super.onAnimationEnd();
26878      *
26879      * @see #setAnimation(android.view.animation.Animation)
26880      * @see #getAnimation()
26881      */
26882     @CallSuper
onAnimationEnd()26883     protected void onAnimationEnd() {
26884         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
26885     }
26886 
26887     /**
26888      * Invoked if there is a Transform that involves alpha. Subclass that can
26889      * draw themselves with the specified alpha should return true, and then
26890      * respect that alpha when their onDraw() is called. If this returns false
26891      * then the view may be redirected to draw into an offscreen buffer to
26892      * fulfill the request, which will look fine, but may be slower than if the
26893      * subclass handles it internally. The default implementation returns false.
26894      *
26895      * @param alpha The alpha (0..255) to apply to the view's drawing
26896      * @return true if the view can draw with the specified alpha.
26897      */
onSetAlpha(int alpha)26898     protected boolean onSetAlpha(int alpha) {
26899         return false;
26900     }
26901 
26902     /**
26903      * This is used by the ViewRoot to perform an optimization when
26904      * the view hierarchy contains one or several SurfaceView.
26905      * SurfaceView is always considered transparent, but its children are not,
26906      * therefore all View objects remove themselves from the global transparent
26907      * region (passed as a parameter to this function).
26908      *
26909      * @param region The transparent region for this ViewAncestor (window).
26910      *
26911      * @return Returns true if the effective visibility of the view at this
26912      * point is opaque, regardless of the transparent region; returns false
26913      * if it is possible for underlying windows to be seen behind the view.
26914      *
26915      */
gatherTransparentRegion(@ullable Region region)26916     public boolean gatherTransparentRegion(@Nullable Region region) {
26917         final AttachInfo attachInfo = mAttachInfo;
26918         if (region != null && attachInfo != null) {
26919             final int pflags = mPrivateFlags;
26920             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
26921                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
26922                 // remove it from the transparent region.
26923                 final int[] location = attachInfo.mTransparentLocation;
26924                 getLocationInWindow(location);
26925                 // When a view has Z value, then it will be better to leave some area below the view
26926                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
26927                 // the bottom part needs more offset than the left, top and right parts due to the
26928                 // spot light effects.
26929                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
26930                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
26931                         location[0] + mRight - mLeft + shadowOffset,
26932                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
26933             } else {
26934                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
26935                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
26936                     // the background drawable's non-transparent parts from this transparent region.
26937                     applyDrawableToTransparentRegion(mBackground, region);
26938                 }
26939                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
26940                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
26941                     // Similarly, we remove the foreground drawable's non-transparent parts.
26942                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
26943                 }
26944                 if (mDefaultFocusHighlight != null
26945                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
26946                     // Similarly, we remove the default focus highlight's non-transparent parts.
26947                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
26948                 }
26949             }
26950         }
26951         return true;
26952     }
26953 
26954     /**
26955      * Play a sound effect for this view.
26956      *
26957      * <p>The framework will play sound effects for some built in actions, such as
26958      * clicking, but you may wish to play these effects in your widget,
26959      * for instance, for internal navigation.
26960      *
26961      * <p>The sound effect will only be played if sound effects are enabled by the user, and
26962      * {@link #isSoundEffectsEnabled()} is true.
26963      *
26964      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}.
26965      */
playSoundEffect(@oundEffectConstants.SoundEffect int soundConstant)26966     public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
26967         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
26968             return;
26969         }
26970         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
26971     }
26972 
26973     /**
26974      * BZZZTT!!1!
26975      *
26976      * <p>Provide haptic feedback to the user for this view.
26977      *
26978      * <p>The framework will provide haptic feedback for some built in actions,
26979      * such as long presses, but you may wish to provide feedback for your
26980      * own widget.
26981      *
26982      * <p>The feedback will only be performed if
26983      * {@link #isHapticFeedbackEnabled()} is true.
26984      *
26985      * @param feedbackConstant One of the constants defined in
26986      * {@link HapticFeedbackConstants}
26987      */
performHapticFeedback(int feedbackConstant)26988     public boolean performHapticFeedback(int feedbackConstant) {
26989         return performHapticFeedback(feedbackConstant, 0);
26990     }
26991 
26992     /**
26993      * BZZZTT!!1!
26994      *
26995      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
26996      *
26997      * @param feedbackConstant One of the constants defined in
26998      * {@link HapticFeedbackConstants}
26999      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
27000      */
performHapticFeedback(int feedbackConstant, int flags)27001     public boolean performHapticFeedback(int feedbackConstant, int flags) {
27002         if (mAttachInfo == null) {
27003             return false;
27004         }
27005         //noinspection SimplifiableIfStatement
27006         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
27007                 && !isHapticFeedbackEnabled()) {
27008             return false;
27009         }
27010         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
27011                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
27012     }
27013 
27014     /**
27015      * Request that the visibility of the status bar or other screen/window
27016      * decorations be changed.
27017      *
27018      * <p>This method is used to put the over device UI into temporary modes
27019      * where the user's attention is focused more on the application content,
27020      * by dimming or hiding surrounding system affordances.  This is typically
27021      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
27022      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
27023      * to be placed behind the action bar (and with these flags other system
27024      * affordances) so that smooth transitions between hiding and showing them
27025      * can be done.
27026      *
27027      * <p>Two representative examples of the use of system UI visibility is
27028      * implementing a content browsing application (like a magazine reader)
27029      * and a video playing application.
27030      *
27031      * <p>The first code shows a typical implementation of a View in a content
27032      * browsing application.  In this implementation, the application goes
27033      * into a content-oriented mode by hiding the status bar and action bar,
27034      * and putting the navigation elements into lights out mode.  The user can
27035      * then interact with content while in this mode.  Such an application should
27036      * provide an easy way for the user to toggle out of the mode (such as to
27037      * check information in the status bar or access notifications).  In the
27038      * implementation here, this is done simply by tapping on the content.
27039      *
27040      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
27041      *      content}
27042      *
27043      * <p>This second code sample shows a typical implementation of a View
27044      * in a video playing application.  In this situation, while the video is
27045      * playing the application would like to go into a complete full-screen mode,
27046      * to use as much of the display as possible for the video.  When in this state
27047      * the user can not interact with the application; the system intercepts
27048      * touching on the screen to pop the UI out of full screen mode.  See
27049      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
27050      *
27051      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
27052      *      content}
27053      *
27054      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
27055      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
27056      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
27057      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
27058      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
27059      *
27060      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27061      * instead.
27062      */
27063     @Deprecated
setSystemUiVisibility(int visibility)27064     public void setSystemUiVisibility(int visibility) {
27065         if (visibility != mSystemUiVisibility) {
27066             mSystemUiVisibility = visibility;
27067             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
27068                 mParent.recomputeViewAttributes(this);
27069             }
27070         }
27071     }
27072 
27073     /**
27074      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
27075      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
27076      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
27077      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
27078      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
27079      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
27080      *
27081      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27082      * instead.
27083      */
27084     @Deprecated
getSystemUiVisibility()27085     public int getSystemUiVisibility() {
27086         return mSystemUiVisibility;
27087     }
27088 
27089     /**
27090      * Returns the current system UI visibility that is currently set for
27091      * the entire window.  This is the combination of the
27092      * {@link #setSystemUiVisibility(int)} values supplied by all of the
27093      * views in the window.
27094      *
27095      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27096      * instead.
27097      */
27098     @Deprecated
getWindowSystemUiVisibility()27099     public int getWindowSystemUiVisibility() {
27100         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
27101     }
27102 
27103     /**
27104      * Override to find out when the window's requested system UI visibility
27105      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
27106      * This is different from the callbacks received through
27107      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
27108      * in that this is only telling you about the local request of the window,
27109      * not the actual values applied by the system.
27110      *
27111      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27112      * instead.
27113      */
27114     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)27115     public void onWindowSystemUiVisibilityChanged(int visible) {
27116     }
27117 
27118     /**
27119      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
27120      * the view hierarchy.
27121      *
27122      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27123      * instead.
27124      */
27125     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)27126     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
27127         onWindowSystemUiVisibilityChanged(visible);
27128     }
27129 
27130     /**
27131      * Set a listener to receive callbacks when the visibility of the system bar changes.
27132      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
27133      *
27134      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
27135      * by setting a {@link OnApplyWindowInsetsListener} on this view.
27136      */
27137     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)27138     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
27139         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
27140         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
27141             mParent.recomputeViewAttributes(this);
27142         }
27143     }
27144 
27145     /**
27146      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
27147      * the view hierarchy.
27148      *
27149      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
27150      * by setting a {@link OnApplyWindowInsetsListener} on this view.
27151      */
27152     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)27153     public void dispatchSystemUiVisibilityChanged(int visibility) {
27154         ListenerInfo li = mListenerInfo;
27155         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
27156             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
27157                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
27158         }
27159     }
27160 
updateLocalSystemUiVisibility(int localValue, int localChanges)27161     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
27162         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
27163         if (val != mSystemUiVisibility) {
27164             setSystemUiVisibility(val);
27165             return true;
27166         }
27167         return false;
27168     }
27169 
27170     /** @hide */
27171     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDisabledSystemUiVisibility(int flags)27172     public void setDisabledSystemUiVisibility(int flags) {
27173         if (mAttachInfo != null) {
27174             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
27175                 mAttachInfo.mDisabledSystemUiVisibility = flags;
27176                 if (mParent != null) {
27177                     mParent.recomputeViewAttributes(this);
27178                 }
27179             }
27180         }
27181     }
27182 
27183     /**
27184      * This needs to be a better API before it is exposed. For now, only the root view will get
27185      * notified.
27186      * @hide
27187      */
onSystemBarAppearanceChanged(@indowInsetsController.Appearance int appearance)27188     public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
27189     }
27190 
27191     /**
27192      * Creates an image that the system displays during the drag and drop
27193      * operation. This is called a &quot;drag shadow&quot;. The default implementation
27194      * for a DragShadowBuilder based on a View returns an image that has exactly the same
27195      * appearance as the given View. The default also positions the center of the drag shadow
27196      * directly under the touch point. If no View is provided (the constructor with no parameters
27197      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
27198      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
27199      * default is an invisible drag shadow.
27200      * <p>
27201      * You are not required to use the View you provide to the constructor as the basis of the
27202      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
27203      * anything you want as the drag shadow.
27204      * </p>
27205      * <p>
27206      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
27207      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
27208      *  size and position of the drag shadow. It uses this data to construct a
27209      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
27210      *  so that your application can draw the shadow image in the Canvas.
27211      * </p>
27212      *
27213      * <div class="special reference">
27214      * <h3>Developer Guides</h3>
27215      * <p>For a guide to implementing drag and drop features, read the
27216      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
27217      * </div>
27218      */
27219     public static class DragShadowBuilder {
27220         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
27221         private final WeakReference<View> mView;
27222 
27223         /**
27224          * Constructs a shadow image builder based on a View. By default, the resulting drag
27225          * shadow will have the same appearance and dimensions as the View, with the touch point
27226          * over the center of the View.
27227          * @param view A View. Any View in scope can be used.
27228          */
DragShadowBuilder(View view)27229         public DragShadowBuilder(View view) {
27230             mView = new WeakReference<View>(view);
27231         }
27232 
27233         /**
27234          * Construct a shadow builder object with no associated View.  This
27235          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
27236          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
27237          * to supply the drag shadow's dimensions and appearance without
27238          * reference to any View object.
27239          */
DragShadowBuilder()27240         public DragShadowBuilder() {
27241             mView = new WeakReference<View>(null);
27242         }
27243 
27244         /**
27245          * Returns the View object that had been passed to the
27246          * {@link #DragShadowBuilder(View)}
27247          * constructor.  If that View parameter was {@code null} or if the
27248          * {@link #DragShadowBuilder()}
27249          * constructor was used to instantiate the builder object, this method will return
27250          * null.
27251          *
27252          * @return The View object associate with this builder object.
27253          */
27254         @SuppressWarnings({"JavadocReference"})
getView()27255         final public View getView() {
27256             return mView.get();
27257         }
27258 
27259         /**
27260          * Provides the metrics for the shadow image. These include the dimensions of
27261          * the shadow image, and the point within that shadow that should
27262          * be centered under the touch location while dragging.
27263          * <p>
27264          * The default implementation sets the dimensions of the shadow to be the
27265          * same as the dimensions of the View itself and centers the shadow under
27266          * the touch point.
27267          * </p>
27268          *
27269          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
27270          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
27271          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
27272          * image. Since Android P, the width and height must be positive values.
27273          *
27274          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
27275          * shadow image that should be underneath the touch point during the drag and drop
27276          * operation. Your application must set {@link android.graphics.Point#x} to the
27277          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
27278          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)27279         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
27280             final View view = mView.get();
27281             if (view != null) {
27282                 outShadowSize.set(view.getWidth(), view.getHeight());
27283                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
27284             } else {
27285                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
27286             }
27287         }
27288 
27289         /**
27290          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
27291          * based on the dimensions it received from the
27292          * {@link #onProvideShadowMetrics(Point, Point)} callback.
27293          *
27294          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
27295          */
onDrawShadow(Canvas canvas)27296         public void onDrawShadow(Canvas canvas) {
27297             final View view = mView.get();
27298             if (view != null) {
27299                 view.draw(canvas);
27300             } else {
27301                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
27302             }
27303         }
27304     }
27305 
27306     /**
27307      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
27308      * startDragAndDrop()} for newer platform versions.
27309      */
27310     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)27311     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
27312                                    Object myLocalState, int flags) {
27313         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
27314     }
27315 
27316     /**
27317      * Starts a drag and drop operation. When your application calls this method, it passes a
27318      * {@link android.view.View.DragShadowBuilder} object to the system. The
27319      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
27320      * to get metrics for the drag shadow, and then calls the object's
27321      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
27322      * <p>
27323      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
27324      *  drag events to all the View objects in your application that are currently visible. It does
27325      *  this either by calling the View object's drag listener (an implementation of
27326      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
27327      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
27328      *  Both are passed a {@link android.view.DragEvent} object that has a
27329      *  {@link android.view.DragEvent#getAction()} value of
27330      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
27331      * </p>
27332      * <p>
27333      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
27334      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
27335      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
27336      * to the View the user selected for dragging.
27337      * </p>
27338      * @param data A {@link android.content.ClipData} object pointing to the data to be
27339      * transferred by the drag and drop operation.
27340      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
27341      * drag shadow.
27342      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
27343      * drop operation. When dispatching drag events to views in the same activity this object
27344      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
27345      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
27346      * will return null).
27347      * <p>
27348      * myLocalState is a lightweight mechanism for the sending information from the dragged View
27349      * to the target Views. For example, it can contain flags that differentiate between a
27350      * a copy operation and a move operation.
27351      * </p>
27352      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
27353      * flags, or any combination of the following:
27354      *     <ul>
27355      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
27356      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
27357      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
27358      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
27359      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
27360      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
27361      *         <li>{@link #DRAG_FLAG_ACCESSIBILITY_ACTION}</li>
27362      *     </ul>
27363      * @return {@code true} if the method completes successfully, or
27364      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
27365      * do a drag because of another ongoing operation or some other reasons.
27366      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)27367     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
27368             Object myLocalState, int flags) {
27369         if (ViewDebug.DEBUG_DRAG) {
27370             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
27371         }
27372         if (mAttachInfo == null) {
27373             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
27374             return false;
27375         }
27376         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
27377             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
27378             return false;
27379         }
27380 
27381         if (data != null) {
27382             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
27383         }
27384 
27385         Rect bounds = new Rect();
27386         getBoundsOnScreen(bounds, true);
27387 
27388         Point lastTouchPoint = new Point();
27389         mAttachInfo.mViewRootImpl.getLastTouchPoint(lastTouchPoint);
27390         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
27391 
27392         // Skip surface logic since shadows and animation are not required during the a11y drag
27393         final boolean a11yEnabled = AccessibilityManager.getInstance(mContext).isEnabled();
27394         if (a11yEnabled && (flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) != 0) {
27395             try {
27396                 IBinder token = mAttachInfo.mSession.performDrag(
27397                         mAttachInfo.mWindow, flags, null,
27398                         mAttachInfo.mViewRootImpl.getLastTouchSource(),
27399                         0f, 0f, 0f, 0f, data);
27400                 if (ViewDebug.DEBUG_DRAG) {
27401                     Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
27402                 }
27403                 if (token != null) {
27404                     root.setLocalDragState(myLocalState);
27405                     mAttachInfo.mDragToken = token;
27406                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
27407                     setAccessibilityDragStarted(true);
27408                 }
27409                 return token != null;
27410             } catch (Exception e) {
27411                 Log.e(VIEW_LOG_TAG, "Unable to initiate a11y drag", e);
27412                 return false;
27413             }
27414         }
27415 
27416         Point shadowSize = new Point();
27417         Point shadowTouchPoint = new Point();
27418         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
27419 
27420         if ((shadowSize.x < 0) || (shadowSize.y < 0)
27421                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
27422             throw new IllegalStateException("Drag shadow dimensions must not be negative");
27423         }
27424 
27425         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
27426         // does not accept zero size surface.
27427         if (shadowSize.x == 0  || shadowSize.y == 0) {
27428             if (!sAcceptZeroSizeDragShadow) {
27429                 throw new IllegalStateException("Drag shadow dimensions must be positive");
27430             }
27431             shadowSize.x = 1;
27432             shadowSize.y = 1;
27433         }
27434 
27435         if (ViewDebug.DEBUG_DRAG) {
27436             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
27437                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
27438         }
27439 
27440         final SurfaceSession session = new SurfaceSession();
27441         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
27442                 .setName("drag surface")
27443                 .setParent(root.getSurfaceControl())
27444                 .setBufferSize(shadowSize.x, shadowSize.y)
27445                 .setFormat(PixelFormat.TRANSLUCENT)
27446                 .setCallsite("View.startDragAndDrop")
27447                 .build();
27448         final Surface surface = new Surface();
27449         surface.copyFrom(surfaceControl);
27450         IBinder token = null;
27451         try {
27452             final Canvas canvas = isHardwareAccelerated()
27453                     ? surface.lockHardwareCanvas()
27454                     : surface.lockCanvas(null);
27455             try {
27456                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
27457                 shadowBuilder.onDrawShadow(canvas);
27458             } finally {
27459                 surface.unlockCanvasAndPost(canvas);
27460             }
27461 
27462             token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
27463                     root.getLastTouchSource(), lastTouchPoint.x, lastTouchPoint.y,
27464                     shadowTouchPoint.x, shadowTouchPoint.y, data);
27465             if (ViewDebug.DEBUG_DRAG) {
27466                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
27467             }
27468             if (token != null) {
27469                 if (mAttachInfo.mDragSurface != null) {
27470                     mAttachInfo.mDragSurface.release();
27471                 }
27472                 mAttachInfo.mDragSurface = surface;
27473                 mAttachInfo.mDragToken = token;
27474                 // Cache the local state object for delivery with DragEvents
27475                 root.setLocalDragState(myLocalState);
27476                 if (a11yEnabled) {
27477                     // Set for AccessibilityEvents
27478                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
27479                 }
27480             }
27481             return token != null;
27482         } catch (Exception e) {
27483             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
27484             return false;
27485         } finally {
27486             if (token == null) {
27487                 surface.destroy();
27488             }
27489             session.kill();
27490         }
27491     }
27492 
setAccessibilityDragStarted(boolean started)27493     void setAccessibilityDragStarted(boolean started) {
27494         int pflags4 = mPrivateFlags4;
27495         if (started) {
27496             pflags4 |= PFLAG4_DRAG_A11Y_STARTED;
27497         } else {
27498             pflags4 &= ~PFLAG4_DRAG_A11Y_STARTED;
27499         }
27500 
27501         if (pflags4 != mPrivateFlags4) {
27502             mPrivateFlags4 = pflags4;
27503             sendWindowContentChangedAccessibilityEvent(CONTENT_CHANGE_TYPE_UNDEFINED);
27504         }
27505     }
27506 
startedSystemDragForAccessibility()27507     private boolean startedSystemDragForAccessibility() {
27508         return (mPrivateFlags4 & PFLAG4_DRAG_A11Y_STARTED) != 0;
27509     }
27510 
27511     /**
27512      * Cancels an ongoing drag and drop operation.
27513      * <p>
27514      * A {@link android.view.DragEvent} object with
27515      * {@link android.view.DragEvent#getAction()} value of
27516      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
27517      * {@link android.view.DragEvent#getResult()} value of {@code false}
27518      * will be sent to every
27519      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
27520      * even if they are not currently visible.
27521      * </p>
27522      * <p>
27523      * This method can be called on any View in the same window as the View on which
27524      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
27525      * was called.
27526      * </p>
27527      */
cancelDragAndDrop()27528     public final void cancelDragAndDrop() {
27529         if (ViewDebug.DEBUG_DRAG) {
27530             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
27531         }
27532         if (mAttachInfo == null) {
27533             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
27534             return;
27535         }
27536         if (mAttachInfo.mDragToken != null) {
27537             try {
27538                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
27539             } catch (Exception e) {
27540                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
27541             }
27542             mAttachInfo.mDragToken = null;
27543         } else {
27544             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
27545         }
27546     }
27547 
27548     /**
27549      * Updates the drag shadow for the ongoing drag and drop operation.
27550      *
27551      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
27552      * new drag shadow.
27553      */
updateDragShadow(DragShadowBuilder shadowBuilder)27554     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
27555         if (ViewDebug.DEBUG_DRAG) {
27556             Log.d(VIEW_LOG_TAG, "updateDragShadow");
27557         }
27558         if (mAttachInfo == null) {
27559             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
27560             return;
27561         }
27562         if (mAttachInfo.mDragToken != null) {
27563             try {
27564                 Canvas canvas = isHardwareAccelerated()
27565                         ? mAttachInfo.mDragSurface.lockHardwareCanvas()
27566                         : mAttachInfo.mDragSurface.lockCanvas(null);
27567                 try {
27568                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
27569                     shadowBuilder.onDrawShadow(canvas);
27570                 } finally {
27571                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
27572                 }
27573             } catch (Exception e) {
27574                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
27575             }
27576         } else {
27577             Log.e(VIEW_LOG_TAG, "No active drag");
27578         }
27579     }
27580 
27581     /**
27582      * Starts a move from {startX, startY}, the amount of the movement will be the offset
27583      * between {startX, startY} and the new cursor positon.
27584      * @param startX horizontal coordinate where the move started.
27585      * @param startY vertical coordinate where the move started.
27586      * @return whether moving was started successfully.
27587      * @hide
27588      */
startMovingTask(float startX, float startY)27589     public final boolean startMovingTask(float startX, float startY) {
27590         if (ViewDebug.DEBUG_POSITIONING) {
27591             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
27592         }
27593         try {
27594             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
27595         } catch (RemoteException e) {
27596             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
27597         }
27598         return false;
27599     }
27600 
27601     /**
27602      * Finish a window move task.
27603      * @hide
27604      */
finishMovingTask()27605     public void finishMovingTask() {
27606         if (ViewDebug.DEBUG_POSITIONING) {
27607             Log.d(VIEW_LOG_TAG, "finishMovingTask");
27608         }
27609         try {
27610             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
27611         } catch (RemoteException e) {
27612             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
27613         }
27614     }
27615 
27616     /**
27617      * Handles drag events sent by the system following a call to
27618      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
27619      * startDragAndDrop()}.
27620      * <p>
27621      * The system calls this method and passes a {@link DragEvent} object in response to drag and
27622      * drop events. This method can then call {@link DragEvent#getAction()} to determine the state
27623      * of the drag and drop operation.
27624      * <p>
27625      * The default implementation returns {@code false} unless an {@link OnReceiveContentListener}
27626      * has been set for this view (see {@link #setOnReceiveContentListener}), in which case
27627      * the default implementation does the following:
27628      * <ul>
27629      *   <li>Returns {@code true} for an
27630      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
27631      *   <li>Calls {@link #performReceiveContent} for an
27632      *     {@link DragEvent#ACTION_DROP ACTION_DROP} event
27633      *   <li>Returns {@code true} for an {@link DragEvent#ACTION_DROP ACTION_DROP} event if the
27634      *     {@code OnReceiveContentListener} consumed some or all of the content
27635      * </ul>
27636      *
27637      * @param event The {@link DragEvent} object sent by the system. The
27638      *   {@link DragEvent#getAction()} method returns an action type constant that indicates the
27639      *   type of drag event represented by this object.
27640      * @return {@code true} if the method successfully handled the drag event, otherwise
27641      *   {@code false}.
27642      *   <p>
27643      *     The method must return {@code true} in response to an
27644      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} action type to continue to
27645      *     receive drag events for the current drag and drop operation.
27646      *   <p>
27647      *     The method should return {@code true} in response to an
27648      *     {@link DragEvent#ACTION_DROP ACTION_DROP} action type if the dropped data was consumed
27649      *     (at least partially); {@code false}, if none of the data was consumed.
27650      *   <p>
27651      *     For all other events, the return value is {@code false}.
27652      */
onDragEvent(DragEvent event)27653     public boolean onDragEvent(DragEvent event) {
27654         if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
27655             return false;
27656         }
27657         // Accept drag events by default if there's an OnReceiveContentListener set.
27658         if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
27659             return true;
27660         }
27661         if (event.getAction() == DragEvent.ACTION_DROP) {
27662             final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
27663             if (permissions != null) {
27664                 permissions.takeTransient();
27665             }
27666             final ContentInfo payload =
27667                     new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
27668                             .setDragAndDropPermissions(permissions)
27669                             .build();
27670             ContentInfo remainingPayload = performReceiveContent(payload);
27671             // Return true unless none of the payload was consumed.
27672             return remainingPayload != payload;
27673         }
27674         return false;
27675     }
27676 
27677     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)27678     boolean dispatchDragEnterExitInPreN(DragEvent event) {
27679         return callDragEventHandler(event);
27680     }
27681 
27682     /**
27683      * Detects if this View is enabled and has a drag event listener.
27684      * If both are true, then it calls the drag event listener with the
27685      * {@link android.view.DragEvent} it received. If the drag event listener returns
27686      * {@code true}, then dispatchDragEvent() returns {@code true}.
27687      * <p>
27688      * For all other cases, the method calls the
27689      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
27690      * method and returns its result.
27691      * </p>
27692      * <p>
27693      * This ensures that a drag event is always consumed, even if the View does not have a drag
27694      * event listener. However, if the View has a listener and the listener returns true, then
27695      * onDragEvent() is not called.
27696      * </p>
27697      */
dispatchDragEvent(DragEvent event)27698     public boolean dispatchDragEvent(DragEvent event) {
27699         event.mEventHandlerWasCalled = true;
27700         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
27701             event.mAction == DragEvent.ACTION_DROP) {
27702             // About to deliver an event with coordinates to this view. Notify that now this view
27703             // has drag focus. This will send exit/enter events as needed.
27704             getViewRootImpl().setDragFocus(this, event);
27705         }
27706         return callDragEventHandler(event);
27707     }
27708 
callDragEventHandler(DragEvent event)27709     final boolean callDragEventHandler(DragEvent event) {
27710         final boolean result;
27711 
27712         ListenerInfo li = mListenerInfo;
27713         //noinspection SimplifiableIfStatement
27714         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
27715                 && li.mOnDragListener.onDrag(this, event)) {
27716             result = true;
27717         } else {
27718             result = onDragEvent(event);
27719         }
27720 
27721         switch (event.mAction) {
27722             case DragEvent.ACTION_DRAG_STARTED: {
27723                 if (result && li != null && li.mOnDragListener != null) {
27724                     sendWindowContentChangedAccessibilityEvent(
27725                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
27726                 }
27727             } break;
27728             case DragEvent.ACTION_DRAG_ENTERED: {
27729                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
27730                 refreshDrawableState();
27731             } break;
27732             case DragEvent.ACTION_DRAG_EXITED: {
27733                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
27734                 refreshDrawableState();
27735             } break;
27736             case DragEvent.ACTION_DROP: {
27737                 if (result && li != null && (li.mOnDragListener != null
27738                         || li.mOnReceiveContentListener != null)) {
27739                     sendWindowContentChangedAccessibilityEvent(
27740                             AccessibilityEvent.CONTENT_CHANGE_TYPE_DRAG_DROPPED);
27741                 }
27742             } break;
27743             case DragEvent.ACTION_DRAG_ENDED: {
27744                 sendWindowContentChangedAccessibilityEvent(
27745                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
27746                 mPrivateFlags2 &= ~View.DRAG_MASK;
27747                 refreshDrawableState();
27748             } break;
27749         }
27750 
27751         return result;
27752     }
27753 
canAcceptDrag()27754     boolean canAcceptDrag() {
27755         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
27756     }
27757 
sendWindowContentChangedAccessibilityEvent(int changeType)27758     void sendWindowContentChangedAccessibilityEvent(int changeType) {
27759         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
27760             AccessibilityEvent event = AccessibilityEvent.obtain();
27761             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
27762             event.setContentChangeTypes(changeType);
27763             sendAccessibilityEventUnchecked(event);
27764         }
27765     }
27766 
27767     /**
27768      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
27769      * it is ever exposed at all.
27770      * @hide
27771      */
27772     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)27773     public void onCloseSystemDialogs(String reason) {
27774     }
27775 
27776     /**
27777      * Given a Drawable whose bounds have been set to draw into this view,
27778      * update a Region being computed for
27779      * {@link #gatherTransparentRegion(android.graphics.Region)} so
27780      * that any non-transparent parts of the Drawable are removed from the
27781      * given transparent region.
27782      *
27783      * @param dr The Drawable whose transparency is to be applied to the region.
27784      * @param region A Region holding the current transparency information,
27785      * where any parts of the region that are set are considered to be
27786      * transparent.  On return, this region will be modified to have the
27787      * transparency information reduced by the corresponding parts of the
27788      * Drawable that are not transparent.
27789      * {@hide}
27790      */
27791     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
applyDrawableToTransparentRegion(Drawable dr, Region region)27792     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
27793         if (DBG) {
27794             Log.i("View", "Getting transparent region for: " + this);
27795         }
27796         final Region r = dr.getTransparentRegion();
27797         final Rect db = dr.getBounds();
27798         final AttachInfo attachInfo = mAttachInfo;
27799         if (r != null && attachInfo != null) {
27800             final int w = getRight()-getLeft();
27801             final int h = getBottom()-getTop();
27802             if (db.left > 0) {
27803                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
27804                 r.op(0, 0, db.left, h, Region.Op.UNION);
27805             }
27806             if (db.right < w) {
27807                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
27808                 r.op(db.right, 0, w, h, Region.Op.UNION);
27809             }
27810             if (db.top > 0) {
27811                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
27812                 r.op(0, 0, w, db.top, Region.Op.UNION);
27813             }
27814             if (db.bottom < h) {
27815                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
27816                 r.op(0, db.bottom, w, h, Region.Op.UNION);
27817             }
27818             final int[] location = attachInfo.mTransparentLocation;
27819             getLocationInWindow(location);
27820             r.translate(location[0], location[1]);
27821             region.op(r, Region.Op.INTERSECT);
27822         } else {
27823             region.op(db, Region.Op.DIFFERENCE);
27824         }
27825     }
27826 
checkForLongClick(long delay, float x, float y, int classification)27827     private void checkForLongClick(long delay, float x, float y, int classification) {
27828         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
27829             mHasPerformedLongPress = false;
27830 
27831             if (mPendingCheckForLongPress == null) {
27832                 mPendingCheckForLongPress = new CheckForLongPress();
27833             }
27834             mPendingCheckForLongPress.setAnchor(x, y);
27835             mPendingCheckForLongPress.rememberWindowAttachCount();
27836             mPendingCheckForLongPress.rememberPressedState();
27837             mPendingCheckForLongPress.setClassification(classification);
27838             postDelayed(mPendingCheckForLongPress, delay);
27839         }
27840     }
27841 
27842     /**
27843      * Inflate a view from an XML resource.  This convenience method wraps the {@link
27844      * LayoutInflater} class, which provides a full range of options for view inflation.
27845      *
27846      * @param context The Context object for your activity or application.
27847      * @param resource The resource ID to inflate
27848      * @param root A view group that will be the parent.  Used to properly inflate the
27849      * layout_* parameters.
27850      * @see LayoutInflater
27851      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)27852     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
27853         LayoutInflater factory = LayoutInflater.from(context);
27854         return factory.inflate(resource, root);
27855     }
27856 
27857     /**
27858      * Scroll the view with standard behavior for scrolling beyond the normal
27859      * content boundaries. Views that call this method should override
27860      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
27861      * results of an over-scroll operation.
27862      *
27863      * Views can use this method to handle any touch or fling-based scrolling.
27864      *
27865      * @param deltaX Change in X in pixels
27866      * @param deltaY Change in Y in pixels
27867      * @param scrollX Current X scroll value in pixels before applying deltaX
27868      * @param scrollY Current Y scroll value in pixels before applying deltaY
27869      * @param scrollRangeX Maximum content scroll range along the X axis
27870      * @param scrollRangeY Maximum content scroll range along the Y axis
27871      * @param maxOverScrollX Number of pixels to overscroll by in either direction
27872      *          along the X axis.
27873      * @param maxOverScrollY Number of pixels to overscroll by in either direction
27874      *          along the Y axis.
27875      * @param isTouchEvent true if this scroll operation is the result of a touch event.
27876      * @return true if scrolling was clamped to an over-scroll boundary along either
27877      *          axis, false otherwise.
27878      */
27879     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)27880     protected boolean overScrollBy(int deltaX, int deltaY,
27881             int scrollX, int scrollY,
27882             int scrollRangeX, int scrollRangeY,
27883             int maxOverScrollX, int maxOverScrollY,
27884             boolean isTouchEvent) {
27885         final int overScrollMode = mOverScrollMode;
27886         final boolean canScrollHorizontal =
27887                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
27888         final boolean canScrollVertical =
27889                 computeVerticalScrollRange() > computeVerticalScrollExtent();
27890         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
27891                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
27892         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
27893                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
27894 
27895         int newScrollX = scrollX + deltaX;
27896         if (!overScrollHorizontal) {
27897             maxOverScrollX = 0;
27898         }
27899 
27900         int newScrollY = scrollY + deltaY;
27901         if (!overScrollVertical) {
27902             maxOverScrollY = 0;
27903         }
27904 
27905         // Clamp values if at the limits and record
27906         final int left = -maxOverScrollX;
27907         final int right = maxOverScrollX + scrollRangeX;
27908         final int top = -maxOverScrollY;
27909         final int bottom = maxOverScrollY + scrollRangeY;
27910 
27911         boolean clampedX = false;
27912         if (newScrollX > right) {
27913             newScrollX = right;
27914             clampedX = true;
27915         } else if (newScrollX < left) {
27916             newScrollX = left;
27917             clampedX = true;
27918         }
27919 
27920         boolean clampedY = false;
27921         if (newScrollY > bottom) {
27922             newScrollY = bottom;
27923             clampedY = true;
27924         } else if (newScrollY < top) {
27925             newScrollY = top;
27926             clampedY = true;
27927         }
27928 
27929         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
27930 
27931         return clampedX || clampedY;
27932     }
27933 
27934     /**
27935      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
27936      * respond to the results of an over-scroll operation.
27937      *
27938      * @param scrollX New X scroll value in pixels
27939      * @param scrollY New Y scroll value in pixels
27940      * @param clampedX True if scrollX was clamped to an over-scroll boundary
27941      * @param clampedY True if scrollY was clamped to an over-scroll boundary
27942      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)27943     protected void onOverScrolled(int scrollX, int scrollY,
27944             boolean clampedX, boolean clampedY) {
27945         // Intentionally empty.
27946     }
27947 
27948     /**
27949      * Returns the over-scroll mode for this view. The result will be
27950      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
27951      * (allow over-scrolling only if the view content is larger than the container),
27952      * or {@link #OVER_SCROLL_NEVER}.
27953      *
27954      * @return This view's over-scroll mode.
27955      */
27956     @InspectableProperty(enumMapping = {
27957             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
27958             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
27959             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
27960     })
getOverScrollMode()27961     public int getOverScrollMode() {
27962         return mOverScrollMode;
27963     }
27964 
27965     /**
27966      * Set the over-scroll mode for this view. Valid over-scroll modes are
27967      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
27968      * (allow over-scrolling only if the view content is larger than the container),
27969      * or {@link #OVER_SCROLL_NEVER}.
27970      *
27971      * Setting the over-scroll mode of a view will have an effect only if the
27972      * view is capable of scrolling.
27973      *
27974      * @param overScrollMode The new over-scroll mode for this view.
27975      */
setOverScrollMode(int overScrollMode)27976     public void setOverScrollMode(int overScrollMode) {
27977         if (overScrollMode != OVER_SCROLL_ALWAYS &&
27978                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
27979                 overScrollMode != OVER_SCROLL_NEVER) {
27980             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
27981         }
27982         mOverScrollMode = overScrollMode;
27983     }
27984 
27985     /**
27986      * Enable or disable nested scrolling for this view.
27987      *
27988      * <p>If this property is set to true the view will be permitted to initiate nested
27989      * scrolling operations with a compatible parent view in the current hierarchy. If this
27990      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
27991      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
27992      * the nested scroll.</p>
27993      *
27994      * @param enabled true to enable nested scrolling, false to disable
27995      *
27996      * @see #isNestedScrollingEnabled()
27997      */
setNestedScrollingEnabled(boolean enabled)27998     public void setNestedScrollingEnabled(boolean enabled) {
27999         if (enabled) {
28000             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
28001         } else {
28002             stopNestedScroll();
28003             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
28004         }
28005     }
28006 
28007     /**
28008      * Returns true if nested scrolling is enabled for this view.
28009      *
28010      * <p>If nested scrolling is enabled and this View class implementation supports it,
28011      * this view will act as a nested scrolling child view when applicable, forwarding data
28012      * about the scroll operation in progress to a compatible and cooperating nested scrolling
28013      * parent.</p>
28014      *
28015      * @return true if nested scrolling is enabled
28016      *
28017      * @see #setNestedScrollingEnabled(boolean)
28018      */
28019     @InspectableProperty
isNestedScrollingEnabled()28020     public boolean isNestedScrollingEnabled() {
28021         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
28022                 PFLAG3_NESTED_SCROLLING_ENABLED;
28023     }
28024 
28025     /**
28026      * Begin a nestable scroll operation along the given axes.
28027      *
28028      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
28029      *
28030      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
28031      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
28032      * In the case of touch scrolling the nested scroll will be terminated automatically in
28033      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
28034      * In the event of programmatic scrolling the caller must explicitly call
28035      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
28036      *
28037      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
28038      * If it returns false the caller may ignore the rest of this contract until the next scroll.
28039      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
28040      *
28041      * <p>At each incremental step of the scroll the caller should invoke
28042      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
28043      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
28044      * parent at least partially consumed the scroll and the caller should adjust the amount it
28045      * scrolls by.</p>
28046      *
28047      * <p>After applying the remainder of the scroll delta the caller should invoke
28048      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
28049      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
28050      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
28051      * </p>
28052      *
28053      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
28054      *             {@link #SCROLL_AXIS_VERTICAL}.
28055      * @return true if a cooperative parent was found and nested scrolling has been enabled for
28056      *         the current gesture.
28057      *
28058      * @see #stopNestedScroll()
28059      * @see #dispatchNestedPreScroll(int, int, int[], int[])
28060      * @see #dispatchNestedScroll(int, int, int, int, int[])
28061      */
startNestedScroll(int axes)28062     public boolean startNestedScroll(int axes) {
28063         if (hasNestedScrollingParent()) {
28064             // Already in progress
28065             return true;
28066         }
28067         if (isNestedScrollingEnabled()) {
28068             ViewParent p = getParent();
28069             View child = this;
28070             while (p != null) {
28071                 try {
28072                     if (p.onStartNestedScroll(child, this, axes)) {
28073                         mNestedScrollingParent = p;
28074                         p.onNestedScrollAccepted(child, this, axes);
28075                         return true;
28076                     }
28077                 } catch (AbstractMethodError e) {
28078                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
28079                             "method onStartNestedScroll", e);
28080                     // Allow the search upward to continue
28081                 }
28082                 if (p instanceof View) {
28083                     child = (View) p;
28084                 }
28085                 p = p.getParent();
28086             }
28087         }
28088         return false;
28089     }
28090 
28091     /**
28092      * Stop a nested scroll in progress.
28093      *
28094      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
28095      *
28096      * @see #startNestedScroll(int)
28097      */
stopNestedScroll()28098     public void stopNestedScroll() {
28099         if (mNestedScrollingParent != null) {
28100             mNestedScrollingParent.onStopNestedScroll(this);
28101             mNestedScrollingParent = null;
28102         }
28103     }
28104 
28105     /**
28106      * Returns true if this view has a nested scrolling parent.
28107      *
28108      * <p>The presence of a nested scrolling parent indicates that this view has initiated
28109      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
28110      *
28111      * @return whether this view has a nested scrolling parent
28112      */
hasNestedScrollingParent()28113     public boolean hasNestedScrollingParent() {
28114         return mNestedScrollingParent != null;
28115     }
28116 
28117     /**
28118      * Dispatch one step of a nested scroll in progress.
28119      *
28120      * <p>Implementations of views that support nested scrolling should call this to report
28121      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
28122      * is not currently in progress or nested scrolling is not
28123      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
28124      *
28125      * <p>Compatible View implementations should also call
28126      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
28127      * consuming a component of the scroll event themselves.</p>
28128      *
28129      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
28130      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
28131      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
28132      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
28133      * @param offsetInWindow Optional. If not null, on return this will contain the offset
28134      *                       in local view coordinates of this view from before this operation
28135      *                       to after it completes. View implementations may use this to adjust
28136      *                       expected input coordinate tracking.
28137      * @return true if the event was dispatched, false if it could not be dispatched.
28138      * @see #dispatchNestedPreScroll(int, int, int[], int[])
28139      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)28140     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
28141             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
28142         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28143             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
28144                 int startX = 0;
28145                 int startY = 0;
28146                 if (offsetInWindow != null) {
28147                     getLocationInWindow(offsetInWindow);
28148                     startX = offsetInWindow[0];
28149                     startY = offsetInWindow[1];
28150                 }
28151 
28152                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
28153                         dxUnconsumed, dyUnconsumed);
28154 
28155                 if (offsetInWindow != null) {
28156                     getLocationInWindow(offsetInWindow);
28157                     offsetInWindow[0] -= startX;
28158                     offsetInWindow[1] -= startY;
28159                 }
28160                 return true;
28161             } else if (offsetInWindow != null) {
28162                 // No motion, no dispatch. Keep offsetInWindow up to date.
28163                 offsetInWindow[0] = 0;
28164                 offsetInWindow[1] = 0;
28165             }
28166         }
28167         return false;
28168     }
28169 
28170     /**
28171      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
28172      *
28173      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
28174      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
28175      * scrolling operation to consume some or all of the scroll operation before the child view
28176      * consumes it.</p>
28177      *
28178      * @param dx Horizontal scroll distance in pixels
28179      * @param dy Vertical scroll distance in pixels
28180      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
28181      *                 and consumed[1] the consumed dy.
28182      * @param offsetInWindow Optional. If not null, on return this will contain the offset
28183      *                       in local view coordinates of this view from before this operation
28184      *                       to after it completes. View implementations may use this to adjust
28185      *                       expected input coordinate tracking.
28186      * @return true if the parent consumed some or all of the scroll delta
28187      * @see #dispatchNestedScroll(int, int, int, int, int[])
28188      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)28189     public boolean dispatchNestedPreScroll(int dx, int dy,
28190             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
28191         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28192             if (dx != 0 || dy != 0) {
28193                 int startX = 0;
28194                 int startY = 0;
28195                 if (offsetInWindow != null) {
28196                     getLocationInWindow(offsetInWindow);
28197                     startX = offsetInWindow[0];
28198                     startY = offsetInWindow[1];
28199                 }
28200 
28201                 if (consumed == null) {
28202                     if (mTempNestedScrollConsumed == null) {
28203                         mTempNestedScrollConsumed = new int[2];
28204                     }
28205                     consumed = mTempNestedScrollConsumed;
28206                 }
28207                 consumed[0] = 0;
28208                 consumed[1] = 0;
28209                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
28210 
28211                 if (offsetInWindow != null) {
28212                     getLocationInWindow(offsetInWindow);
28213                     offsetInWindow[0] -= startX;
28214                     offsetInWindow[1] -= startY;
28215                 }
28216                 return consumed[0] != 0 || consumed[1] != 0;
28217             } else if (offsetInWindow != null) {
28218                 offsetInWindow[0] = 0;
28219                 offsetInWindow[1] = 0;
28220             }
28221         }
28222         return false;
28223     }
28224 
28225     /**
28226      * Dispatch a fling to a nested scrolling parent.
28227      *
28228      * <p>This method should be used to indicate that a nested scrolling child has detected
28229      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
28230      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
28231      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
28232      * along a scrollable axis.</p>
28233      *
28234      * <p>If a nested scrolling child view would normally fling but it is at the edge of
28235      * its own content, it can use this method to delegate the fling to its nested scrolling
28236      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
28237      *
28238      * @param velocityX Horizontal fling velocity in pixels per second
28239      * @param velocityY Vertical fling velocity in pixels per second
28240      * @param consumed true if the child consumed the fling, false otherwise
28241      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
28242      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)28243     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
28244         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28245             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
28246         }
28247         return false;
28248     }
28249 
28250     /**
28251      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
28252      *
28253      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
28254      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
28255      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
28256      * before the child view consumes it. If this method returns <code>true</code>, a nested
28257      * parent view consumed the fling and this view should not scroll as a result.</p>
28258      *
28259      * <p>For a better user experience, only one view in a nested scrolling chain should consume
28260      * the fling at a time. If a parent view consumed the fling this method will return false.
28261      * Custom view implementations should account for this in two ways:</p>
28262      *
28263      * <ul>
28264      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
28265      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
28266      *     position regardless.</li>
28267      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
28268      *     even to settle back to a valid idle position.</li>
28269      * </ul>
28270      *
28271      * <p>Views should also not offer fling velocities to nested parent views along an axis
28272      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
28273      * should not offer a horizontal fling velocity to its parents since scrolling along that
28274      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
28275      *
28276      * @param velocityX Horizontal fling velocity in pixels per second
28277      * @param velocityY Vertical fling velocity in pixels per second
28278      * @return true if a nested scrolling parent consumed the fling
28279      */
dispatchNestedPreFling(float velocityX, float velocityY)28280     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
28281         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28282             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
28283         }
28284         return false;
28285     }
28286 
28287     /**
28288      * Gets a scale factor that determines the distance the view should scroll
28289      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
28290      * @return The vertical scroll scale factor.
28291      * @hide
28292      */
28293     @UnsupportedAppUsage
getVerticalScrollFactor()28294     protected float getVerticalScrollFactor() {
28295         if (mVerticalScrollFactor == 0) {
28296             TypedValue outValue = new TypedValue();
28297             if (!mContext.getTheme().resolveAttribute(
28298                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
28299                 throw new IllegalStateException(
28300                         "Expected theme to define listPreferredItemHeight.");
28301             }
28302             mVerticalScrollFactor = outValue.getDimension(
28303                     mContext.getResources().getDisplayMetrics());
28304         }
28305         return mVerticalScrollFactor;
28306     }
28307 
28308     /**
28309      * Gets a scale factor that determines the distance the view should scroll
28310      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
28311      * @return The horizontal scroll scale factor.
28312      * @hide
28313      */
28314     @UnsupportedAppUsage
getHorizontalScrollFactor()28315     protected float getHorizontalScrollFactor() {
28316         // TODO: Should use something else.
28317         return getVerticalScrollFactor();
28318     }
28319 
28320     /**
28321      * Return the value specifying the text direction or policy that was set with
28322      * {@link #setTextDirection(int)}.
28323      *
28324      * @return the defined text direction. It can be one of:
28325      *
28326      * {@link #TEXT_DIRECTION_INHERIT},
28327      * {@link #TEXT_DIRECTION_FIRST_STRONG},
28328      * {@link #TEXT_DIRECTION_ANY_RTL},
28329      * {@link #TEXT_DIRECTION_LTR},
28330      * {@link #TEXT_DIRECTION_RTL},
28331      * {@link #TEXT_DIRECTION_LOCALE},
28332      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
28333      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
28334      *
28335      * @attr ref android.R.styleable#View_textDirection
28336      *
28337      * @hide
28338      */
28339     @ViewDebug.ExportedProperty(category = "text", mapping = {
28340             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
28341             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
28342             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
28343             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
28344             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
28345             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
28346             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
28347             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
28348     })
28349     @InspectableProperty(hasAttributeId = false, enumMapping = {
28350             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
28351             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
28352             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
28353             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
28354             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
28355             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
28356             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
28357             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
28358     })
28359     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextDirection()28360     public int getRawTextDirection() {
28361         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
28362     }
28363 
28364     /**
28365      * Set the text direction.
28366      *
28367      * @param textDirection the direction to set. Should be one of:
28368      *
28369      * {@link #TEXT_DIRECTION_INHERIT},
28370      * {@link #TEXT_DIRECTION_FIRST_STRONG},
28371      * {@link #TEXT_DIRECTION_ANY_RTL},
28372      * {@link #TEXT_DIRECTION_LTR},
28373      * {@link #TEXT_DIRECTION_RTL},
28374      * {@link #TEXT_DIRECTION_LOCALE}
28375      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
28376      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
28377      *
28378      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
28379      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
28380      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
28381      *
28382      * @attr ref android.R.styleable#View_textDirection
28383      */
setTextDirection(int textDirection)28384     public void setTextDirection(int textDirection) {
28385         if (getRawTextDirection() != textDirection) {
28386             // Reset the current text direction and the resolved one
28387             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
28388             resetResolvedTextDirection();
28389             // Set the new text direction
28390             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
28391             // Do resolution
28392             resolveTextDirection();
28393             // Notify change
28394             onRtlPropertiesChanged(getLayoutDirection());
28395             // Refresh
28396             requestLayout();
28397             invalidate(true);
28398         }
28399     }
28400 
28401     /**
28402      * Return the resolved text direction.
28403      *
28404      * @return the resolved text direction. Returns one of:
28405      *
28406      * {@link #TEXT_DIRECTION_FIRST_STRONG},
28407      * {@link #TEXT_DIRECTION_ANY_RTL},
28408      * {@link #TEXT_DIRECTION_LTR},
28409      * {@link #TEXT_DIRECTION_RTL},
28410      * {@link #TEXT_DIRECTION_LOCALE},
28411      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
28412      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
28413      *
28414      * @attr ref android.R.styleable#View_textDirection
28415      */
28416     @ViewDebug.ExportedProperty(category = "text", mapping = {
28417             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
28418             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
28419             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
28420             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
28421             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
28422             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
28423             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
28424             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
28425     })
28426     @InspectableProperty(hasAttributeId = false, enumMapping = {
28427             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
28428             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
28429             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
28430             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
28431             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
28432             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
28433             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
28434     })
getTextDirection()28435     public int getTextDirection() {
28436         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
28437     }
28438 
28439     /**
28440      * Resolve the text direction.
28441      *
28442      * @return true if resolution has been done, false otherwise.
28443      *
28444      * @hide
28445      */
resolveTextDirection()28446     public boolean resolveTextDirection() {
28447         // Reset any previous text direction resolution
28448         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
28449 
28450         if (hasRtlSupport()) {
28451             // Set resolved text direction flag depending on text direction flag
28452             final int textDirection = getRawTextDirection();
28453             switch(textDirection) {
28454                 case TEXT_DIRECTION_INHERIT:
28455                     if (!canResolveTextDirection()) {
28456                         // We cannot do the resolution if there is no parent, so use the default one
28457                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28458                         // Resolution will need to happen again later
28459                         return false;
28460                     }
28461 
28462                     // Parent has not yet resolved, so we still return the default
28463                     try {
28464                         if (!mParent.isTextDirectionResolved()) {
28465                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28466                             // Resolution will need to happen again later
28467                             return false;
28468                         }
28469                     } catch (AbstractMethodError e) {
28470                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28471                                 " does not fully implement ViewParent", e);
28472                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
28473                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28474                         return true;
28475                     }
28476 
28477                     // Set current resolved direction to the same value as the parent's one
28478                     int parentResolvedDirection;
28479                     try {
28480                         parentResolvedDirection = mParent.getTextDirection();
28481                     } catch (AbstractMethodError e) {
28482                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28483                                 " does not fully implement ViewParent", e);
28484                         parentResolvedDirection = TEXT_DIRECTION_LTR;
28485                     }
28486                     switch (parentResolvedDirection) {
28487                         case TEXT_DIRECTION_FIRST_STRONG:
28488                         case TEXT_DIRECTION_ANY_RTL:
28489                         case TEXT_DIRECTION_LTR:
28490                         case TEXT_DIRECTION_RTL:
28491                         case TEXT_DIRECTION_LOCALE:
28492                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
28493                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
28494                             mPrivateFlags2 |=
28495                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
28496                             break;
28497                         default:
28498                             // Default resolved direction is "first strong" heuristic
28499                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28500                     }
28501                     break;
28502                 case TEXT_DIRECTION_FIRST_STRONG:
28503                 case TEXT_DIRECTION_ANY_RTL:
28504                 case TEXT_DIRECTION_LTR:
28505                 case TEXT_DIRECTION_RTL:
28506                 case TEXT_DIRECTION_LOCALE:
28507                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
28508                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
28509                     // Resolved direction is the same as text direction
28510                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
28511                     break;
28512                 default:
28513                     // Default resolved direction is "first strong" heuristic
28514                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28515             }
28516         } else {
28517             // Default resolved direction is "first strong" heuristic
28518             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28519         }
28520 
28521         // Set to resolved
28522         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
28523         return true;
28524     }
28525 
28526     /**
28527      * Check if text direction resolution can be done.
28528      *
28529      * @return true if text direction resolution can be done otherwise return false.
28530      */
canResolveTextDirection()28531     public boolean canResolveTextDirection() {
28532         switch (getRawTextDirection()) {
28533             case TEXT_DIRECTION_INHERIT:
28534                 if (mParent != null) {
28535                     try {
28536                         return mParent.canResolveTextDirection();
28537                     } catch (AbstractMethodError e) {
28538                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28539                                 " does not fully implement ViewParent", e);
28540                     }
28541                 }
28542                 return false;
28543 
28544             default:
28545                 return true;
28546         }
28547     }
28548 
28549     /**
28550      * Reset resolved text direction. Text direction will be resolved during a call to
28551      * {@link #onMeasure(int, int)}.
28552      *
28553      * @hide
28554      */
28555     @TestApi
resetResolvedTextDirection()28556     public void resetResolvedTextDirection() {
28557         // Reset any previous text direction resolution
28558         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
28559         // Set to default value
28560         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
28561     }
28562 
28563     /**
28564      * @return true if text direction is inherited.
28565      *
28566      * @hide
28567      */
isTextDirectionInherited()28568     public boolean isTextDirectionInherited() {
28569         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
28570     }
28571 
28572     /**
28573      * @return true if text direction is resolved.
28574      */
isTextDirectionResolved()28575     public boolean isTextDirectionResolved() {
28576         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
28577     }
28578 
28579     /**
28580      * Return the value specifying the text alignment or policy that was set with
28581      * {@link #setTextAlignment(int)}.
28582      *
28583      * @return the defined text alignment. It can be one of:
28584      *
28585      * {@link #TEXT_ALIGNMENT_INHERIT},
28586      * {@link #TEXT_ALIGNMENT_GRAVITY},
28587      * {@link #TEXT_ALIGNMENT_CENTER},
28588      * {@link #TEXT_ALIGNMENT_TEXT_START},
28589      * {@link #TEXT_ALIGNMENT_TEXT_END},
28590      * {@link #TEXT_ALIGNMENT_VIEW_START},
28591      * {@link #TEXT_ALIGNMENT_VIEW_END}
28592      *
28593      * @attr ref android.R.styleable#View_textAlignment
28594      *
28595      * @hide
28596      */
28597     @ViewDebug.ExportedProperty(category = "text", mapping = {
28598             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
28599             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
28600             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
28601             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
28602             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
28603             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
28604             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
28605     })
28606     @InspectableProperty(hasAttributeId = false, enumMapping = {
28607             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
28608             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
28609             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
28610             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
28611             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
28612             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
28613             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
28614     })
28615     @TextAlignment
28616     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextAlignment()28617     public int getRawTextAlignment() {
28618         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
28619     }
28620 
28621     /**
28622      * Set the text alignment.
28623      *
28624      * @param textAlignment The text alignment to set. Should be one of
28625      *
28626      * {@link #TEXT_ALIGNMENT_INHERIT},
28627      * {@link #TEXT_ALIGNMENT_GRAVITY},
28628      * {@link #TEXT_ALIGNMENT_CENTER},
28629      * {@link #TEXT_ALIGNMENT_TEXT_START},
28630      * {@link #TEXT_ALIGNMENT_TEXT_END},
28631      * {@link #TEXT_ALIGNMENT_VIEW_START},
28632      * {@link #TEXT_ALIGNMENT_VIEW_END}
28633      *
28634      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
28635      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
28636      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
28637      *
28638      * @attr ref android.R.styleable#View_textAlignment
28639      */
setTextAlignment(@extAlignment int textAlignment)28640     public void setTextAlignment(@TextAlignment int textAlignment) {
28641         if (textAlignment != getRawTextAlignment()) {
28642             // Reset the current and resolved text alignment
28643             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
28644             resetResolvedTextAlignment();
28645             // Set the new text alignment
28646             mPrivateFlags2 |=
28647                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
28648             // Do resolution
28649             resolveTextAlignment();
28650             // Notify change
28651             onRtlPropertiesChanged(getLayoutDirection());
28652             // Refresh
28653             requestLayout();
28654             invalidate(true);
28655         }
28656     }
28657 
28658     /**
28659      * Return the resolved text alignment.
28660      *
28661      * @return the resolved text alignment. Returns one of:
28662      *
28663      * {@link #TEXT_ALIGNMENT_GRAVITY},
28664      * {@link #TEXT_ALIGNMENT_CENTER},
28665      * {@link #TEXT_ALIGNMENT_TEXT_START},
28666      * {@link #TEXT_ALIGNMENT_TEXT_END},
28667      * {@link #TEXT_ALIGNMENT_VIEW_START},
28668      * {@link #TEXT_ALIGNMENT_VIEW_END}
28669      *
28670      * @attr ref android.R.styleable#View_textAlignment
28671      */
28672     @ViewDebug.ExportedProperty(category = "text", mapping = {
28673             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
28674             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
28675             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
28676             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
28677             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
28678             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
28679             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
28680     })
28681     @InspectableProperty(enumMapping = {
28682             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
28683             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
28684             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
28685             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
28686             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
28687             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
28688     })
28689     @TextAlignment
getTextAlignment()28690     public int getTextAlignment() {
28691         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
28692                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
28693     }
28694 
28695     /**
28696      * Resolve the text alignment.
28697      *
28698      * @return true if resolution has been done, false otherwise.
28699      *
28700      * @hide
28701      */
resolveTextAlignment()28702     public boolean resolveTextAlignment() {
28703         // Reset any previous text alignment resolution
28704         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
28705 
28706         if (hasRtlSupport()) {
28707             // Set resolved text alignment flag depending on text alignment flag
28708             final int textAlignment = getRawTextAlignment();
28709             switch (textAlignment) {
28710                 case TEXT_ALIGNMENT_INHERIT:
28711                     // Check if we can resolve the text alignment
28712                     if (!canResolveTextAlignment()) {
28713                         // We cannot do the resolution if there is no parent so use the default
28714                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28715                         // Resolution will need to happen again later
28716                         return false;
28717                     }
28718 
28719                     // Parent has not yet resolved, so we still return the default
28720                     try {
28721                         if (!mParent.isTextAlignmentResolved()) {
28722                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28723                             // Resolution will need to happen again later
28724                             return false;
28725                         }
28726                     } catch (AbstractMethodError e) {
28727                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28728                                 " does not fully implement ViewParent", e);
28729                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
28730                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28731                         return true;
28732                     }
28733 
28734                     int parentResolvedTextAlignment;
28735                     try {
28736                         parentResolvedTextAlignment = mParent.getTextAlignment();
28737                     } catch (AbstractMethodError e) {
28738                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28739                                 " does not fully implement ViewParent", e);
28740                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
28741                     }
28742                     switch (parentResolvedTextAlignment) {
28743                         case TEXT_ALIGNMENT_GRAVITY:
28744                         case TEXT_ALIGNMENT_TEXT_START:
28745                         case TEXT_ALIGNMENT_TEXT_END:
28746                         case TEXT_ALIGNMENT_CENTER:
28747                         case TEXT_ALIGNMENT_VIEW_START:
28748                         case TEXT_ALIGNMENT_VIEW_END:
28749                             // Resolved text alignment is the same as the parent resolved
28750                             // text alignment
28751                             mPrivateFlags2 |=
28752                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
28753                             break;
28754                         default:
28755                             // Use default resolved text alignment
28756                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28757                     }
28758                     break;
28759                 case TEXT_ALIGNMENT_GRAVITY:
28760                 case TEXT_ALIGNMENT_TEXT_START:
28761                 case TEXT_ALIGNMENT_TEXT_END:
28762                 case TEXT_ALIGNMENT_CENTER:
28763                 case TEXT_ALIGNMENT_VIEW_START:
28764                 case TEXT_ALIGNMENT_VIEW_END:
28765                     // Resolved text alignment is the same as text alignment
28766                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
28767                     break;
28768                 default:
28769                     // Use default resolved text alignment
28770                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28771             }
28772         } else {
28773             // Use default resolved text alignment
28774             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28775         }
28776 
28777         // Set the resolved
28778         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
28779         return true;
28780     }
28781 
28782     /**
28783      * Check if text alignment resolution can be done.
28784      *
28785      * @return true if text alignment resolution can be done otherwise return false.
28786      */
canResolveTextAlignment()28787     public boolean canResolveTextAlignment() {
28788         switch (getRawTextAlignment()) {
28789             case TEXT_DIRECTION_INHERIT:
28790                 if (mParent != null) {
28791                     try {
28792                         return mParent.canResolveTextAlignment();
28793                     } catch (AbstractMethodError e) {
28794                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28795                                 " does not fully implement ViewParent", e);
28796                     }
28797                 }
28798                 return false;
28799 
28800             default:
28801                 return true;
28802         }
28803     }
28804 
28805     /**
28806      * Reset resolved text alignment. Text alignment will be resolved during a call to
28807      * {@link #onMeasure(int, int)}.
28808      *
28809      * @hide
28810      */
28811     @TestApi
resetResolvedTextAlignment()28812     public void resetResolvedTextAlignment() {
28813         // Reset any previous text alignment resolution
28814         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
28815         // Set to default
28816         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28817     }
28818 
28819     /**
28820      * @return true if text alignment is inherited.
28821      *
28822      * @hide
28823      */
isTextAlignmentInherited()28824     public boolean isTextAlignmentInherited() {
28825         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
28826     }
28827 
28828     /**
28829      * @return true if text alignment is resolved.
28830      */
isTextAlignmentResolved()28831     public boolean isTextAlignmentResolved() {
28832         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
28833     }
28834 
28835     /**
28836      * Generate a value suitable for use in {@link #setId(int)}.
28837      * This value will not collide with ID values generated at build time by aapt for R.id.
28838      *
28839      * @return a generated ID value
28840      */
generateViewId()28841     public static int generateViewId() {
28842         for (;;) {
28843             final int result = sNextGeneratedId.get();
28844             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
28845             int newValue = result + 1;
28846             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
28847             if (sNextGeneratedId.compareAndSet(result, newValue)) {
28848                 return result;
28849             }
28850         }
28851     }
28852 
isViewIdGenerated(int id)28853     private static boolean isViewIdGenerated(int id) {
28854         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
28855     }
28856 
28857     /**
28858      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
28859      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
28860      *                           a normal View or a ViewGroup with
28861      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
28862      * @hide
28863      */
captureTransitioningViews(List<View> transitioningViews)28864     public void captureTransitioningViews(List<View> transitioningViews) {
28865         if (getVisibility() == View.VISIBLE) {
28866             transitioningViews.add(this);
28867         }
28868     }
28869 
28870     /**
28871      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
28872      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
28873      * @hide
28874      */
findNamedViews(Map<String, View> namedElements)28875     public void findNamedViews(Map<String, View> namedElements) {
28876         if (getVisibility() == VISIBLE || mGhostView != null) {
28877             String transitionName = getTransitionName();
28878             if (transitionName != null) {
28879                 namedElements.put(transitionName, this);
28880             }
28881         }
28882     }
28883 
28884     /**
28885      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
28886      * The default implementation does not care the location or event types, but some subclasses
28887      * may use it (such as WebViews).
28888      * @param event The MotionEvent from a mouse
28889      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
28890      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
28891      * @see PointerIcon
28892      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)28893     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
28894         final float x = event.getX(pointerIndex);
28895         final float y = event.getY(pointerIndex);
28896         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
28897             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
28898         }
28899         return mPointerIcon;
28900     }
28901 
28902     /**
28903      * Set the pointer icon for the current view.
28904      * Passing {@code null} will restore the pointer icon to its default value.
28905      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
28906      */
setPointerIcon(PointerIcon pointerIcon)28907     public void setPointerIcon(PointerIcon pointerIcon) {
28908         mPointerIcon = pointerIcon;
28909         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
28910             return;
28911         }
28912         try {
28913             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
28914         } catch (RemoteException e) {
28915         }
28916     }
28917 
28918     /**
28919      * Gets the pointer icon for the current view.
28920      */
28921     @InspectableProperty
getPointerIcon()28922     public PointerIcon getPointerIcon() {
28923         return mPointerIcon;
28924     }
28925 
28926     /**
28927      * Checks pointer capture status.
28928      *
28929      * @return true if the view has pointer capture.
28930      * @see #requestPointerCapture()
28931      * @see #hasPointerCapture()
28932      */
hasPointerCapture()28933     public boolean hasPointerCapture() {
28934         final ViewRootImpl viewRootImpl = getViewRootImpl();
28935         if (viewRootImpl == null) {
28936             return false;
28937         }
28938         return viewRootImpl.hasPointerCapture();
28939     }
28940 
28941     /**
28942      * Requests pointer capture mode.
28943      * <p>
28944      * When the window has pointer capture, the mouse pointer icon will disappear and will not
28945      * change its position. Enabling pointer capture will change the behavior of input devices in
28946      * the following ways:
28947      * <ul>
28948      *     <li>Events from a mouse will be delivered with the source
28949      *     {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
28950      *     available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
28951      *
28952      *     <li>Events from a touchpad or trackpad will be delivered with the source
28953      *     {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
28954      *     on the touchpad will be available through {@link MotionEvent#getX(int)} and
28955      *     {@link MotionEvent#getY(int)}, and their relative movements are stored in
28956      *     {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li>
28957      *
28958      *     <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
28959      * </ul>
28960      * <p>
28961      * When pointer capture changes, connected mouse and trackpad devices may be reconfigured,
28962      * and their properties (such as their sources or motion ranges) may change. Use an
28963      * {@link android.hardware.input.InputManager.InputDeviceListener} to be notified when a device
28964      * changes (which may happen after enabling or disabling pointer capture), and use
28965      * {@link InputDevice#getDevice(int)} to get the updated {@link InputDevice}.
28966      * <p>
28967      * Events captured through pointer capture will be dispatched to
28968      * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
28969      * {@link OnCapturedPointerListener} is set, and otherwise to
28970      * {@link #onCapturedPointerEvent(MotionEvent)}.
28971      * <p>
28972      * If the window already has pointer capture, this call does nothing.
28973      * <p>
28974      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
28975      * automatically when the window loses focus.
28976      *
28977      * @see #releasePointerCapture()
28978      * @see #hasPointerCapture()
28979      * @see #onPointerCaptureChange(boolean)
28980      */
requestPointerCapture()28981     public void requestPointerCapture() {
28982         final ViewRootImpl viewRootImpl = getViewRootImpl();
28983         if (viewRootImpl != null) {
28984             viewRootImpl.requestPointerCapture(true);
28985         }
28986     }
28987 
28988 
28989     /**
28990      * Releases the pointer capture.
28991      * <p>
28992      * If the window does not have pointer capture, this call will do nothing.
28993      * @see #requestPointerCapture()
28994      * @see #hasPointerCapture()
28995      * @see #onPointerCaptureChange(boolean)
28996      */
releasePointerCapture()28997     public void releasePointerCapture() {
28998         final ViewRootImpl viewRootImpl = getViewRootImpl();
28999         if (viewRootImpl != null) {
29000             viewRootImpl.requestPointerCapture(false);
29001         }
29002     }
29003 
29004     /**
29005      * Called when the window has just acquired or lost pointer capture.
29006      *
29007      * @param hasCapture True if the view now has pointerCapture, false otherwise.
29008      */
29009     @CallSuper
onPointerCaptureChange(boolean hasCapture)29010     public void onPointerCaptureChange(boolean hasCapture) {
29011     }
29012 
29013     /**
29014      * @see #onPointerCaptureChange
29015      */
dispatchPointerCaptureChanged(boolean hasCapture)29016     public void dispatchPointerCaptureChanged(boolean hasCapture) {
29017         onPointerCaptureChange(hasCapture);
29018     }
29019 
29020     /**
29021      * Implement this method to handle captured pointer events
29022      *
29023      * @param event The captured pointer event.
29024      * @return True if the event was handled, false otherwise.
29025      * @see #requestPointerCapture()
29026      */
onCapturedPointerEvent(MotionEvent event)29027     public boolean onCapturedPointerEvent(MotionEvent event) {
29028         return false;
29029     }
29030 
29031     /**
29032      * Interface definition for a callback to be invoked when a captured pointer event
29033      * is being dispatched this view. The callback will be invoked before the event is
29034      * given to the view.
29035      */
29036     public interface OnCapturedPointerListener {
29037         /**
29038          * Called when a captured pointer event is dispatched to a view.
29039          * @param view The view this event has been dispatched to.
29040          * @param event The captured event.
29041          * @return True if the listener has consumed the event, false otherwise.
29042          */
onCapturedPointer(View view, MotionEvent event)29043         boolean onCapturedPointer(View view, MotionEvent event);
29044     }
29045 
29046     /**
29047      * Set a listener to receive callbacks when the pointer capture state of a view changes.
29048      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
29049      */
setOnCapturedPointerListener(OnCapturedPointerListener l)29050     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
29051         getListenerInfo().mOnCapturedPointerListener = l;
29052     }
29053 
29054     // Properties
29055     //
29056     /**
29057      * A Property wrapper around the <code>alpha</code> functionality handled by the
29058      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
29059      */
29060     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
29061         @Override
29062         public void setValue(View object, float value) {
29063             object.setAlpha(value);
29064         }
29065 
29066         @Override
29067         public Float get(View object) {
29068             return object.getAlpha();
29069         }
29070     };
29071 
29072     /**
29073      * A Property wrapper around the <code>translationX</code> functionality handled by the
29074      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
29075      */
29076     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
29077         @Override
29078         public void setValue(View object, float value) {
29079             object.setTranslationX(value);
29080         }
29081 
29082                 @Override
29083         public Float get(View object) {
29084             return object.getTranslationX();
29085         }
29086     };
29087 
29088     /**
29089      * A Property wrapper around the <code>translationY</code> functionality handled by the
29090      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
29091      */
29092     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
29093         @Override
29094         public void setValue(View object, float value) {
29095             object.setTranslationY(value);
29096         }
29097 
29098         @Override
29099         public Float get(View object) {
29100             return object.getTranslationY();
29101         }
29102     };
29103 
29104     /**
29105      * A Property wrapper around the <code>translationZ</code> functionality handled by the
29106      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
29107      */
29108     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
29109         @Override
29110         public void setValue(View object, float value) {
29111             object.setTranslationZ(value);
29112         }
29113 
29114         @Override
29115         public Float get(View object) {
29116             return object.getTranslationZ();
29117         }
29118     };
29119 
29120     /**
29121      * A Property wrapper around the <code>x</code> functionality handled by the
29122      * {@link View#setX(float)} and {@link View#getX()} methods.
29123      */
29124     public static final Property<View, Float> X = new FloatProperty<View>("x") {
29125         @Override
29126         public void setValue(View object, float value) {
29127             object.setX(value);
29128         }
29129 
29130         @Override
29131         public Float get(View object) {
29132             return object.getX();
29133         }
29134     };
29135 
29136     /**
29137      * A Property wrapper around the <code>y</code> functionality handled by the
29138      * {@link View#setY(float)} and {@link View#getY()} methods.
29139      */
29140     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
29141         @Override
29142         public void setValue(View object, float value) {
29143             object.setY(value);
29144         }
29145 
29146         @Override
29147         public Float get(View object) {
29148             return object.getY();
29149         }
29150     };
29151 
29152     /**
29153      * A Property wrapper around the <code>z</code> functionality handled by the
29154      * {@link View#setZ(float)} and {@link View#getZ()} methods.
29155      */
29156     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
29157         @Override
29158         public void setValue(View object, float value) {
29159             object.setZ(value);
29160         }
29161 
29162         @Override
29163         public Float get(View object) {
29164             return object.getZ();
29165         }
29166     };
29167 
29168     /**
29169      * A Property wrapper around the <code>rotation</code> functionality handled by the
29170      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
29171      */
29172     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
29173         @Override
29174         public void setValue(View object, float value) {
29175             object.setRotation(value);
29176         }
29177 
29178         @Override
29179         public Float get(View object) {
29180             return object.getRotation();
29181         }
29182     };
29183 
29184     /**
29185      * A Property wrapper around the <code>rotationX</code> functionality handled by the
29186      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
29187      */
29188     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
29189         @Override
29190         public void setValue(View object, float value) {
29191             object.setRotationX(value);
29192         }
29193 
29194         @Override
29195         public Float get(View object) {
29196             return object.getRotationX();
29197         }
29198     };
29199 
29200     /**
29201      * A Property wrapper around the <code>rotationY</code> functionality handled by the
29202      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
29203      */
29204     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
29205         @Override
29206         public void setValue(View object, float value) {
29207             object.setRotationY(value);
29208         }
29209 
29210         @Override
29211         public Float get(View object) {
29212             return object.getRotationY();
29213         }
29214     };
29215 
29216     /**
29217      * A Property wrapper around the <code>scaleX</code> functionality handled by the
29218      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
29219      */
29220     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
29221         @Override
29222         public void setValue(View object, float value) {
29223             object.setScaleX(value);
29224         }
29225 
29226         @Override
29227         public Float get(View object) {
29228             return object.getScaleX();
29229         }
29230     };
29231 
29232     /**
29233      * A Property wrapper around the <code>scaleY</code> functionality handled by the
29234      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
29235      */
29236     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
29237         @Override
29238         public void setValue(View object, float value) {
29239             object.setScaleY(value);
29240         }
29241 
29242         @Override
29243         public Float get(View object) {
29244             return object.getScaleY();
29245         }
29246     };
29247 
29248     /**
29249      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
29250      * Each MeasureSpec represents a requirement for either the width or the height.
29251      * A MeasureSpec is comprised of a size and a mode. There are three possible
29252      * modes:
29253      * <dl>
29254      * <dt>UNSPECIFIED</dt>
29255      * <dd>
29256      * The parent has not imposed any constraint on the child. It can be whatever size
29257      * it wants.
29258      * </dd>
29259      *
29260      * <dt>EXACTLY</dt>
29261      * <dd>
29262      * The parent has determined an exact size for the child. The child is going to be
29263      * given those bounds regardless of how big it wants to be.
29264      * </dd>
29265      *
29266      * <dt>AT_MOST</dt>
29267      * <dd>
29268      * The child can be as large as it wants up to the specified size.
29269      * </dd>
29270      * </dl>
29271      *
29272      * MeasureSpecs are implemented as ints to reduce object allocation. This class
29273      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
29274      */
29275     public static class MeasureSpec {
29276         private static final int MODE_SHIFT = 30;
29277         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
29278 
29279         /** @hide */
29280         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
29281         @Retention(RetentionPolicy.SOURCE)
29282         public @interface MeasureSpecMode {}
29283 
29284         /**
29285          * Measure specification mode: The parent has not imposed any constraint
29286          * on the child. It can be whatever size it wants.
29287          */
29288         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
29289 
29290         /**
29291          * Measure specification mode: The parent has determined an exact size
29292          * for the child. The child is going to be given those bounds regardless
29293          * of how big it wants to be.
29294          */
29295         public static final int EXACTLY     = 1 << MODE_SHIFT;
29296 
29297         /**
29298          * Measure specification mode: The child can be as large as it wants up
29299          * to the specified size.
29300          */
29301         public static final int AT_MOST     = 2 << MODE_SHIFT;
29302 
29303         /**
29304          * Creates a measure specification based on the supplied size and mode.
29305          *
29306          * The mode must always be one of the following:
29307          * <ul>
29308          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
29309          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
29310          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
29311          * </ul>
29312          *
29313          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
29314          * implementation was such that the order of arguments did not matter
29315          * and overflow in either value could impact the resulting MeasureSpec.
29316          * {@link android.widget.RelativeLayout} was affected by this bug.
29317          * Apps targeting API levels greater than 17 will get the fixed, more strict
29318          * behavior.</p>
29319          *
29320          * @param size the size of the measure specification
29321          * @param mode the mode of the measure specification
29322          * @return the measure specification based on size and mode
29323          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)29324         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
29325                                           @MeasureSpecMode int mode) {
29326             if (sUseBrokenMakeMeasureSpec) {
29327                 return size + mode;
29328             } else {
29329                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
29330             }
29331         }
29332 
29333         /**
29334          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
29335          * will automatically get a size of 0. Older apps expect this.
29336          *
29337          * @hide internal use only for compatibility with system widgets and older apps
29338          */
29339         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)29340         public static int makeSafeMeasureSpec(int size, int mode) {
29341             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
29342                 return 0;
29343             }
29344             return makeMeasureSpec(size, mode);
29345         }
29346 
29347         /**
29348          * Extracts the mode from the supplied measure specification.
29349          *
29350          * @param measureSpec the measure specification to extract the mode from
29351          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
29352          *         {@link android.view.View.MeasureSpec#AT_MOST} or
29353          *         {@link android.view.View.MeasureSpec#EXACTLY}
29354          */
29355         @MeasureSpecMode
getMode(int measureSpec)29356         public static int getMode(int measureSpec) {
29357             //noinspection ResourceType
29358             return (measureSpec & MODE_MASK);
29359         }
29360 
29361         /**
29362          * Extracts the size from the supplied measure specification.
29363          *
29364          * @param measureSpec the measure specification to extract the size from
29365          * @return the size in pixels defined in the supplied measure specification
29366          */
getSize(int measureSpec)29367         public static int getSize(int measureSpec) {
29368             return (measureSpec & ~MODE_MASK);
29369         }
29370 
adjust(int measureSpec, int delta)29371         static int adjust(int measureSpec, int delta) {
29372             final int mode = getMode(measureSpec);
29373             int size = getSize(measureSpec);
29374             if (mode == UNSPECIFIED) {
29375                 // No need to adjust size for UNSPECIFIED mode.
29376                 return makeMeasureSpec(size, UNSPECIFIED);
29377             }
29378             size += delta;
29379             if (size < 0) {
29380                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
29381                         ") spec: " + toString(measureSpec) + " delta: " + delta);
29382                 size = 0;
29383             }
29384             return makeMeasureSpec(size, mode);
29385         }
29386 
29387         /**
29388          * Returns a String representation of the specified measure
29389          * specification.
29390          *
29391          * @param measureSpec the measure specification to convert to a String
29392          * @return a String with the following format: "MeasureSpec: MODE SIZE"
29393          */
toString(int measureSpec)29394         public static String toString(int measureSpec) {
29395             int mode = getMode(measureSpec);
29396             int size = getSize(measureSpec);
29397 
29398             StringBuilder sb = new StringBuilder("MeasureSpec: ");
29399 
29400             if (mode == UNSPECIFIED)
29401                 sb.append("UNSPECIFIED ");
29402             else if (mode == EXACTLY)
29403                 sb.append("EXACTLY ");
29404             else if (mode == AT_MOST)
29405                 sb.append("AT_MOST ");
29406             else
29407                 sb.append(mode).append(" ");
29408 
29409             sb.append(size);
29410             return sb.toString();
29411         }
29412     }
29413 
29414     private final class CheckForLongPress implements Runnable {
29415         private int mOriginalWindowAttachCount;
29416         private float mX;
29417         private float mY;
29418         private boolean mOriginalPressedState;
29419         /**
29420          * The classification of the long click being checked: one of the
29421          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
29422          */
29423         private int mClassification;
29424 
29425         @UnsupportedAppUsage
CheckForLongPress()29426         private CheckForLongPress() {
29427         }
29428 
29429         @Override
run()29430         public void run() {
29431             if ((mOriginalPressedState == isPressed()) && (mParent != null)
29432                     && mOriginalWindowAttachCount == mWindowAttachCount) {
29433                 recordGestureClassification(mClassification);
29434                 if (performLongClick(mX, mY)) {
29435                     mHasPerformedLongPress = true;
29436                 }
29437             }
29438         }
29439 
setAnchor(float x, float y)29440         public void setAnchor(float x, float y) {
29441             mX = x;
29442             mY = y;
29443         }
29444 
rememberWindowAttachCount()29445         public void rememberWindowAttachCount() {
29446             mOriginalWindowAttachCount = mWindowAttachCount;
29447         }
29448 
rememberPressedState()29449         public void rememberPressedState() {
29450             mOriginalPressedState = isPressed();
29451         }
29452 
setClassification(int classification)29453         public void setClassification(int classification) {
29454             mClassification = classification;
29455         }
29456     }
29457 
29458     private final class CheckForTap implements Runnable {
29459         public float x;
29460         public float y;
29461 
29462         @Override
run()29463         public void run() {
29464             mPrivateFlags &= ~PFLAG_PREPRESSED;
29465             setPressed(true, x, y);
29466             final long delay =
29467                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
29468             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
29469         }
29470     }
29471 
29472     private final class PerformClick implements Runnable {
29473         @Override
run()29474         public void run() {
29475             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
29476             performClickInternal();
29477         }
29478     }
29479 
29480     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)29481     private void recordGestureClassification(int classification) {
29482         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
29483             return;
29484         }
29485         // To avoid negatively impacting View performance, the latency and displacement metrics
29486         // are omitted.
29487         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
29488                 classification);
29489     }
29490 
29491     /**
29492      * This method returns a ViewPropertyAnimator object, which can be used to animate
29493      * specific properties on this View.
29494      *
29495      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
29496      */
animate()29497     public ViewPropertyAnimator animate() {
29498         if (mAnimator == null) {
29499             mAnimator = new ViewPropertyAnimator(this);
29500         }
29501         return mAnimator;
29502     }
29503 
29504     /**
29505      * Sets the name of the View to be used to identify Views in Transitions.
29506      * Names should be unique in the View hierarchy.
29507      *
29508      * @param transitionName The name of the View to uniquely identify it for Transitions.
29509      */
setTransitionName(String transitionName)29510     public final void setTransitionName(String transitionName) {
29511         mTransitionName = transitionName;
29512     }
29513 
29514     /**
29515      * Returns the name of the View to be used to identify Views in Transitions.
29516      * Names should be unique in the View hierarchy.
29517      *
29518      * <p>This returns null if the View has not been given a name.</p>
29519      *
29520      * @return The name used of the View to be used to identify Views in Transitions or null
29521      * if no name has been given.
29522      */
29523     @ViewDebug.ExportedProperty
29524     @InspectableProperty
getTransitionName()29525     public String getTransitionName() {
29526         return mTransitionName;
29527     }
29528 
29529     /**
29530      * @hide
29531      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)29532     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
29533         // Do nothing.
29534     }
29535 
29536     /**
29537      * Interface definition for a callback to be invoked when a hardware key event is
29538      * dispatched to this view. The callback will be invoked before the key event is
29539      * given to the view. This is only useful for hardware keyboards; a software input
29540      * method has no obligation to trigger this listener.
29541      */
29542     public interface OnKeyListener {
29543         /**
29544          * Called when a hardware key is dispatched to a view. This allows listeners to
29545          * get a chance to respond before the target view.
29546          * <p>Key presses in software keyboards will generally NOT trigger this method,
29547          * although some may elect to do so in some situations. Do not assume a
29548          * software input method has to be key-based; even if it is, it may use key presses
29549          * in a different way than you expect, so there is no way to reliably catch soft
29550          * input key presses.
29551          *
29552          * @param v The view the key has been dispatched to.
29553          * @param keyCode The code for the physical key that was pressed
29554          * @param event The KeyEvent object containing full information about
29555          *        the event.
29556          * @return True if the listener has consumed the event, false otherwise.
29557          */
onKey(View v, int keyCode, KeyEvent event)29558         boolean onKey(View v, int keyCode, KeyEvent event);
29559     }
29560 
29561     /**
29562      * Interface definition for a callback to be invoked when a hardware key event hasn't
29563      * been handled by the view hierarchy.
29564      */
29565     public interface OnUnhandledKeyEventListener {
29566         /**
29567          * Called when a hardware key is dispatched to a view after being unhandled during normal
29568          * {@link KeyEvent} dispatch.
29569          *
29570          * @param v The view the key has been dispatched to.
29571          * @param event The KeyEvent object containing information about the event.
29572          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
29573          */
onUnhandledKeyEvent(View v, KeyEvent event)29574         boolean onUnhandledKeyEvent(View v, KeyEvent event);
29575     }
29576 
29577     /**
29578      * Interface definition for a callback to be invoked when a touch event is
29579      * dispatched to this view. The callback will be invoked before the touch
29580      * event is given to the view.
29581      */
29582     public interface OnTouchListener {
29583         /**
29584          * Called when a touch event is dispatched to a view. This allows listeners to
29585          * get a chance to respond before the target view.
29586          *
29587          * @param v The view the touch event has been dispatched to.
29588          * @param event The MotionEvent object containing full information about
29589          *        the event.
29590          * @return True if the listener has consumed the event, false otherwise.
29591          */
onTouch(View v, MotionEvent event)29592         boolean onTouch(View v, MotionEvent event);
29593     }
29594 
29595     /**
29596      * Interface definition for a callback to be invoked when a hover event is
29597      * dispatched to this view. The callback will be invoked before the hover
29598      * event is given to the view.
29599      */
29600     public interface OnHoverListener {
29601         /**
29602          * Called when a hover event is dispatched to a view. This allows listeners to
29603          * get a chance to respond before the target view.
29604          *
29605          * @param v The view the hover event has been dispatched to.
29606          * @param event The MotionEvent object containing full information about
29607          *        the event.
29608          * @return True if the listener has consumed the event, false otherwise.
29609          */
onHover(View v, MotionEvent event)29610         boolean onHover(View v, MotionEvent event);
29611     }
29612 
29613     /**
29614      * Interface definition for a callback to be invoked when a generic motion event is
29615      * dispatched to this view. The callback will be invoked before the generic motion
29616      * event is given to the view.
29617      */
29618     public interface OnGenericMotionListener {
29619         /**
29620          * Called when a generic motion event is dispatched to a view. This allows listeners to
29621          * get a chance to respond before the target view.
29622          *
29623          * @param v The view the generic motion event has been dispatched to.
29624          * @param event The MotionEvent object containing full information about
29625          *        the event.
29626          * @return True if the listener has consumed the event, false otherwise.
29627          */
onGenericMotion(View v, MotionEvent event)29628         boolean onGenericMotion(View v, MotionEvent event);
29629     }
29630 
29631     /**
29632      * Interface definition for a callback to be invoked when a view has been clicked and held.
29633      */
29634     public interface OnLongClickListener {
29635         /**
29636          * Called when a view has been clicked and held.
29637          *
29638          * @param v The view that was clicked and held.
29639          *
29640          * @return true if the callback consumed the long click, false otherwise.
29641          */
onLongClick(View v)29642         boolean onLongClick(View v);
29643     }
29644 
29645     /**
29646      * Interface definition for a listener that's invoked when a drag event is dispatched to this
29647      * view. The listener is invoked before the view's own
29648      * {@link #onDragEvent(DragEvent)} method. To fall back to the view's
29649      * {@code onDragEvent(DragEvent)} behavior, return {@code false} from the listener method.
29650      *
29651      * <div class="special reference">
29652      *   <h3>Developer Guides</h3>
29653      *   <p>For a guide to implementing drag and drop features, see the
29654      *   <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and drop</a> developer guide.</p>
29655      * </div>
29656      */
29657     public interface OnDragListener {
29658         /**
29659          * Called when a drag event is dispatched to a view. Enables listeners to override the
29660          * base behavior provided by {@link #onDragEvent(DragEvent)}.
29661          *
29662          * @param v The {@code View} that received the drag event.
29663          * @param event The event object for the drag event.
29664          * @return {@code true} if the drag event was handled successfully; {@code false}, if the
29665          *   drag event was not handled. <b>Note:</b> A {@code false} return value triggers the
29666          *   view's {@link #onDragEvent(DragEvent)} handler.
29667          */
onDrag(View v, DragEvent event)29668         boolean onDrag(View v, DragEvent event);
29669     }
29670 
29671     /**
29672      * Interface definition for a callback to be invoked when the focus state of
29673      * a view changed.
29674      */
29675     public interface OnFocusChangeListener {
29676         /**
29677          * Called when the focus state of a view has changed.
29678          *
29679          * @param v The view whose state has changed.
29680          * @param hasFocus The new focus state of v.
29681          */
onFocusChange(View v, boolean hasFocus)29682         void onFocusChange(View v, boolean hasFocus);
29683     }
29684 
29685     /**
29686      * Interface definition for a callback to be invoked when a view is clicked.
29687      */
29688     public interface OnClickListener {
29689         /**
29690          * Called when a view has been clicked.
29691          *
29692          * @param v The view that was clicked.
29693          */
onClick(View v)29694         void onClick(View v);
29695     }
29696 
29697     /**
29698      * Interface definition for a callback to be invoked when a view is context clicked.
29699      */
29700     public interface OnContextClickListener {
29701         /**
29702          * Called when a view is context clicked.
29703          *
29704          * @param v The view that has been context clicked.
29705          * @return true if the callback consumed the context click, false otherwise.
29706          */
onContextClick(View v)29707         boolean onContextClick(View v);
29708     }
29709 
29710     /**
29711      * Interface definition for a callback to be invoked when the context menu
29712      * for this view is being built.
29713      */
29714     public interface OnCreateContextMenuListener {
29715         /**
29716          * Called when the context menu for this view is being built. It is not
29717          * safe to hold onto the menu after this method returns.
29718          *
29719          * @param menu The context menu that is being built
29720          * @param v The view for which the context menu is being built
29721          * @param menuInfo Extra information about the item for which the
29722          *            context menu should be shown. This information will vary
29723          *            depending on the class of v.
29724          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)29725         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
29726     }
29727 
29728     /**
29729      * Interface definition for a callback to be invoked when the status bar changes
29730      * visibility.  This reports <strong>global</strong> changes to the system UI
29731      * state, not what the application is requesting.
29732      *
29733      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
29734      *
29735      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
29736      * by setting a {@link OnApplyWindowInsetsListener} on this view.
29737      */
29738     @Deprecated
29739     public interface OnSystemUiVisibilityChangeListener {
29740         /**
29741          * Called when the status bar changes visibility because of a call to
29742          * {@link View#setSystemUiVisibility(int)}.
29743          *
29744          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
29745          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
29746          * This tells you the <strong>global</strong> state of these UI visibility
29747          * flags, not what your app is currently applying.
29748          */
onSystemUiVisibilityChange(int visibility)29749         public void onSystemUiVisibilityChange(int visibility);
29750     }
29751 
29752     /**
29753      * Interface definition for a callback to be invoked when this view is attached
29754      * or detached from its window.
29755      */
29756     public interface OnAttachStateChangeListener {
29757         /**
29758          * Called when the view is attached to a window.
29759          * @param v The view that was attached
29760          */
onViewAttachedToWindow(@onNull View v)29761         public void onViewAttachedToWindow(@NonNull View v);
29762         /**
29763          * Called when the view is detached from a window.
29764          * @param v The view that was detached
29765          */
onViewDetachedFromWindow(@onNull View v)29766         public void onViewDetachedFromWindow(@NonNull View v);
29767     }
29768 
29769     /**
29770      * Listener for applying window insets on a view in a custom way.
29771      *
29772      * <p>Apps may choose to implement this interface if they want to apply custom policy
29773      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
29774      * is set, its
29775      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
29776      * method will be called instead of the View's own
29777      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
29778      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
29779      * the View's normal behavior as part of its own.</p>
29780      */
29781     public interface OnApplyWindowInsetsListener {
29782         /**
29783          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
29784          * on a View, this listener method will be called instead of the view's own
29785          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
29786          *
29787          * @param v The view applying window insets
29788          * @param insets The insets to apply
29789          * @return The insets supplied, minus any insets that were consumed
29790          */
onApplyWindowInsets(@onNull View v, @NonNull WindowInsets insets)29791         public @NonNull WindowInsets onApplyWindowInsets(@NonNull View v,
29792                 @NonNull WindowInsets insets);
29793     }
29794 
29795     private final class UnsetPressedState implements Runnable {
29796         @Override
run()29797         public void run() {
29798             setPressed(false);
29799         }
29800     }
29801 
29802     /**
29803      * When a view becomes invisible checks if autofill considers the view invisible too. This
29804      * happens after the regular removal operation to make sure the operation is finished by the
29805      * time this is called.
29806      */
29807     private static class VisibilityChangeForAutofillHandler extends Handler {
29808         private final AutofillManager mAfm;
29809         private final View mView;
29810 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)29811         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
29812                 @NonNull View view) {
29813             mAfm = afm;
29814             mView = view;
29815         }
29816 
29817         @Override
handleMessage(Message msg)29818         public void handleMessage(Message msg) {
29819             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
29820         }
29821     }
29822 
29823     /**
29824      * Base class for derived classes that want to save and restore their own
29825      * state in {@link android.view.View#onSaveInstanceState()}.
29826      */
29827     public static class BaseSavedState extends AbsSavedState {
29828         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
29829         static final int IS_AUTOFILLED = 0b10;
29830         static final int AUTOFILL_ID = 0b100;
29831 
29832         // Flags that describe what data in this state is valid
29833         int mSavedData;
29834         String mStartActivityRequestWhoSaved;
29835         boolean mIsAutofilled;
29836         boolean mHideHighlight;
29837         int mAutofillViewId;
29838 
29839         /**
29840          * Constructor used when reading from a parcel. Reads the state of the superclass.
29841          *
29842          * @param source parcel to read from
29843          */
BaseSavedState(Parcel source)29844         public BaseSavedState(Parcel source) {
29845             this(source, null);
29846         }
29847 
29848         /**
29849          * Constructor used when reading from a parcel using a given class loader.
29850          * Reads the state of the superclass.
29851          *
29852          * @param source parcel to read from
29853          * @param loader ClassLoader to use for reading
29854          */
BaseSavedState(Parcel source, ClassLoader loader)29855         public BaseSavedState(Parcel source, ClassLoader loader) {
29856             super(source, loader);
29857             mSavedData = source.readInt();
29858             mStartActivityRequestWhoSaved = source.readString();
29859             mIsAutofilled = source.readBoolean();
29860             mHideHighlight = source.readBoolean();
29861             mAutofillViewId = source.readInt();
29862         }
29863 
29864         /**
29865          * Constructor called by derived classes when creating their SavedState objects
29866          *
29867          * @param superState The state of the superclass of this view
29868          */
BaseSavedState(Parcelable superState)29869         public BaseSavedState(Parcelable superState) {
29870             super(superState);
29871         }
29872 
29873         @Override
writeToParcel(Parcel out, int flags)29874         public void writeToParcel(Parcel out, int flags) {
29875             super.writeToParcel(out, flags);
29876 
29877             out.writeInt(mSavedData);
29878             out.writeString(mStartActivityRequestWhoSaved);
29879             out.writeBoolean(mIsAutofilled);
29880             out.writeBoolean(mHideHighlight);
29881             out.writeInt(mAutofillViewId);
29882         }
29883 
29884         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
29885                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
29886             @Override
29887             public BaseSavedState createFromParcel(Parcel in) {
29888                 return new BaseSavedState(in);
29889             }
29890 
29891             @Override
29892             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
29893                 return new BaseSavedState(in, loader);
29894             }
29895 
29896             @Override
29897             public BaseSavedState[] newArray(int size) {
29898                 return new BaseSavedState[size];
29899             }
29900         };
29901     }
29902 
29903     /**
29904      * A set of information given to a view when it is attached to its parent
29905      * window.
29906      */
29907     final static class AttachInfo {
29908 
29909         interface Callbacks {
playSoundEffect(int effectId)29910             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)29911             boolean performHapticFeedback(int effectId, boolean always);
29912         }
29913 
29914         /**
29915          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
29916          * to a Handler. This class contains the target (View) to invalidate and
29917          * the coordinates of the dirty rectangle.
29918          *
29919          * For performance purposes, this class also implements a pool of up to
29920          * POOL_LIMIT objects that get reused. This reduces memory allocations
29921          * whenever possible.
29922          */
29923         static class InvalidateInfo {
29924 
29925             @UnsupportedAppUsage
InvalidateInfo()29926             InvalidateInfo() {
29927             }
29928 
29929             private static final int POOL_LIMIT = 10;
29930 
29931             private static final SynchronizedPool<InvalidateInfo> sPool =
29932                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
29933 
29934             @UnsupportedAppUsage
29935             View target;
29936 
29937             @UnsupportedAppUsage
29938             int left;
29939             @UnsupportedAppUsage
29940             int top;
29941             @UnsupportedAppUsage
29942             int right;
29943             @UnsupportedAppUsage
29944             int bottom;
29945 
obtain()29946             public static InvalidateInfo obtain() {
29947                 InvalidateInfo instance = sPool.acquire();
29948                 return (instance != null) ? instance : new InvalidateInfo();
29949             }
29950 
recycle()29951             public void recycle() {
29952                 target = null;
29953                 sPool.release(this);
29954             }
29955         }
29956 
29957         @UnsupportedAppUsage
29958         final IWindowSession mSession;
29959 
29960         @UnsupportedAppUsage
29961         final IWindow mWindow;
29962 
29963         final IBinder mWindowToken;
29964 
29965         Display mDisplay;
29966 
29967         final Callbacks mRootCallbacks;
29968 
29969         IWindowId mIWindowId;
29970         WindowId mWindowId;
29971 
29972         /**
29973          * The top view of the hierarchy.
29974          */
29975         View mRootView;
29976 
29977         IBinder mPanelParentWindowToken;
29978 
29979         boolean mHardwareAccelerated;
29980         boolean mHardwareAccelerationRequested;
29981         ThreadedRenderer mThreadedRenderer;
29982         List<RenderNode> mPendingAnimatingRenderNodes;
29983 
29984         /**
29985          * The state of the display to which the window is attached, as reported
29986          * by {@link Display#getState()}.  Note that the display state constants
29987          * declared by {@link Display} do not exactly line up with the screen state
29988          * constants declared by {@link View} (there are more display states than
29989          * screen states).
29990          */
29991         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
29992         int mDisplayState = Display.STATE_UNKNOWN;
29993 
29994         /**
29995          * Scale factor used by the compatibility mode
29996          */
29997         @UnsupportedAppUsage
29998         float mApplicationScale;
29999 
30000         /**
30001          * Indicates whether the application is in compatibility mode
30002          */
30003         @UnsupportedAppUsage
30004         boolean mScalingRequired;
30005 
30006         /**
30007          * Left position of this view's window
30008          */
30009         int mWindowLeft;
30010 
30011         /**
30012          * Top position of this view's window
30013          */
30014         int mWindowTop;
30015 
30016         /**
30017          * Indicates whether views need to use 32-bit drawing caches
30018          */
30019         boolean mUse32BitDrawingCache;
30020 
30021         /**
30022          * For windows that are full-screen but using insets to layout inside
30023          * of the screen decorations, these are the current insets for the
30024          * content of the window.
30025          */
30026         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
30027                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
30028         final Rect mContentInsets = new Rect();
30029 
30030         /**
30031          * For windows that are full-screen but using insets to layout inside
30032          * of the screen decorations, these are the current insets for the
30033          * actual visible parts of the window.
30034          */
30035         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
30036                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
30037         final Rect mVisibleInsets = new Rect();
30038 
30039         /**
30040          * For windows that are full-screen but using insets to layout inside
30041          * of the screen decorations, these are the current insets for the
30042          * stable system windows.
30043          */
30044         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
30045                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
30046         final Rect mStableInsets = new Rect();
30047 
30048         /**
30049          * Current caption insets to the display coordinate.
30050          */
30051         final Rect mCaptionInsets = new Rect();
30052 
30053         /**
30054          * In multi-window we force show the system bars. Because we don't want that the surface
30055          * size changes in this mode, we instead have a flag whether the system bars sizes should
30056          * always be consumed, so the app is treated like there are no virtual system bars at all.
30057          */
30058         boolean mAlwaysConsumeSystemBars;
30059 
30060         /**
30061          * The internal insets given by this window.  This value is
30062          * supplied by the client (through
30063          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
30064          * be given to the window manager when changed to be used in laying
30065          * out windows behind it.
30066          */
30067         @UnsupportedAppUsage
30068         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
30069                 = new ViewTreeObserver.InternalInsetsInfo();
30070 
30071         /**
30072          * Set to true when mGivenInternalInsets is non-empty.
30073          */
30074         boolean mHasNonEmptyGivenInternalInsets;
30075 
30076         /**
30077          * All views in the window's hierarchy that serve as scroll containers,
30078          * used to determine if the window can be resized or must be panned
30079          * to adjust for a soft input area.
30080          */
30081         @UnsupportedAppUsage
30082         final ArrayList<View> mScrollContainers = new ArrayList<View>();
30083 
30084         @UnsupportedAppUsage
30085         final KeyEvent.DispatcherState mKeyDispatchState
30086                 = new KeyEvent.DispatcherState();
30087 
30088         /**
30089          * Indicates whether the view's window currently has the focus.
30090          */
30091         @UnsupportedAppUsage
30092         boolean mHasWindowFocus;
30093 
30094         /**
30095          * The current visibility of the window.
30096          */
30097         int mWindowVisibility;
30098 
30099         /**
30100          * Indicates the time at which drawing started to occur.
30101          */
30102         @UnsupportedAppUsage
30103         long mDrawingTime;
30104 
30105         /**
30106          * Indicates whether the view's window is currently in touch mode.
30107          */
30108         @UnsupportedAppUsage
30109         boolean mInTouchMode;
30110 
30111         /**
30112          * Indicates whether the view has requested unbuffered input dispatching for the current
30113          * event stream.
30114          */
30115         boolean mUnbufferedDispatchRequested;
30116 
30117         /**
30118          * Indicates that ViewAncestor should trigger a global layout change
30119          * the next time it performs a traversal
30120          */
30121         @UnsupportedAppUsage
30122         boolean mRecomputeGlobalAttributes;
30123 
30124         /**
30125          * Always report new attributes at next traversal.
30126          */
30127         boolean mForceReportNewAttributes;
30128 
30129         /**
30130          * Set during a traveral if any views want to keep the screen on.
30131          */
30132         @UnsupportedAppUsage
30133         boolean mKeepScreenOn;
30134 
30135         /**
30136          * Set during a traveral if the light center needs to be updated.
30137          */
30138         boolean mNeedsUpdateLightCenter;
30139 
30140         /**
30141          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
30142          */
30143         int mSystemUiVisibility;
30144 
30145         /**
30146          * Hack to force certain system UI visibility flags to be cleared.
30147          */
30148         int mDisabledSystemUiVisibility;
30149 
30150         /**
30151          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
30152          * attached.
30153          */
30154         boolean mHasSystemUiListeners;
30155 
30156         /**
30157          * Set if the visibility of any views has changed.
30158          */
30159         @UnsupportedAppUsage
30160         boolean mViewVisibilityChanged;
30161 
30162         /**
30163          * Set to true if a view has been scrolled.
30164          */
30165         @UnsupportedAppUsage
30166         boolean mViewScrollChanged;
30167 
30168         /**
30169          * Set to true if a pointer event is currently being handled.
30170          */
30171         boolean mHandlingPointerEvent;
30172 
30173         /**
30174          * The window matrix of this view when it's on a {@link SurfaceControlViewHost} that is
30175          * embedded within a SurfaceView.
30176          */
30177         Matrix mWindowMatrixInEmbeddedHierarchy;
30178 
30179         /**
30180          * Global to the view hierarchy used as a temporary for dealing with
30181          * x/y points in the transparent region computations.
30182          */
30183         final int[] mTransparentLocation = new int[2];
30184 
30185         /**
30186          * Global to the view hierarchy used as a temporary for dealing with
30187          * x/y points in the ViewGroup.invalidateChild implementation.
30188          */
30189         final int[] mInvalidateChildLocation = new int[2];
30190 
30191         /**
30192          * Global to the view hierarchy used as a temporary for dealing with
30193          * computing absolute on-screen location.
30194          */
30195         final int[] mTmpLocation = new int[2];
30196 
30197         /**
30198          * Global to the view hierarchy used as a temporary for dealing with
30199          * x/y location when view is transformed.
30200          */
30201         final float[] mTmpTransformLocation = new float[2];
30202 
30203         /**
30204          * The view tree observer used to dispatch global events like
30205          * layout, pre-draw, touch mode change, etc.
30206          */
30207         @UnsupportedAppUsage
30208         final ViewTreeObserver mTreeObserver;
30209 
30210         /**
30211          * A Canvas used by the view hierarchy to perform bitmap caching.
30212          */
30213         Canvas mCanvas;
30214 
30215         /**
30216          * The view root impl.
30217          */
30218         final ViewRootImpl mViewRootImpl;
30219 
30220         /**
30221          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
30222          * handler can be used to pump events in the UI events queue.
30223          */
30224         @UnsupportedAppUsage
30225         final Handler mHandler;
30226 
30227         /**
30228          * Temporary for use in computing invalidate rectangles while
30229          * calling up the hierarchy.
30230          */
30231         final Rect mTmpInvalRect = new Rect();
30232 
30233         /**
30234          * Temporary for use in computing hit areas with transformed views
30235          */
30236         final RectF mTmpTransformRect = new RectF();
30237 
30238         /**
30239          * Temporary for use in computing hit areas with transformed views
30240          */
30241         final RectF mTmpTransformRect1 = new RectF();
30242 
30243         /**
30244          * Temporary list of rectanges.
30245          */
30246         final List<RectF> mTmpRectList = new ArrayList<>();
30247 
30248         /**
30249          * Temporary for use in transforming invalidation rect
30250          */
30251         final Matrix mTmpMatrix = new Matrix();
30252 
30253         /**
30254          * Temporary for use in transforming invalidation rect
30255          */
30256         final Transformation mTmpTransformation = new Transformation();
30257 
30258         /**
30259          * Temporary for use in querying outlines from OutlineProviders
30260          */
30261         final Outline mTmpOutline = new Outline();
30262 
30263         /**
30264          * Temporary list for use in collecting focusable descendents of a view.
30265          */
30266         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
30267 
30268         /**
30269          * The id of the window for accessibility purposes.
30270          */
30271         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
30272 
30273         /**
30274          * Flags related to accessibility processing.
30275          *
30276          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
30277          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
30278          */
30279         int mAccessibilityFetchFlags;
30280 
30281         /**
30282          * The drawable for highlighting accessibility focus.
30283          */
30284         Drawable mAccessibilityFocusDrawable;
30285 
30286         /**
30287          * The drawable for highlighting autofilled views.
30288          *
30289          * @see #isAutofilled()
30290          */
30291         Drawable mAutofilledDrawable;
30292 
30293         /**
30294          * Show where the margins, bounds and layout bounds are for each view.
30295          */
30296         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
30297 
30298         /**
30299          * Point used to compute visible regions.
30300          */
30301         final Point mPoint = new Point();
30302 
30303         /**
30304          * Used to track which View originated a requestLayout() call, used when
30305          * requestLayout() is called during layout.
30306          */
30307         View mViewRequestingLayout;
30308 
30309         /**
30310          * Used to track the identity of the current drag operation.
30311          */
30312         IBinder mDragToken;
30313 
30314         /**
30315          * The drag shadow surface for the current drag operation.
30316          */
30317         public Surface mDragSurface;
30318 
30319 
30320         /**
30321          * The view that currently has a tooltip displayed.
30322          */
30323         View mTooltipHost;
30324 
30325         /**
30326          * The initial structure has been reported so the view is ready to report updates.
30327          */
30328         boolean mReadyForContentCaptureUpdates;
30329 
30330         /**
30331          * Map(keyed by session) of content capture events that need to be notified after the view
30332          * hierarchy is traversed: value is either the view itself for appearead events, or its
30333          * autofill id for disappeared.
30334          */
30335         SparseArray<ArrayList<Object>> mContentCaptureEvents;
30336 
30337         /**
30338          * Cached reference to the {@link ContentCaptureManager}.
30339          */
30340         ContentCaptureManager mContentCaptureManager;
30341 
30342         /**
30343          * Listener used to fit content on window level.
30344          */
30345         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
30346 
30347         /**
30348          * The leash token of this view's parent when it's in an embedded hierarchy that is
30349          * re-parented to another window.
30350          */
30351         IBinder mLeashedParentToken;
30352 
30353         /**
30354          * The accessibility view id of this view's parent when it's in an embedded
30355          * hierarchy that is re-parented to another window.
30356          */
30357         int mLeashedParentAccessibilityViewId;
30358 
30359         /**
30360          *
30361          */
30362         ScrollCaptureInternal mScrollCaptureInternal;
30363 
30364         /**
30365          * Creates a new set of attachment information with the specified
30366          * events handler and thread.
30367          *
30368          * @param handler the events handler the view must use
30369          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)30370         AttachInfo(IWindowSession session, IWindow window, Display display,
30371                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
30372                 Context context) {
30373             mSession = session;
30374             mWindow = window;
30375             mWindowToken = window.asBinder();
30376             mDisplay = display;
30377             mViewRootImpl = viewRootImpl;
30378             mHandler = handler;
30379             mRootCallbacks = effectPlayer;
30380             mTreeObserver = new ViewTreeObserver(context);
30381         }
30382 
30383         @Nullable
getContentCaptureManager(@onNull Context context)30384         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
30385             if (mContentCaptureManager != null) {
30386                 return mContentCaptureManager;
30387             }
30388             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
30389             return mContentCaptureManager;
30390         }
30391 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)30392         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
30393             if (mContentCaptureManager == null) {
30394                 return;
30395             }
30396 
30397             ArrayList<Object> events = ensureEvents(
30398                         mContentCaptureManager.getMainContentCaptureSession());
30399             events.add(insets);
30400         }
30401 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)30402         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
30403                 @NonNull View view, boolean appeared) {
30404             ArrayList<Object> events = ensureEvents(session);
30405             events.add(appeared ? view : view.getAutofillId());
30406         }
30407 
30408         @NonNull
ensureEvents(@onNull ContentCaptureSession session)30409         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
30410             if (mContentCaptureEvents == null) {
30411                 // Most of the time there will be just one session, so intial capacity is 1
30412                 mContentCaptureEvents = new SparseArray<>(1);
30413             }
30414             int sessionId = session.getId();
30415             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
30416             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
30417             if (events == null) {
30418                 events = new ArrayList<>();
30419                 mContentCaptureEvents.put(sessionId, events);
30420             }
30421 
30422             return events;
30423         }
30424 
30425         @Nullable
getScrollCaptureInternal()30426         ScrollCaptureInternal getScrollCaptureInternal() {
30427             if (mScrollCaptureInternal != null) {
30428                 mScrollCaptureInternal = new ScrollCaptureInternal();
30429             }
30430             return mScrollCaptureInternal;
30431         }
30432 
getRootSurfaceControl()30433         AttachedSurfaceControl getRootSurfaceControl() {
30434             return mViewRootImpl;
30435         }
30436 
dump(String prefix, PrintWriter writer)30437         public void dump(String prefix, PrintWriter writer) {
30438             String innerPrefix = prefix + "  ";
30439             writer.println(prefix + "AttachInfo:");
30440             writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
30441             writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
30442             writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
30443             writer.println(innerPrefix + "mUnbufferedDispatchRequested="
30444                     + mUnbufferedDispatchRequested);
30445         }
30446     }
30447 
30448     /**
30449      * <p>ScrollabilityCache holds various fields used by a View when scrolling
30450      * is supported. This avoids keeping too many unused fields in most
30451      * instances of View.</p>
30452      */
30453     private static class ScrollabilityCache implements Runnable {
30454 
30455         /**
30456          * Scrollbars are not visible
30457          */
30458         public static final int OFF = 0;
30459 
30460         /**
30461          * Scrollbars are visible
30462          */
30463         public static final int ON = 1;
30464 
30465         /**
30466          * Scrollbars are fading away
30467          */
30468         public static final int FADING = 2;
30469 
30470         public boolean fadeScrollBars;
30471 
30472         public int fadingEdgeLength;
30473         public int scrollBarDefaultDelayBeforeFade;
30474         public int scrollBarFadeDuration;
30475 
30476         public int scrollBarSize;
30477         public int scrollBarMinTouchTarget;
30478         @UnsupportedAppUsage
30479         public ScrollBarDrawable scrollBar;
30480         public float[] interpolatorValues;
30481         @UnsupportedAppUsage
30482         public View host;
30483 
30484         public final Paint paint;
30485         public final Matrix matrix;
30486         public Shader shader;
30487 
30488         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
30489 
30490         private static final float[] OPAQUE = { 255 };
30491         private static final float[] TRANSPARENT = { 0.0f };
30492 
30493         /**
30494          * When fading should start. This time moves into the future every time
30495          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
30496          */
30497         public long fadeStartTime;
30498 
30499 
30500         /**
30501          * The current state of the scrollbars: ON, OFF, or FADING
30502          */
30503         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
30504         public int state = OFF;
30505 
30506         private int mLastColor;
30507 
30508         public final Rect mScrollBarBounds = new Rect();
30509         public final Rect mScrollBarTouchBounds = new Rect();
30510 
30511         public static final int NOT_DRAGGING = 0;
30512         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
30513         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
30514         public int mScrollBarDraggingState = NOT_DRAGGING;
30515 
30516         public float mScrollBarDraggingPos = 0;
30517 
ScrollabilityCache(ViewConfiguration configuration, View host)30518         public ScrollabilityCache(ViewConfiguration configuration, View host) {
30519             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
30520             scrollBarSize = configuration.getScaledScrollBarSize();
30521             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
30522             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
30523             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
30524 
30525             paint = new Paint();
30526             matrix = new Matrix();
30527             // use use a height of 1, and then wack the matrix each time we
30528             // actually use it.
30529             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
30530             paint.setShader(shader);
30531             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
30532 
30533             this.host = host;
30534         }
30535 
setFadeColor(int color)30536         public void setFadeColor(int color) {
30537             if (color != mLastColor) {
30538                 mLastColor = color;
30539 
30540                 if (color != 0) {
30541                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
30542                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
30543                     paint.setShader(shader);
30544                     // Restore the default transfer mode (src_over)
30545                     paint.setXfermode(null);
30546                 } else {
30547                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
30548                     paint.setShader(shader);
30549                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
30550                 }
30551             }
30552         }
30553 
run()30554         public void run() {
30555             long now = AnimationUtils.currentAnimationTimeMillis();
30556             if (now >= fadeStartTime) {
30557 
30558                 // the animation fades the scrollbars out by changing
30559                 // the opacity (alpha) from fully opaque to fully
30560                 // transparent
30561                 int nextFrame = (int) now;
30562                 int framesCount = 0;
30563 
30564                 Interpolator interpolator = scrollBarInterpolator;
30565 
30566                 // Start opaque
30567                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
30568 
30569                 // End transparent
30570                 nextFrame += scrollBarFadeDuration;
30571                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
30572 
30573                 state = FADING;
30574 
30575                 // Kick off the fade animation
30576                 host.invalidate(true);
30577             }
30578         }
30579     }
30580 
30581     private class SendAccessibilityEventThrottle implements Runnable {
30582         public volatile boolean mIsPending;
30583         private AccessibilityEvent mAccessibilityEvent;
30584 
post(AccessibilityEvent accessibilityEvent)30585         public void post(AccessibilityEvent accessibilityEvent) {
30586             updateWithAccessibilityEvent(accessibilityEvent);
30587             if (!mIsPending) {
30588                 mIsPending = true;
30589                 postDelayed(this,
30590                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
30591             }
30592         }
30593 
30594         @Override
run()30595         public void run() {
30596             if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
30597                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
30598             }
30599             reset();
30600         }
30601 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)30602         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
30603             mAccessibilityEvent = accessibilityEvent;
30604         }
30605 
reset()30606         public void reset() {
30607             mIsPending = false;
30608             mAccessibilityEvent = null;
30609         }
30610 
30611     }
30612 
30613     /**
30614      * Resuable callback for sending
30615      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
30616      */
30617     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
30618         public int mDeltaX;
30619         public int mDeltaY;
30620 
30621         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)30622         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
30623             super.updateWithAccessibilityEvent(accessibilityEvent);
30624             mDeltaX += accessibilityEvent.getScrollDeltaX();
30625             mDeltaY += accessibilityEvent.getScrollDeltaY();
30626             accessibilityEvent.setScrollDeltaX(mDeltaX);
30627             accessibilityEvent.setScrollDeltaY(mDeltaY);
30628         }
30629 
30630         @Override
reset()30631         public void reset() {
30632             super.reset();
30633             mDeltaX = 0;
30634             mDeltaY = 0;
30635         }
30636     }
30637     /**
30638      * Remove the pending callback for sending a throttled accessibility event.
30639      */
30640     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)30641     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
30642         if (callback == null || !callback.mIsPending) return;
30643         removeCallbacks(callback);
30644         callback.reset();
30645     }
30646 
30647     /**
30648      * <p>
30649      * This class represents a delegate that can be registered in a {@link View}
30650      * to enhance accessibility support via composition rather via inheritance.
30651      * It is specifically targeted to widget developers that extend basic View
30652      * classes i.e. classes in package android.view, that would like their
30653      * applications to be backwards compatible.
30654      * </p>
30655      * <div class="special reference">
30656      * <h3>Developer Guides</h3>
30657      * <p>For more information about making applications accessible, read the
30658      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
30659      * developer guide.</p>
30660      * </div>
30661      * <p>
30662      * A scenario in which a developer would like to use an accessibility delegate
30663      * is overriding a method introduced in a later API version than the minimal API
30664      * version supported by the application. For example, the method
30665      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
30666      * in API version 4 when the accessibility APIs were first introduced. If a
30667      * developer would like their application to run on API version 4 devices (assuming
30668      * all other APIs used by the application are version 4 or lower) and take advantage
30669      * of this method, instead of overriding the method which would break the application's
30670      * backwards compatibility, they can override the corresponding method in this
30671      * delegate and register the delegate in the target View if the API version of
30672      * the system is high enough, i.e. the API version is the same as or higher than the API
30673      * version that introduced
30674      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
30675      * </p>
30676      * <p>
30677      * Here is an example implementation:
30678      * </p>
30679      * <code><pre><p>
30680      * if (Build.VERSION.SDK_INT >= 14) {
30681      *     // If the API version is equal of higher than the version in
30682      *     // which onInitializeAccessibilityNodeInfo was introduced we
30683      *     // register a delegate with a customized implementation.
30684      *     View view = findViewById(R.id.view_id);
30685      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
30686      *         public void onInitializeAccessibilityNodeInfo(View host,
30687      *                 AccessibilityNodeInfo info) {
30688      *             // Let the default implementation populate the info.
30689      *             super.onInitializeAccessibilityNodeInfo(host, info);
30690      *             // Set some other information.
30691      *             info.setEnabled(host.isEnabled());
30692      *         }
30693      *     });
30694      * }
30695      * </code></pre></p>
30696      * <p>
30697      * This delegate contains methods that correspond to the accessibility methods
30698      * in View. If a delegate has been specified the implementation in View hands
30699      * off handling to the corresponding method in this delegate. The default
30700      * implementation the delegate methods behaves exactly as the corresponding
30701      * method in View for the case of no accessibility delegate been set. Hence,
30702      * to customize the behavior of a View method, clients can override only the
30703      * corresponding delegate method without altering the behavior of the rest
30704      * accessibility related methods of the host view.
30705      * </p>
30706      * <p>
30707      * <strong>Note:</strong> On platform versions prior to
30708      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
30709      * views in the {@code android.widget.*} package are called <i>before</i>
30710      * host methods. This prevents certain properties such as class name from
30711      * being modified by overriding
30712      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
30713      * as any changes will be overwritten by the host class.
30714      * <p>
30715      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
30716      * methods are called <i>after</i> host methods, which all properties to be
30717      * modified without being overwritten by the host class.
30718      */
30719     public static class AccessibilityDelegate {
30720 
30721         /**
30722          * Sends an accessibility event of the given type. If accessibility is not
30723          * enabled this method has no effect.
30724          * <p>
30725          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
30726          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
30727          * been set.
30728          * </p>
30729          *
30730          * @param host The View hosting the delegate.
30731          * @param eventType The type of the event to send.
30732          *
30733          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
30734          */
sendAccessibilityEvent(@onNull View host, int eventType)30735         public void sendAccessibilityEvent(@NonNull View host, int eventType) {
30736             host.sendAccessibilityEventInternal(eventType);
30737         }
30738 
30739         /**
30740          * Performs the specified accessibility action on the view. For
30741          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
30742          * <p>
30743          * The default implementation behaves as
30744          * {@link View#performAccessibilityAction(int, Bundle)
30745          *  View#performAccessibilityAction(int, Bundle)} for the case of
30746          *  no accessibility delegate been set.
30747          * </p>
30748          *
30749          * @param action The action to perform.
30750          * @return Whether the action was performed.
30751          *
30752          * @see View#performAccessibilityAction(int, Bundle)
30753          *      View#performAccessibilityAction(int, Bundle)
30754          */
performAccessibilityAction(@onNull View host, int action, @Nullable Bundle args)30755         public boolean performAccessibilityAction(@NonNull View host, int action,
30756                 @Nullable Bundle args) {
30757             return host.performAccessibilityActionInternal(action, args);
30758         }
30759 
30760         /**
30761          * Sends an accessibility event. This method behaves exactly as
30762          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
30763          * empty {@link AccessibilityEvent} and does not perform a check whether
30764          * accessibility is enabled.
30765          * <p>
30766          * The default implementation behaves as
30767          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
30768          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
30769          * the case of no accessibility delegate been set.
30770          * </p>
30771          *
30772          * @param host The View hosting the delegate.
30773          * @param event The event to send.
30774          *
30775          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
30776          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
30777          */
sendAccessibilityEventUnchecked(@onNull View host, @NonNull AccessibilityEvent event)30778         public void sendAccessibilityEventUnchecked(@NonNull View host,
30779                 @NonNull AccessibilityEvent event) {
30780             host.sendAccessibilityEventUncheckedInternal(event);
30781         }
30782 
30783         /**
30784          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
30785          * to its children for adding their text content to the event.
30786          * <p>
30787          * The default implementation behaves as
30788          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30789          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
30790          * the case of no accessibility delegate been set.
30791          * </p>
30792          *
30793          * @param host The View hosting the delegate.
30794          * @param event The event.
30795          * @return True if the event population was completed.
30796          *
30797          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30798          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30799          */
dispatchPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)30800         public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
30801                 @NonNull AccessibilityEvent event) {
30802             return host.dispatchPopulateAccessibilityEventInternal(event);
30803         }
30804 
30805         /**
30806          * Gives a chance to the host View to populate the accessibility event with its
30807          * text content.
30808          * <p>
30809          * The default implementation behaves as
30810          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
30811          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
30812          * the case of no accessibility delegate been set.
30813          * </p>
30814          *
30815          * @param host The View hosting the delegate.
30816          * @param event The accessibility event which to populate.
30817          *
30818          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
30819          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
30820          */
onPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)30821         public void onPopulateAccessibilityEvent(@NonNull View host,
30822                 @NonNull AccessibilityEvent event) {
30823             host.onPopulateAccessibilityEventInternal(event);
30824         }
30825 
30826         /**
30827          * Initializes an {@link AccessibilityEvent} with information about the
30828          * the host View which is the event source.
30829          * <p>
30830          * The default implementation behaves as
30831          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
30832          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
30833          * the case of no accessibility delegate been set.
30834          * </p>
30835          *
30836          * @param host The View hosting the delegate.
30837          * @param event The event to initialize.
30838          *
30839          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
30840          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
30841          */
onInitializeAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)30842         public void onInitializeAccessibilityEvent(@NonNull View host,
30843                 @NonNull AccessibilityEvent event) {
30844             host.onInitializeAccessibilityEventInternal(event);
30845         }
30846 
30847         /**
30848          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
30849          * <p>
30850          * The default implementation behaves as
30851          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30852          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
30853          * the case of no accessibility delegate been set.
30854          * </p>
30855          *
30856          * @param host The View hosting the delegate.
30857          * @param info The instance to initialize.
30858          *
30859          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30860          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30861          */
onInitializeAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info)30862         public void onInitializeAccessibilityNodeInfo(@NonNull View host,
30863                 @NonNull AccessibilityNodeInfo info) {
30864             host.onInitializeAccessibilityNodeInfoInternal(info);
30865         }
30866 
30867         /**
30868          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
30869          * additional data.
30870          * <p>
30871          * This method only needs to be implemented if the View offers to provide additional data.
30872          * </p>
30873          * <p>
30874          * The default implementation behaves as
30875          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
30876          * for the case where no accessibility delegate is set.
30877          * </p>
30878          *
30879          * @param host The View hosting the delegate. Never {@code null}.
30880          * @param info The info to which to add the extra data. Never {@code null}.
30881          * @param extraDataKey A key specifying the type of extra data to add to the info. The
30882          *                     extra data should be added to the {@link Bundle} returned by
30883          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
30884          *                     {@code null}.
30885          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
30886          *                  May be {@code null} if the if the service provided no arguments.
30887          *
30888          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
30889          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)30890         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
30891                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
30892                 @Nullable Bundle arguments) {
30893             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
30894         }
30895 
30896         /**
30897          * Called when a child of the host View has requested sending an
30898          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
30899          * to augment the event.
30900          * <p>
30901          * The default implementation behaves as
30902          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30903          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
30904          * the case of no accessibility delegate been set.
30905          * </p>
30906          *
30907          * @param host The View hosting the delegate.
30908          * @param child The child which requests sending the event.
30909          * @param event The event to be sent.
30910          * @return True if the event should be sent
30911          *
30912          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30913          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30914          */
onRequestSendAccessibilityEvent(@onNull ViewGroup host, @NonNull View child, @NonNull AccessibilityEvent event)30915         public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
30916                 @NonNull AccessibilityEvent event) {
30917             return host.onRequestSendAccessibilityEventInternal(child, event);
30918         }
30919 
30920         /**
30921          * Gets the provider for managing a virtual view hierarchy rooted at this View
30922          * and reported to {@link android.accessibilityservice.AccessibilityService}s
30923          * that explore the window content.
30924          * <p>
30925          * The default implementation behaves as
30926          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
30927          * the case of no accessibility delegate been set.
30928          * </p>
30929          *
30930          * @return The provider.
30931          *
30932          * @see AccessibilityNodeProvider
30933          */
getAccessibilityNodeProvider( @onNull View host)30934         public @Nullable AccessibilityNodeProvider getAccessibilityNodeProvider(
30935                 @NonNull View host) {
30936             return null;
30937         }
30938 
30939         /**
30940          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
30941          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
30942          * This method is responsible for obtaining an accessibility node info from a
30943          * pool of reusable instances and calling
30944          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
30945          * view to initialize the former.
30946          * <p>
30947          * <strong>Note:</strong> The client is responsible for recycling the obtained
30948          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
30949          * creation.
30950          * </p>
30951          * <p>
30952          * The default implementation behaves as
30953          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
30954          * the case of no accessibility delegate been set.
30955          * </p>
30956          * @return A populated {@link AccessibilityNodeInfo}.
30957          *
30958          * @see AccessibilityNodeInfo
30959          *
30960          * @hide
30961          */
30962         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
createAccessibilityNodeInfo(@onNull View host)30963         public AccessibilityNodeInfo createAccessibilityNodeInfo(@NonNull View host) {
30964             return host.createAccessibilityNodeInfoInternal();
30965         }
30966     }
30967 
30968     private static class MatchIdPredicate implements Predicate<View> {
30969         public int mId;
30970 
30971         @Override
test(View view)30972         public boolean test(View view) {
30973             return (view.mID == mId);
30974         }
30975     }
30976 
30977     private static class MatchLabelForPredicate implements Predicate<View> {
30978         private int mLabeledId;
30979 
30980         @Override
test(View view)30981         public boolean test(View view) {
30982             return (view.mLabelForId == mLabeledId);
30983         }
30984     }
30985 
30986 
30987     /**
30988      * Returns the current scroll capture hint for this view.
30989      *
30990      * @return the current scroll capture hint
30991      */
30992     @ScrollCaptureHint
getScrollCaptureHint()30993     public int getScrollCaptureHint() {
30994         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
30995                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
30996     }
30997 
30998     /**
30999      * Sets the scroll capture hint for this View. These flags affect the search for a potential
31000      * scroll capture targets.
31001      *
31002      * @param hint the scrollCaptureHint flags value to set
31003      */
setScrollCaptureHint(@crollCaptureHint int hint)31004     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
31005         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
31006         // Since include/exclude are mutually exclusive, exclude takes precedence.
31007         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
31008             hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
31009         }
31010         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
31011                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
31012     }
31013 
31014     /**
31015      * Sets the callback to receive scroll capture requests. This component is the adapter between
31016      * the scroll capture API and application UI code. If no callback is set, the system may provide
31017      * an implementation. Any value provided here will take precedence over a system version.
31018      * <p>
31019      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
31020      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
31021      * <p>
31022      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
31023      * setting a custom callback to help ensure it is selected as the target.
31024      *
31025      * @param callback the new callback to assign
31026      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)31027     public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
31028         getListenerInfo().mScrollCaptureCallback = callback;
31029     }
31030 
31031     /** {@hide} */
31032     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)31033     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
31034             @NonNull Point windowOffset) {
31035         if (mAttachInfo == null) {
31036             return null;
31037         }
31038         if (mAttachInfo.mScrollCaptureInternal == null) {
31039             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
31040         }
31041         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
31042                 windowOffset);
31043     }
31044 
31045     /**
31046      * Dispatch a scroll capture search request down the view hierarchy.
31047      *
31048      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
31049      *                         the parent
31050      * @param windowOffset     the offset of this view within the window
31051      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
31052      *                         results.accept} may be called zero or more times on the calling
31053      *                         thread before onScrollCaptureSearch returns
31054      */
dispatchScrollCaptureSearch( @onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)31055     public void dispatchScrollCaptureSearch(
31056             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
31057             @NonNull Consumer<ScrollCaptureTarget> targets) {
31058         onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
31059     }
31060 
31061     /**
31062      * Called when scroll capture is requested, to search for appropriate content to scroll. If
31063      * applicable, this view adds itself to the provided list for consideration, subject to the
31064      * flags set by {@link #setScrollCaptureHint}.
31065      *
31066      * @param localVisibleRect the local visible rect of this view
31067      * @param windowOffset     the offset of localVisibleRect within the window
31068      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
31069      *                         results.accept} may be called zero or more times on the calling
31070      *                         thread before onScrollCaptureSearch returns
31071      * @throws IllegalStateException if this view is not attached to a window
31072      */
onScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)31073     public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
31074             @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
31075         int hint = getScrollCaptureHint();
31076         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
31077             return;
31078         }
31079         boolean rectIsVisible = true;
31080 
31081         // Apply clipBounds if present.
31082         if (mClipBounds != null) {
31083             rectIsVisible = localVisibleRect.intersect(mClipBounds);
31084         }
31085         if (!rectIsVisible) {
31086             return;
31087         }
31088 
31089         // Get a callback provided by the framework, library or application.
31090         ScrollCaptureCallback callback =
31091                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
31092 
31093         // Try framework support for standard scrolling containers.
31094         if (callback == null) {
31095             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
31096         }
31097 
31098         // If found, then add it to the list.
31099         if (callback != null) {
31100             // Add to the list for consideration
31101             Point offset = new Point(windowOffset.x, windowOffset.y);
31102             Rect rect = new Rect(localVisibleRect);
31103             targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
31104         }
31105     }
31106 
31107     /**
31108      * Dump all private flags in readable format, useful for documentation and
31109      * consistency checking.
31110      */
dumpFlags()31111     private static void dumpFlags() {
31112         final HashMap<String, String> found = Maps.newHashMap();
31113         try {
31114             for (Field field : View.class.getDeclaredFields()) {
31115                 final int modifiers = field.getModifiers();
31116                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
31117                     if (field.getType().equals(int.class)) {
31118                         final int value = field.getInt(null);
31119                         dumpFlag(found, field.getName(), value);
31120                     } else if (field.getType().equals(int[].class)) {
31121                         final int[] values = (int[]) field.get(null);
31122                         for (int i = 0; i < values.length; i++) {
31123                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
31124                         }
31125                     }
31126                 }
31127             }
31128         } catch (IllegalAccessException e) {
31129             throw new RuntimeException(e);
31130         }
31131 
31132         final ArrayList<String> keys = Lists.newArrayList();
31133         keys.addAll(found.keySet());
31134         Collections.sort(keys);
31135         for (String key : keys) {
31136             Log.d(VIEW_LOG_TAG, found.get(key));
31137         }
31138     }
31139 
dumpFlag(HashMap<String, String> found, String name, int value)31140     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
31141         // Sort flags by prefix, then by bits, always keeping unique keys
31142         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
31143         final int prefix = name.indexOf('_');
31144         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
31145         final String output = bits + " " + name;
31146         found.put(key, output);
31147     }
31148 
31149     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)31150     public void encode(@NonNull ViewHierarchyEncoder stream) {
31151         stream.beginObject(this);
31152         encodeProperties(stream);
31153         stream.endObject();
31154     }
31155 
31156     /** {@hide} */
31157     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)31158     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
31159         Object resolveId = ViewDebug.resolveId(getContext(), mID);
31160         if (resolveId instanceof String) {
31161             stream.addProperty("id", (String) resolveId);
31162         } else {
31163             stream.addProperty("id", mID);
31164         }
31165 
31166         stream.addProperty("misc:transformation.alpha",
31167                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
31168         stream.addProperty("misc:transitionName", getTransitionName());
31169 
31170         // layout
31171         stream.addProperty("layout:left", mLeft);
31172         stream.addProperty("layout:right", mRight);
31173         stream.addProperty("layout:top", mTop);
31174         stream.addProperty("layout:bottom", mBottom);
31175         stream.addProperty("layout:width", getWidth());
31176         stream.addProperty("layout:height", getHeight());
31177         stream.addProperty("layout:layoutDirection", getLayoutDirection());
31178         stream.addProperty("layout:layoutRtl", isLayoutRtl());
31179         stream.addProperty("layout:hasTransientState", hasTransientState());
31180         stream.addProperty("layout:baseline", getBaseline());
31181 
31182         // layout params
31183         ViewGroup.LayoutParams layoutParams = getLayoutParams();
31184         if (layoutParams != null) {
31185             stream.addPropertyKey("layoutParams");
31186             layoutParams.encode(stream);
31187         }
31188 
31189         // scrolling
31190         stream.addProperty("scrolling:scrollX", mScrollX);
31191         stream.addProperty("scrolling:scrollY", mScrollY);
31192 
31193         // padding
31194         stream.addProperty("padding:paddingLeft", mPaddingLeft);
31195         stream.addProperty("padding:paddingRight", mPaddingRight);
31196         stream.addProperty("padding:paddingTop", mPaddingTop);
31197         stream.addProperty("padding:paddingBottom", mPaddingBottom);
31198         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
31199         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
31200         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
31201         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
31202         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
31203 
31204         // measurement
31205         stream.addProperty("measurement:minHeight", mMinHeight);
31206         stream.addProperty("measurement:minWidth", mMinWidth);
31207         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
31208         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
31209 
31210         // drawing
31211         stream.addProperty("drawing:elevation", getElevation());
31212         stream.addProperty("drawing:translationX", getTranslationX());
31213         stream.addProperty("drawing:translationY", getTranslationY());
31214         stream.addProperty("drawing:translationZ", getTranslationZ());
31215         stream.addProperty("drawing:rotation", getRotation());
31216         stream.addProperty("drawing:rotationX", getRotationX());
31217         stream.addProperty("drawing:rotationY", getRotationY());
31218         stream.addProperty("drawing:scaleX", getScaleX());
31219         stream.addProperty("drawing:scaleY", getScaleY());
31220         stream.addProperty("drawing:pivotX", getPivotX());
31221         stream.addProperty("drawing:pivotY", getPivotY());
31222         stream.addProperty("drawing:clipBounds",
31223                 mClipBounds == null ? null : mClipBounds.toString());
31224         stream.addProperty("drawing:opaque", isOpaque());
31225         stream.addProperty("drawing:alpha", getAlpha());
31226         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
31227         stream.addProperty("drawing:shadow", hasShadow());
31228         stream.addProperty("drawing:solidColor", getSolidColor());
31229         stream.addProperty("drawing:layerType", mLayerType);
31230         stream.addProperty("drawing:willNotDraw", willNotDraw());
31231         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
31232         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
31233         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
31234         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
31235         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
31236         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
31237 
31238         // focus
31239         stream.addProperty("focus:hasFocus", hasFocus());
31240         stream.addProperty("focus:isFocused", isFocused());
31241         stream.addProperty("focus:focusable", getFocusable());
31242         stream.addProperty("focus:isFocusable", isFocusable());
31243         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
31244 
31245         stream.addProperty("misc:clickable", isClickable());
31246         stream.addProperty("misc:pressed", isPressed());
31247         stream.addProperty("misc:selected", isSelected());
31248         stream.addProperty("misc:touchMode", isInTouchMode());
31249         stream.addProperty("misc:hovered", isHovered());
31250         stream.addProperty("misc:activated", isActivated());
31251 
31252         stream.addProperty("misc:visibility", getVisibility());
31253         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
31254         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
31255 
31256         stream.addProperty("misc:enabled", isEnabled());
31257         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
31258         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
31259 
31260         // theme attributes
31261         Resources.Theme theme = getContext().getTheme();
31262         if (theme != null) {
31263             stream.addPropertyKey("theme");
31264             theme.encode(stream);
31265         }
31266 
31267         // view attribute information
31268         int n = mAttributes != null ? mAttributes.length : 0;
31269         stream.addProperty("meta:__attrCount__", n/2);
31270         for (int i = 0; i < n; i += 2) {
31271             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
31272         }
31273 
31274         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
31275 
31276         // text
31277         stream.addProperty("text:textDirection", getTextDirection());
31278         stream.addProperty("text:textAlignment", getTextAlignment());
31279 
31280         // accessibility
31281         CharSequence contentDescription = getContentDescription();
31282         stream.addUserProperty("accessibility:contentDescription",
31283                 contentDescription == null ? "" : contentDescription.toString());
31284         stream.addProperty("accessibility:labelFor", getLabelFor());
31285         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
31286     }
31287 
31288     /**
31289      * Determine if this view is rendered on a round wearable device and is the main view
31290      * on the screen.
31291      */
shouldDrawRoundScrollbar()31292     boolean shouldDrawRoundScrollbar() {
31293         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
31294             return false;
31295         }
31296 
31297         final View rootView = getRootView();
31298         final WindowInsets insets = getRootWindowInsets();
31299 
31300         int height = getHeight();
31301         int width = getWidth();
31302         int displayHeight = rootView.getHeight();
31303         int displayWidth = rootView.getWidth();
31304 
31305         if (height != displayHeight || width != displayWidth) {
31306             return false;
31307         }
31308 
31309         getLocationInWindow(mAttachInfo.mTmpLocation);
31310         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
31311                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
31312     }
31313 
31314     /**
31315      * Sets the tooltip text which will be displayed in a small popup next to the view.
31316      * <p>
31317      * The tooltip will be displayed:
31318      * <ul>
31319      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
31320      * menu). </li>
31321      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
31322      * </ul>
31323      * <p>
31324      * <strong>Note:</strong> Do not override this method, as it will have no
31325      * effect on the text displayed in the tooltip.
31326      *
31327      * @param tooltipText the tooltip text, or null if no tooltip is required
31328      * @see #getTooltipText()
31329      * @attr ref android.R.styleable#View_tooltipText
31330      */
setTooltipText(@ullable CharSequence tooltipText)31331     public void setTooltipText(@Nullable CharSequence tooltipText) {
31332         if (TextUtils.isEmpty(tooltipText)) {
31333             setFlags(0, TOOLTIP);
31334             hideTooltip();
31335             mTooltipInfo = null;
31336         } else {
31337             setFlags(TOOLTIP, TOOLTIP);
31338             if (mTooltipInfo == null) {
31339                 mTooltipInfo = new TooltipInfo();
31340                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
31341                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
31342                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
31343                 mTooltipInfo.clearAnchorPos();
31344             }
31345             mTooltipInfo.mTooltipText = tooltipText;
31346         }
31347     }
31348 
31349     /**
31350      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
31351      */
31352     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)31353     public void setTooltip(@Nullable CharSequence tooltipText) {
31354         setTooltipText(tooltipText);
31355     }
31356 
31357     /**
31358      * Returns the view's tooltip text.
31359      *
31360      * <strong>Note:</strong> Do not override this method, as it will have no
31361      * effect on the text displayed in the tooltip. You must call
31362      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
31363      *
31364      * @return the tooltip text
31365      * @see #setTooltipText(CharSequence)
31366      * @attr ref android.R.styleable#View_tooltipText
31367      */
31368     @InspectableProperty
31369     @Nullable
getTooltipText()31370     public CharSequence getTooltipText() {
31371         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
31372     }
31373 
31374     /**
31375      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
31376      */
31377     @Nullable
getTooltip()31378     public CharSequence getTooltip() {
31379         return getTooltipText();
31380     }
31381 
showTooltip(int x, int y, boolean fromLongClick)31382     private boolean showTooltip(int x, int y, boolean fromLongClick) {
31383         if (mAttachInfo == null || mTooltipInfo == null) {
31384             return false;
31385         }
31386         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
31387             return false;
31388         }
31389         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
31390             return false;
31391         }
31392         hideTooltip();
31393         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
31394         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
31395         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
31396         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
31397         mAttachInfo.mTooltipHost = this;
31398         // The available accessibility actions have changed
31399         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
31400         return true;
31401     }
31402 
31403     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hideTooltip()31404     void hideTooltip() {
31405         if (mTooltipInfo == null) {
31406             return;
31407         }
31408         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
31409         if (mTooltipInfo.mTooltipPopup == null) {
31410             return;
31411         }
31412         mTooltipInfo.mTooltipPopup.hide();
31413         mTooltipInfo.mTooltipPopup = null;
31414         mTooltipInfo.mTooltipFromLongClick = false;
31415         mTooltipInfo.clearAnchorPos();
31416         if (mAttachInfo != null) {
31417             mAttachInfo.mTooltipHost = null;
31418         }
31419         // The available accessibility actions have changed
31420         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
31421     }
31422 
showLongClickTooltip(int x, int y)31423     private boolean showLongClickTooltip(int x, int y) {
31424         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
31425         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
31426         return showTooltip(x, y, true);
31427     }
31428 
showHoverTooltip()31429     private boolean showHoverTooltip() {
31430         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
31431     }
31432 
dispatchTooltipHoverEvent(MotionEvent event)31433     boolean dispatchTooltipHoverEvent(MotionEvent event) {
31434         if (mTooltipInfo == null) {
31435             return false;
31436         }
31437         switch(event.getAction()) {
31438             case MotionEvent.ACTION_HOVER_MOVE:
31439                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
31440                     break;
31441                 }
31442                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
31443                     if (mTooltipInfo.mTooltipPopup == null) {
31444                         // Schedule showing the tooltip after a timeout.
31445                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
31446                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
31447                                 ViewConfiguration.getHoverTooltipShowTimeout());
31448                     }
31449 
31450                     // Hide hover-triggered tooltip after a period of inactivity.
31451                     // Match the timeout used by NativeInputManager to hide the mouse pointer
31452                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
31453                     final int timeout;
31454                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
31455                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
31456                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
31457                     } else {
31458                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
31459                     }
31460                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
31461                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
31462                 }
31463                 return true;
31464 
31465             case MotionEvent.ACTION_HOVER_EXIT:
31466                 mTooltipInfo.clearAnchorPos();
31467                 if (!mTooltipInfo.mTooltipFromLongClick) {
31468                     hideTooltip();
31469                 }
31470                 break;
31471         }
31472         return false;
31473     }
31474 
handleTooltipKey(KeyEvent event)31475     void handleTooltipKey(KeyEvent event) {
31476         switch (event.getAction()) {
31477             case KeyEvent.ACTION_DOWN:
31478                 if (event.getRepeatCount() == 0) {
31479                     hideTooltip();
31480                 }
31481                 break;
31482 
31483             case KeyEvent.ACTION_UP:
31484                 handleTooltipUp();
31485                 break;
31486         }
31487     }
31488 
handleTooltipUp()31489     private void handleTooltipUp() {
31490         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
31491             return;
31492         }
31493         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
31494         postDelayed(mTooltipInfo.mHideTooltipRunnable,
31495                 ViewConfiguration.getLongPressTooltipHideTimeout());
31496     }
31497 
getFocusableAttribute(TypedArray attributes)31498     private int getFocusableAttribute(TypedArray attributes) {
31499         TypedValue val = new TypedValue();
31500         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
31501             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
31502                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
31503             } else {
31504                 return val.data;
31505             }
31506         } else {
31507             return FOCUSABLE_AUTO;
31508         }
31509     }
31510 
31511     /**
31512      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
31513      * is not showing.
31514      * @hide
31515      */
31516     @TestApi
getTooltipView()31517     public View getTooltipView() {
31518         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
31519             return null;
31520         }
31521         return mTooltipInfo.mTooltipPopup.getContentView();
31522     }
31523 
31524     /**
31525      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
31526      * @hide
31527      */
31528     @TestApi
isDefaultFocusHighlightEnabled()31529     public static boolean isDefaultFocusHighlightEnabled() {
31530         return sUseDefaultFocusHighlight;
31531     }
31532 
31533     /**
31534      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
31535      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
31536      * (visually on-top views first).
31537      *
31538      * @param evt the previously unhandled {@link KeyEvent}.
31539      * @return the {@link View} which consumed the event or {@code null} if not consumed.
31540      */
dispatchUnhandledKeyEvent(KeyEvent evt)31541     View dispatchUnhandledKeyEvent(KeyEvent evt) {
31542         if (onUnhandledKeyEvent(evt)) {
31543             return this;
31544         }
31545         return null;
31546     }
31547 
31548     /**
31549      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
31550      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
31551      * this will dispatch into all the listeners registered via
31552      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
31553      * order (most recently added will receive events first).
31554      *
31555      * @param event An unhandled event.
31556      * @return {@code true} if the event was handled, {@code false} otherwise.
31557      * @see #addOnUnhandledKeyEventListener
31558      */
onUnhandledKeyEvent(@onNull KeyEvent event)31559     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
31560         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
31561             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
31562                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
31563                     return true;
31564                 }
31565             }
31566         }
31567         return false;
31568     }
31569 
hasUnhandledKeyListener()31570     boolean hasUnhandledKeyListener() {
31571         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
31572                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
31573     }
31574 
31575     /**
31576      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
31577      * UI thread.
31578      *
31579      * @param listener a receiver of unhandled {@link KeyEvent}s.
31580      * @see #removeOnUnhandledKeyEventListener
31581      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)31582     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
31583         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
31584         if (listeners == null) {
31585             listeners = new ArrayList<>();
31586             getListenerInfo().mUnhandledKeyListeners = listeners;
31587         }
31588         listeners.add(listener);
31589         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
31590             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
31591         }
31592     }
31593 
31594     /**
31595      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
31596      * UI thread.
31597      *
31598      * @param listener a receiver of unhandled {@link KeyEvent}s.
31599      * @see #addOnUnhandledKeyEventListener
31600      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)31601     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
31602         if (mListenerInfo != null) {
31603             if (mListenerInfo.mUnhandledKeyListeners != null
31604                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
31605                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
31606                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
31607                     mListenerInfo.mUnhandledKeyListeners = null;
31608                     if (mParent instanceof ViewGroup) {
31609                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
31610                     }
31611                 }
31612             }
31613         }
31614     }
31615 
31616     /**
31617      * Set the view to be detached or not detached.
31618      *
31619      * @param detached Whether the view is detached.
31620      *
31621      * @hide
31622      */
setDetached(boolean detached)31623     protected void setDetached(boolean detached) {
31624         if (detached) {
31625             mPrivateFlags4 |= PFLAG4_DETACHED;
31626         } else {
31627             mPrivateFlags4 &= ~PFLAG4_DETACHED;
31628         }
31629     }
31630 
31631     /**
31632      * Set whether this view enables automatic handwriting initiation.
31633      *
31634      * For a view with an active {@link InputConnection}, if auto handwriting is enabled then
31635      * stylus movement within its view boundary will automatically trigger the handwriting mode.
31636      * Check {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} for
31637      * more details about handwriting mode.
31638      *
31639      * If the View wants to initiate handwriting mode by itself, it can set this field to
31640      * {@code false} and call
31641      * {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} when there
31642      * is stylus movement detected.
31643      *
31644      * @see #onCreateInputConnection(EditorInfo)
31645      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
31646      * @param enabled whether auto handwriting initiation is enabled for this view.
31647      * @attr ref android.R.styleable#View_autoHandwritingEnabled
31648      */
setAutoHandwritingEnabled(boolean enabled)31649     public void setAutoHandwritingEnabled(boolean enabled) {
31650         if (enabled) {
31651             mPrivateFlags4 |= PFLAG4_AUTO_HANDWRITING_ENABLED;
31652         } else {
31653             mPrivateFlags4 &= ~PFLAG4_AUTO_HANDWRITING_ENABLED;
31654         }
31655         updatePositionUpdateListener();
31656         postUpdate(this::updateHandwritingArea);
31657     }
31658 
31659     /**
31660      * Return whether the View allows automatic handwriting initiation. Returns true if automatic
31661      * handwriting initiation is enabled, and verse visa.
31662      * @see #setAutoHandwritingEnabled(boolean)
31663      */
isAutoHandwritingEnabled()31664     public boolean isAutoHandwritingEnabled() {
31665         return (mPrivateFlags4 & PFLAG4_AUTO_HANDWRITING_ENABLED)
31666                 == PFLAG4_AUTO_HANDWRITING_ENABLED;
31667     }
31668 
setTraversalTracingEnabled(boolean enabled)31669     private void setTraversalTracingEnabled(boolean enabled) {
31670         if (enabled) {
31671             if (mTracingStrings == null) {
31672                 mTracingStrings = new ViewTraversalTracingStrings(this);
31673             }
31674             mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
31675         } else {
31676             mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
31677         }
31678     }
31679 
isTraversalTracingEnabled()31680     private boolean isTraversalTracingEnabled() {
31681         return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
31682                 == PFLAG4_TRAVERSAL_TRACING_ENABLED;
31683     }
31684 
setRelayoutTracingEnabled(boolean enabled)31685     private void setRelayoutTracingEnabled(boolean enabled) {
31686         if (enabled) {
31687             if (mTracingStrings == null) {
31688                 mTracingStrings = new ViewTraversalTracingStrings(this);
31689             }
31690             mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
31691         } else {
31692             mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
31693         }
31694     }
31695 
isRelayoutTracingEnabled()31696     private boolean isRelayoutTracingEnabled() {
31697         return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
31698                 == PFLAG4_RELAYOUT_TRACING_ENABLED;
31699     }
31700 
31701     /**
31702      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
31703      * the view.
31704      *
31705      * <p>The default implementation does nothing.</p>
31706      *
31707      * @param supportedFormats the supported translation formats. For now, the only possible value
31708      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
31709      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to
31710      * collect the information to be translated in the view. The {@code requestsCollector} only
31711      * accepts one request; an IllegalStateException is thrown if more than one
31712      * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the
31713      * {@link ViewTranslationRequest}.
31714      */
onCreateViewTranslationRequest(@onNull @ataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)31715     public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
31716             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
31717     }
31718 
31719     /**
31720      * Collects {@link ViewTranslationRequest}s which represents the content to be translated
31721      * for the virtual views in the host view. This is called if this view returned a virtual
31722      * view structure from {@link #onProvideContentCaptureStructure} and the system determined that
31723      * those virtual views were relevant for translation.
31724      *
31725      * <p>The default implementation does nothing.</p>
31726      *
31727      * @param virtualIds the virtual view ids which represents the virtual views in the host
31728      * view.
31729      * @param supportedFormats the supported translation formats. For now, the only possible value
31730      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
31731      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
31732      * multiple times to collect the information to be translated in the host view. One
31733      * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
31734      * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
31735      * Consumer after the method returns.
31736      */
31737     @SuppressLint("NullableCollection")
onCreateVirtualViewTranslationRequests(@onNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)31738     public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
31739             @NonNull @DataFormat int[] supportedFormats,
31740             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
31741         // no-op
31742     }
31743 
31744     /**
31745      * Returns a {@link ViewTranslationCallback} that is used to display the translated information
31746      * or {@code null} if this View doesn't support translation.
31747      *
31748      * @hide
31749      */
31750     @Nullable
getViewTranslationCallback()31751     public ViewTranslationCallback getViewTranslationCallback() {
31752         return mViewTranslationCallback;
31753     }
31754 
31755     /**
31756      * Sets a {@link ViewTranslationCallback} that is used to display/hide the translated
31757      * information. Developers can provide the customized implementation for show/hide translated
31758      * information.
31759      *
31760      * @param callback a {@link ViewTranslationCallback} that is used to control how to display the
31761      * translated information
31762      */
setViewTranslationCallback(@onNull ViewTranslationCallback callback)31763     public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
31764         mViewTranslationCallback = callback;
31765     }
31766 
31767     /**
31768      * Clear the {@link ViewTranslationCallback} from this view.
31769      */
clearViewTranslationCallback()31770     public void clearViewTranslationCallback() {
31771         mViewTranslationCallback = null;
31772     }
31773 
31774     /**
31775      * Returns the {@link ViewTranslationResponse} associated with this view. The response will be
31776      * set when the translation is done then {@link #onViewTranslationResponse} is called. The
31777      * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the
31778      * translated information.
31779      *
31780      * @return a {@link ViewTranslationResponse} that contains the translated information associated
31781      * with this view or {@code null} if this View doesn't have the translation.
31782      */
31783     @Nullable
getViewTranslationResponse()31784     public ViewTranslationResponse getViewTranslationResponse() {
31785         return mViewTranslationResponse;
31786     }
31787 
31788     /**
31789      * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated
31790      * by the TranslationService. The {@link ViewTranslationResponse} should be saved here so that
31791      * the {@link ViewTranslationResponse} can be used to display the translation when the system
31792      * calls {@link ViewTranslationCallback#onShowTranslation}.
31793      *
31794      * <p> The default implementation will set the ViewTranslationResponse that can be get from
31795      * {@link View#getViewTranslationResponse}. </p>
31796      *
31797      * @param response a {@link ViewTranslationResponse} that contains the translated information
31798      * which can be shown in the view.
31799      */
onViewTranslationResponse(@onNull ViewTranslationResponse response)31800     public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
31801         mViewTranslationResponse = response;
31802     }
31803 
31804     /**
31805      * Clears the ViewTranslationResponse stored by the default implementation of {@link
31806      * #onViewTranslationResponse}.
31807      *
31808      * @hide
31809      */
clearViewTranslationResponse()31810     public void clearViewTranslationResponse() {
31811         mViewTranslationResponse = null;
31812     }
31813 
31814     /**
31815      * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
31816      * translated by the TranslationService.
31817      *
31818      * <p> The default implementation does nothing.</p>
31819      *
31820      * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
31821      * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information
31822      * which can be shown in the view. The key of SparseArray is the virtual child ids.
31823      */
onVirtualViewTranslationResponses( @onNull LongSparseArray<ViewTranslationResponse> response)31824     public void onVirtualViewTranslationResponses(
31825             @NonNull LongSparseArray<ViewTranslationResponse> response) {
31826         // no-op
31827     }
31828 
31829     /**
31830      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
31831      * the hierarchy when the app requests ui translation. Typically, this method should only be
31832      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
31833      * classes should override {@link View#onCreateViewTranslationRequest} for normal view or
31834      * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children.
31835      * When requested to start the ui translation, the system will call this method to traverse the
31836      * view hierarchy to collect {@link ViewTranslationRequest}s and create a
31837      * {@link android.view.translation.Translator} to translate the requests. All the
31838      * {@link ViewTranslationRequest}s must be added when the traversal is done.
31839      *
31840      * <p> The default implementation calls {@link View#onCreateViewTranslationRequest} for normal
31841      * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
31842      * children to build {@link ViewTranslationRequest} if the view should be translated.
31843      * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
31844      * recycling of views doesn't prevent the system from attaching the response to it. Therefore,
31845      * if overriding this method, you should set or reset the transient state. </p>
31846      *
31847      * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
31848      * {@code null} if the view doesn't have virtual child that should be translated. The virtual
31849      * child ids are the same virtual ids provided by ContentCapture.
31850      * @param supportedFormats the supported translation formats. For now, the only possible value
31851      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
31852      * @param capability a {@link TranslationCapability} that holds translation capability.
31853      * information, e.g. source spec, target spec.
31854      * @param requests fill in with {@link ViewTranslationRequest}s for translation purpose.
31855      */
dispatchCreateViewTranslationRequest(@onNull Map<AutofillId, long[]> viewIds, @NonNull @DataFormat int[] supportedFormats, @NonNull TranslationCapability capability, @NonNull List<ViewTranslationRequest> requests)31856     public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
31857             @NonNull @DataFormat int[] supportedFormats,
31858             @NonNull TranslationCapability capability,
31859             @NonNull List<ViewTranslationRequest> requests) {
31860         AutofillId autofillId = getAutofillId();
31861         if (viewIds.containsKey(autofillId)) {
31862             if (viewIds.get(autofillId) == null) {
31863                 // TODO: avoiding the allocation per view
31864                 onCreateViewTranslationRequest(supportedFormats,
31865                         new ViewTranslationRequestConsumer(requests));
31866             } else {
31867                 onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
31868                         request -> {
31869                             requests.add(request);
31870                         });
31871             }
31872         }
31873     }
31874 
31875     private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
31876         private final List<ViewTranslationRequest> mRequests;
31877         private boolean mCalled;
31878 
ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests)31879         ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
31880             mRequests = requests;
31881         }
31882 
31883         @Override
accept(ViewTranslationRequest request)31884         public void accept(ViewTranslationRequest request) {
31885             if (mCalled) {
31886                 throw new IllegalStateException("The translation Consumer is not reusable.");
31887             }
31888             mCalled = true;
31889             if (request != null && request.getKeys().size() > 0) {
31890                 mRequests.add(request);
31891                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
31892                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
31893                             + getAutofillId());
31894                 }
31895                 setHasTransientState(true);
31896                 setHasTranslationTransientState(true);
31897             }
31898         }
31899     }
31900 
31901     /**
31902      * Called to generate a {@link DisplayHash} for this view.
31903      *
31904      * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
31905      *                      the values returned from
31906      *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
31907      * @param bounds The bounds for the content within the View to generate the hash for. If
31908      *               bounds are null, the entire View's bounds will be used. If empty, it will
31909      *               invoke the callback
31910      *               {@link DisplayHashResultCallback#onDisplayHashError} with error
31911      *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
31912      * @param executor The executor that the callback should be invoked on.
31913      * @param callback The callback to handle the results of generating the display hash
31914      */
generateDisplayHash(@onNull String hashAlgorithm, @Nullable Rect bounds, @NonNull Executor executor, @NonNull DisplayHashResultCallback callback)31915     public void generateDisplayHash(@NonNull String hashAlgorithm,
31916             @Nullable Rect bounds, @NonNull Executor executor,
31917             @NonNull DisplayHashResultCallback callback) {
31918         IWindowSession session = getWindowSession();
31919         if (session == null) {
31920             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
31921             return;
31922         }
31923         IWindow window = getWindow();
31924         if (window == null) {
31925             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
31926             return;
31927         }
31928 
31929         Rect visibleBounds = new Rect();
31930         getGlobalVisibleRect(visibleBounds);
31931 
31932         if (bounds != null && bounds.isEmpty()) {
31933             callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
31934             return;
31935         }
31936 
31937         if (bounds != null) {
31938             bounds.offset(visibleBounds.left, visibleBounds.top);
31939             visibleBounds.intersectUnchecked(bounds);
31940         }
31941 
31942         if (visibleBounds.isEmpty()) {
31943             callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
31944             return;
31945         }
31946 
31947         RemoteCallback remoteCallback = new RemoteCallback(result ->
31948                 executor.execute(() -> {
31949                     DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH);
31950                     int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
31951                             DISPLAY_HASH_ERROR_UNKNOWN);
31952                     if (displayHash != null) {
31953                         callback.onDisplayHashResult(displayHash);
31954                     } else {
31955                         callback.onDisplayHashError(errorCode);
31956                     }
31957                 }));
31958 
31959         try {
31960             session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
31961         } catch (RemoteException e) {
31962             Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
31963             callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
31964         }
31965     }
31966 
31967     /**
31968      * The AttachedSurfaceControl itself is not a View, it is just the interface to the
31969      * windowing-system object that contains the entire view hierarchy.
31970      * For the root View of a given hierarchy see {@link #getRootView}.
31971 
31972      * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
31973      * This will only return a non-null value when called between {@link #onAttachedToWindow}
31974      * and {@link #onDetachedFromWindow}.
31975      */
getRootSurfaceControl()31976     public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
31977         if (mAttachInfo != null) {
31978           return mAttachInfo.getRootSurfaceControl();
31979         }
31980         return null;
31981     }
31982 }
31983