1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static android.content.res.Resources.ID_NULL;
20 import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
21 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
22 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
23 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
24 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
25 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
26 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH;
27 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
28 
29 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
30 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
31 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
32 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
33 
34 import static java.lang.Math.max;
35 
36 import android.animation.AnimatorInflater;
37 import android.animation.StateListAnimator;
38 import android.annotation.AttrRes;
39 import android.annotation.CallSuper;
40 import android.annotation.ColorInt;
41 import android.annotation.DrawableRes;
42 import android.annotation.FloatRange;
43 import android.annotation.IdRes;
44 import android.annotation.IntDef;
45 import android.annotation.IntRange;
46 import android.annotation.LayoutRes;
47 import android.annotation.NonNull;
48 import android.annotation.Nullable;
49 import android.annotation.Size;
50 import android.annotation.StyleRes;
51 import android.annotation.SuppressLint;
52 import android.annotation.TestApi;
53 import android.annotation.UiContext;
54 import android.annotation.UiThread;
55 import android.compat.annotation.UnsupportedAppUsage;
56 import android.content.AutofillOptions;
57 import android.content.ClipData;
58 import android.content.ClipDescription;
59 import android.content.Context;
60 import android.content.ContextWrapper;
61 import android.content.Intent;
62 import android.content.res.ColorStateList;
63 import android.content.res.Configuration;
64 import android.content.res.Resources;
65 import android.content.res.TypedArray;
66 import android.graphics.Bitmap;
67 import android.graphics.BlendMode;
68 import android.graphics.Canvas;
69 import android.graphics.Color;
70 import android.graphics.Insets;
71 import android.graphics.Interpolator;
72 import android.graphics.LinearGradient;
73 import android.graphics.Matrix;
74 import android.graphics.Outline;
75 import android.graphics.Paint;
76 import android.graphics.PixelFormat;
77 import android.graphics.Point;
78 import android.graphics.PorterDuff;
79 import android.graphics.PorterDuffXfermode;
80 import android.graphics.RecordingCanvas;
81 import android.graphics.Rect;
82 import android.graphics.RectF;
83 import android.graphics.Region;
84 import android.graphics.RenderEffect;
85 import android.graphics.RenderNode;
86 import android.graphics.Shader;
87 import android.graphics.drawable.ColorDrawable;
88 import android.graphics.drawable.Drawable;
89 import android.graphics.drawable.GradientDrawable;
90 import android.hardware.display.DisplayManagerGlobal;
91 import android.net.Uri;
92 import android.os.Build;
93 import android.os.Bundle;
94 import android.os.Handler;
95 import android.os.IBinder;
96 import android.os.Message;
97 import android.os.Parcel;
98 import android.os.Parcelable;
99 import android.os.RemoteCallback;
100 import android.os.RemoteException;
101 import android.os.SystemClock;
102 import android.os.Trace;
103 import android.sysprop.DisplayProperties;
104 import android.text.InputType;
105 import android.text.TextUtils;
106 import android.util.AttributeSet;
107 import android.util.FloatProperty;
108 import android.util.LayoutDirection;
109 import android.util.Log;
110 import android.util.LongSparseArray;
111 import android.util.LongSparseLongArray;
112 import android.util.Pair;
113 import android.util.Pools.SynchronizedPool;
114 import android.util.Property;
115 import android.util.SparseArray;
116 import android.util.SparseIntArray;
117 import android.util.StateSet;
118 import android.util.SuperNotCalledException;
119 import android.util.TypedValue;
120 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
121 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
122 import android.view.AccessibilityIterators.TextSegmentIterator;
123 import android.view.AccessibilityIterators.WordTextSegmentIterator;
124 import android.view.ContextMenu.ContextMenuInfo;
125 import android.view.InputDevice.InputSourceClass;
126 import android.view.Window.OnContentApplyWindowInsetsListener;
127 import android.view.WindowInsets.Type;
128 import android.view.WindowInsetsAnimation.Bounds;
129 import android.view.WindowManager.LayoutParams;
130 import android.view.accessibility.AccessibilityEvent;
131 import android.view.accessibility.AccessibilityEventSource;
132 import android.view.accessibility.AccessibilityManager;
133 import android.view.accessibility.AccessibilityNodeIdManager;
134 import android.view.accessibility.AccessibilityNodeInfo;
135 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
136 import android.view.accessibility.AccessibilityNodeProvider;
137 import android.view.accessibility.AccessibilityWindowInfo;
138 import android.view.animation.Animation;
139 import android.view.animation.AnimationUtils;
140 import android.view.animation.Transformation;
141 import android.view.autofill.AutofillId;
142 import android.view.autofill.AutofillManager;
143 import android.view.autofill.AutofillValue;
144 import android.view.contentcapture.ContentCaptureContext;
145 import android.view.contentcapture.ContentCaptureManager;
146 import android.view.contentcapture.ContentCaptureSession;
147 import android.view.displayhash.DisplayHash;
148 import android.view.displayhash.DisplayHashManager;
149 import android.view.displayhash.DisplayHashResultCallback;
150 import android.view.inputmethod.EditorInfo;
151 import android.view.inputmethod.InputConnection;
152 import android.view.inspector.InspectableProperty;
153 import android.view.inspector.InspectableProperty.EnumEntry;
154 import android.view.inspector.InspectableProperty.FlagEntry;
155 import android.view.translation.TranslationCapability;
156 import android.view.translation.TranslationSpec.DataFormat;
157 import android.view.translation.ViewTranslationCallback;
158 import android.view.translation.ViewTranslationRequest;
159 import android.view.translation.ViewTranslationResponse;
160 import android.widget.Checkable;
161 import android.widget.FrameLayout;
162 import android.widget.ScrollBarDrawable;
163 
164 import com.android.internal.R;
165 import com.android.internal.util.ArrayUtils;
166 import com.android.internal.util.FrameworkStatsLog;
167 import com.android.internal.util.Preconditions;
168 import com.android.internal.view.ScrollCaptureInternal;
169 import com.android.internal.view.TooltipPopup;
170 import com.android.internal.view.menu.MenuBuilder;
171 import com.android.internal.widget.ScrollBarUtils;
172 
173 import com.google.android.collect.Lists;
174 import com.google.android.collect.Maps;
175 
176 import java.io.PrintWriter;
177 import java.lang.annotation.Retention;
178 import java.lang.annotation.RetentionPolicy;
179 import java.lang.ref.WeakReference;
180 import java.lang.reflect.Field;
181 import java.lang.reflect.InvocationTargetException;
182 import java.lang.reflect.Method;
183 import java.lang.reflect.Modifier;
184 import java.util.ArrayList;
185 import java.util.Arrays;
186 import java.util.Calendar;
187 import java.util.Collection;
188 import java.util.Collections;
189 import java.util.HashMap;
190 import java.util.List;
191 import java.util.Locale;
192 import java.util.Map;
193 import java.util.concurrent.CopyOnWriteArrayList;
194 import java.util.concurrent.Executor;
195 import java.util.concurrent.atomic.AtomicInteger;
196 import java.util.function.Consumer;
197 import java.util.function.Predicate;
198 
199 /**
200  * <p>
201  * This class represents the basic building block for user interface components. A View
202  * occupies a rectangular area on the screen and is responsible for drawing and
203  * event handling. View is the base class for <em>widgets</em>, which are
204  * used to create interactive UI components (buttons, text fields, etc.). The
205  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
206  * are invisible containers that hold other Views (or other ViewGroups) and define
207  * their layout properties.
208  * </p>
209  *
210  * <div class="special reference">
211  * <h3>Developer Guides</h3>
212  * <p>For information about using this class to develop your application's user interface,
213  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
214  * </div>
215  *
216  * <a name="Using"></a>
217  * <h3>Using Views</h3>
218  * <p>
219  * All of the views in a window are arranged in a single tree. You can add views
220  * either from code or by specifying a tree of views in one or more XML layout
221  * files. There are many specialized subclasses of views that act as controls or
222  * are capable of displaying text, images, or other content.
223  * </p>
224  * <p>
225  * Once you have created a tree of views, there are typically a few types of
226  * common operations you may wish to perform:
227  * <ul>
228  * <li><strong>Set properties:</strong> for example setting the text of a
229  * {@link android.widget.TextView}. The available properties and the methods
230  * that set them will vary among the different subclasses of views. Note that
231  * properties that are known at build time can be set in the XML layout
232  * files.</li>
233  * <li><strong>Set focus:</strong> The framework will handle moving focus in
234  * response to user input. To force focus to a specific view, call
235  * {@link #requestFocus}.</li>
236  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
237  * that will be notified when something interesting happens to the view. For
238  * example, all views will let you set a listener to be notified when the view
239  * gains or loses focus. You can register such a listener using
240  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
241  * Other view subclasses offer more specialized listeners. For example, a Button
242  * exposes a listener to notify clients when the button is clicked.</li>
243  * <li><strong>Set visibility:</strong> You can hide or show views using
244  * {@link #setVisibility(int)}.</li>
245  * </ul>
246  * </p>
247  * <p><em>
248  * Note: The Android framework is responsible for measuring, laying out and
249  * drawing views. You should not call methods that perform these actions on
250  * views yourself unless you are actually implementing a
251  * {@link android.view.ViewGroup}.
252  * </em></p>
253  *
254  * <a name="Lifecycle"></a>
255  * <h3>Implementing a Custom View</h3>
256  *
257  * <p>
258  * To implement a custom view, you will usually begin by providing overrides for
259  * some of the standard methods that the framework calls on all views. You do
260  * not need to override all of these methods. In fact, you can start by just
261  * overriding {@link #onDraw(android.graphics.Canvas)}.
262  * <table border="2" width="85%" align="center" cellpadding="5">
263  *     <thead>
264  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
265  *     </thead>
266  *
267  *     <tbody>
268  *     <tr>
269  *         <td rowspan="2">Creation</td>
270  *         <td>Constructors</td>
271  *         <td>There is a form of the constructor that are called when the view
272  *         is created from code and a form that is called when the view is
273  *         inflated from a layout file. The second form should parse and apply
274  *         any attributes defined in the layout file.
275  *         </td>
276  *     </tr>
277  *     <tr>
278  *         <td><code>{@link #onFinishInflate()}</code></td>
279  *         <td>Called after a view and all of its children has been inflated
280  *         from XML.</td>
281  *     </tr>
282  *
283  *     <tr>
284  *         <td rowspan="3">Layout</td>
285  *         <td><code>{@link #onMeasure(int, int)}</code></td>
286  *         <td>Called to determine the size requirements for this view and all
287  *         of its children.
288  *         </td>
289  *     </tr>
290  *     <tr>
291  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
292  *         <td>Called when this view should assign a size and position to all
293  *         of its children.
294  *         </td>
295  *     </tr>
296  *     <tr>
297  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
298  *         <td>Called when the size of this view has changed.
299  *         </td>
300  *     </tr>
301  *
302  *     <tr>
303  *         <td>Drawing</td>
304  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
305  *         <td>Called when the view should render its content.
306  *         </td>
307  *     </tr>
308  *
309  *     <tr>
310  *         <td rowspan="4">Event processing</td>
311  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
312  *         <td>Called when a new hardware key event occurs.
313  *         </td>
314  *     </tr>
315  *     <tr>
316  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
317  *         <td>Called when a hardware key up event occurs.
318  *         </td>
319  *     </tr>
320  *     <tr>
321  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
322  *         <td>Called when a trackball motion event occurs.
323  *         </td>
324  *     </tr>
325  *     <tr>
326  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
327  *         <td>Called when a touch screen motion event occurs.
328  *         </td>
329  *     </tr>
330  *
331  *     <tr>
332  *         <td rowspan="2">Focus</td>
333  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
334  *         <td>Called when the view gains or loses focus.
335  *         </td>
336  *     </tr>
337  *
338  *     <tr>
339  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
340  *         <td>Called when the window containing the view gains or loses focus.
341  *         </td>
342  *     </tr>
343  *
344  *     <tr>
345  *         <td rowspan="3">Attaching</td>
346  *         <td><code>{@link #onAttachedToWindow()}</code></td>
347  *         <td>Called when the view is attached to a window.
348  *         </td>
349  *     </tr>
350  *
351  *     <tr>
352  *         <td><code>{@link #onDetachedFromWindow}</code></td>
353  *         <td>Called when the view is detached from its window.
354  *         </td>
355  *     </tr>
356  *
357  *     <tr>
358  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
359  *         <td>Called when the visibility of the window containing the view
360  *         has changed.
361  *         </td>
362  *     </tr>
363  *     </tbody>
364  *
365  * </table>
366  * </p>
367  *
368  * <a name="IDs"></a>
369  * <h3>IDs</h3>
370  * Views may have an integer id associated with them. These ids are typically
371  * assigned in the layout XML files, and are used to find specific views within
372  * the view tree. A common pattern is to:
373  * <ul>
374  * <li>Define a Button in the layout file and assign it a unique ID.
375  * <pre>
376  * &lt;Button
377  *     android:id="@+id/my_button"
378  *     android:layout_width="wrap_content"
379  *     android:layout_height="wrap_content"
380  *     android:text="@string/my_button_text"/&gt;
381  * </pre></li>
382  * <li>From the onCreate method of an Activity, find the Button
383  * <pre class="prettyprint">
384  *      Button myButton = findViewById(R.id.my_button);
385  * </pre></li>
386  * </ul>
387  * <p>
388  * View IDs need not be unique throughout the tree, but it is good practice to
389  * ensure that they are at least unique within the part of the tree you are
390  * searching.
391  * </p>
392  *
393  * <a name="Position"></a>
394  * <h3>Position</h3>
395  * <p>
396  * The geometry of a view is that of a rectangle. A view has a location,
397  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
398  * two dimensions, expressed as a width and a height. The unit for location
399  * and dimensions is the pixel.
400  * </p>
401  *
402  * <p>
403  * It is possible to retrieve the location of a view by invoking the methods
404  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
405  * coordinate of the rectangle representing the view. The latter returns the
406  * top, or Y, coordinate of the rectangle representing the view. These methods
407  * both return the location of the view relative to its parent. For instance,
408  * when getLeft() returns 20, that means the view is located 20 pixels to the
409  * right of the left edge of its direct parent.
410  * </p>
411  *
412  * <p>
413  * In addition, several convenience methods are offered to avoid unnecessary
414  * computations, namely {@link #getRight()} and {@link #getBottom()}.
415  * These methods return the coordinates of the right and bottom edges of the
416  * rectangle representing the view. For instance, calling {@link #getRight()}
417  * is similar to the following computation: <code>getLeft() + getWidth()</code>
418  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
419  * </p>
420  *
421  * <a name="SizePaddingMargins"></a>
422  * <h3>Size, padding and margins</h3>
423  * <p>
424  * The size of a view is expressed with a width and a height. A view actually
425  * possess two pairs of width and height values.
426  * </p>
427  *
428  * <p>
429  * The first pair is known as <em>measured width</em> and
430  * <em>measured height</em>. These dimensions define how big a view wants to be
431  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
432  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
433  * and {@link #getMeasuredHeight()}.
434  * </p>
435  *
436  * <p>
437  * The second pair is simply known as <em>width</em> and <em>height</em>, or
438  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
439  * dimensions define the actual size of the view on screen, at drawing time and
440  * after layout. These values may, but do not have to, be different from the
441  * measured width and height. The width and height can be obtained by calling
442  * {@link #getWidth()} and {@link #getHeight()}.
443  * </p>
444  *
445  * <p>
446  * To measure its dimensions, a view takes into account its padding. The padding
447  * is expressed in pixels for the left, top, right and bottom parts of the view.
448  * Padding can be used to offset the content of the view by a specific amount of
449  * pixels. For instance, a left padding of 2 will push the view's content by
450  * 2 pixels to the right of the left edge. Padding can be set using the
451  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
452  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
453  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
454  * {@link #getPaddingEnd()}.
455  * </p>
456  *
457  * <p>
458  * Even though a view can define a padding, it does not provide any support for
459  * margins. However, view groups provide such a support. Refer to
460  * {@link android.view.ViewGroup} and
461  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
462  * </p>
463  *
464  * <a name="Layout"></a>
465  * <h3>Layout</h3>
466  * <p>
467  * Layout is a two pass process: a measure pass and a layout pass. The measuring
468  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
469  * of the view tree. Each view pushes dimension specifications down the tree
470  * during the recursion. At the end of the measure pass, every view has stored
471  * its measurements. The second pass happens in
472  * {@link #layout(int,int,int,int)} and is also top-down. During
473  * this pass each parent is responsible for positioning all of its children
474  * using the sizes computed in the measure pass.
475  * </p>
476  *
477  * <p>
478  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
479  * {@link #getMeasuredHeight()} values must be set, along with those for all of
480  * that view's descendants. A view's measured width and measured height values
481  * must respect the constraints imposed by the view's parents. This guarantees
482  * that at the end of the measure pass, all parents accept all of their
483  * children's measurements. A parent view may call measure() more than once on
484  * its children. For example, the parent may measure each child once with
485  * unspecified dimensions to find out how big they want to be, then call
486  * measure() on them again with actual numbers if the sum of all the children's
487  * unconstrained sizes is too big or too small.
488  * </p>
489  *
490  * <p>
491  * The measure pass uses two classes to communicate dimensions. The
492  * {@link MeasureSpec} class is used by views to tell their parents how they
493  * want to be measured and positioned. The base LayoutParams class just
494  * describes how big the view wants to be for both width and height. For each
495  * dimension, it can specify one of:
496  * <ul>
497  * <li> an exact number
498  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
499  * (minus padding)
500  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
501  * enclose its content (plus padding).
502  * </ul>
503  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
504  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
505  * an X and Y value.
506  * </p>
507  *
508  * <p>
509  * MeasureSpecs are used to push requirements down the tree from parent to
510  * child. A MeasureSpec can be in one of three modes:
511  * <ul>
512  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
513  * of a child view. For example, a LinearLayout may call measure() on its child
514  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
515  * tall the child view wants to be given a width of 240 pixels.
516  * <li>EXACTLY: This is used by the parent to impose an exact size on the
517  * child. The child must use this size, and guarantee that all of its
518  * descendants will fit within this size.
519  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
520  * child. The child must guarantee that it and all of its descendants will fit
521  * within this size.
522  * </ul>
523  * </p>
524  *
525  * <p>
526  * To initiate a layout, call {@link #requestLayout}. This method is typically
527  * called by a view on itself when it believes that it can no longer fit within
528  * its current bounds.
529  * </p>
530  *
531  * <a name="Drawing"></a>
532  * <h3>Drawing</h3>
533  * <p>
534  * Drawing is handled by walking the tree and recording the drawing commands of
535  * any View that needs to update. After this, the drawing commands of the
536  * entire tree are issued to screen, clipped to the newly damaged area.
537  * </p>
538  *
539  * <p>
540  * The tree is largely recorded and drawn in order, with parents drawn before
541  * (i.e., behind) their children, with siblings drawn in the order they appear
542  * in the tree. If you set a background drawable for a View, then the View will
543  * draw it before calling back to its <code>onDraw()</code> method. The child
544  * drawing order can be overridden with
545  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
546  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
547  * </p>
548  *
549  * <p>
550  * To force a view to draw, call {@link #invalidate()}.
551  * </p>
552  *
553  * <a name="EventHandlingThreading"></a>
554  * <h3>Event Handling and Threading</h3>
555  * <p>
556  * The basic cycle of a view is as follows:
557  * <ol>
558  * <li>An event comes in and is dispatched to the appropriate view. The view
559  * handles the event and notifies any listeners.</li>
560  * <li>If in the course of processing the event, the view's bounds may need
561  * to be changed, the view will call {@link #requestLayout()}.</li>
562  * <li>Similarly, if in the course of processing the event the view's appearance
563  * may need to be changed, the view will call {@link #invalidate()}.</li>
564  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
565  * the framework will take care of measuring, laying out, and drawing the tree
566  * as appropriate.</li>
567  * </ol>
568  * </p>
569  *
570  * <p><em>Note: The entire view tree is single threaded. You must always be on
571  * the UI thread when calling any method on any view.</em>
572  * If you are doing work on other threads and want to update the state of a view
573  * from that thread, you should use a {@link Handler}.
574  * </p>
575  *
576  * <a name="FocusHandling"></a>
577  * <h3>Focus Handling</h3>
578  * <p>
579  * The framework will handle routine focus movement in response to user input.
580  * This includes changing the focus as views are removed or hidden, or as new
581  * views become available. Views indicate their willingness to take focus
582  * through the {@link #isFocusable} method. To change whether a view can take
583  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
584  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
585  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
586  * </p>
587  * <p>
588  * Focus movement is based on an algorithm which finds the nearest neighbor in a
589  * given direction. In rare cases, the default algorithm may not match the
590  * intended behavior of the developer. In these situations, you can provide
591  * explicit overrides by using these XML attributes in the layout file:
592  * <pre>
593  * nextFocusDown
594  * nextFocusLeft
595  * nextFocusRight
596  * nextFocusUp
597  * </pre>
598  * </p>
599  *
600  *
601  * <p>
602  * To get a particular view to take focus, call {@link #requestFocus()}.
603  * </p>
604  *
605  * <a name="TouchMode"></a>
606  * <h3>Touch Mode</h3>
607  * <p>
608  * When a user is navigating a user interface via directional keys such as a D-pad, it is
609  * necessary to give focus to actionable items such as buttons so the user can see
610  * what will take input.  If the device has touch capabilities, however, and the user
611  * begins interacting with the interface by touching it, it is no longer necessary to
612  * always highlight, or give focus to, a particular view.  This motivates a mode
613  * for interaction named 'touch mode'.
614  * </p>
615  * <p>
616  * For a touch capable device, once the user touches the screen, the device
617  * will enter touch mode.  From this point onward, only views for which
618  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
619  * Other views that are touchable, like buttons, will not take focus when touched; they will
620  * only fire the on click listeners.
621  * </p>
622  * <p>
623  * Any time a user hits a directional key, such as a D-pad direction, the view device will
624  * exit touch mode, and find a view to take focus, so that the user may resume interacting
625  * with the user interface without touching the screen again.
626  * </p>
627  * <p>
628  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
629  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
630  * </p>
631  *
632  * <a name="Scrolling"></a>
633  * <h3>Scrolling</h3>
634  * <p>
635  * The framework provides basic support for views that wish to internally
636  * scroll their content. This includes keeping track of the X and Y scroll
637  * offset as well as mechanisms for drawing scrollbars. See
638  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
639  * {@link #awakenScrollBars()} for more details.
640  * </p>
641  *
642  * <a name="Tags"></a>
643  * <h3>Tags</h3>
644  * <p>
645  * Unlike IDs, tags are not used to identify views. Tags are essentially an
646  * extra piece of information that can be associated with a view. They are most
647  * often used as a convenience to store data related to views in the views
648  * themselves rather than by putting them in a separate structure.
649  * </p>
650  * <p>
651  * Tags may be specified with character sequence values in layout XML as either
652  * a single tag using the {@link android.R.styleable#View_tag android:tag}
653  * attribute or multiple tags using the {@code <tag>} child element:
654  * <pre>
655  *     &lt;View ...
656  *           android:tag="@string/mytag_value" /&gt;
657  *     &lt;View ...&gt;
658  *         &lt;tag android:id="@+id/mytag"
659  *              android:value="@string/mytag_value" /&gt;
660  *     &lt;/View>
661  * </pre>
662  * </p>
663  * <p>
664  * Tags may also be specified with arbitrary objects from code using
665  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
666  * </p>
667  *
668  * <a name="Themes"></a>
669  * <h3>Themes</h3>
670  * <p>
671  * By default, Views are created using the theme of the Context object supplied
672  * to their constructor; however, a different theme may be specified by using
673  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
674  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
675  * code.
676  * </p>
677  * <p>
678  * When the {@link android.R.styleable#View_theme android:theme} attribute is
679  * used in XML, the specified theme is applied on top of the inflation
680  * context's theme (see {@link LayoutInflater}) and used for the view itself as
681  * well as any child elements.
682  * </p>
683  * <p>
684  * In the following example, both views will be created using the Material dark
685  * color scheme; however, because an overlay theme is used which only defines a
686  * subset of attributes, the value of
687  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
688  * the inflation context's theme (e.g. the Activity theme) will be preserved.
689  * <pre>
690  *     &lt;LinearLayout
691  *             ...
692  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
693  *         &lt;View ...&gt;
694  *     &lt;/LinearLayout&gt;
695  * </pre>
696  * </p>
697  *
698  * <a name="Properties"></a>
699  * <h3>Properties</h3>
700  * <p>
701  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
702  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
703  * available both in the {@link Property} form as well as in similarly-named setter/getter
704  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
705  * be used to set persistent state associated with these rendering-related properties on the view.
706  * The properties and methods can also be used in conjunction with
707  * {@link android.animation.Animator Animator}-based animations, described more in the
708  * <a href="#Animation">Animation</a> section.
709  * </p>
710  *
711  * <a name="Animation"></a>
712  * <h3>Animation</h3>
713  * <p>
714  * Starting with Android 3.0, the preferred way of animating views is to use the
715  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
716  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
717  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
718  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
719  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
720  * makes animating these View properties particularly easy and efficient.
721  * </p>
722  * <p>
723  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
724  * You can attach an {@link Animation} object to a view using
725  * {@link #setAnimation(Animation)} or
726  * {@link #startAnimation(Animation)}. The animation can alter the scale,
727  * rotation, translation and alpha of a view over time. If the animation is
728  * attached to a view that has children, the animation will affect the entire
729  * subtree rooted by that node. When an animation is started, the framework will
730  * take care of redrawing the appropriate views until the animation completes.
731  * </p>
732  *
733  * <a name="Security"></a>
734  * <h3>Security</h3>
735  * <p>
736  * Sometimes it is essential that an application be able to verify that an action
737  * is being performed with the full knowledge and consent of the user, such as
738  * granting a permission request, making a purchase or clicking on an advertisement.
739  * Unfortunately, a malicious application could try to spoof the user into
740  * performing these actions, unaware, by concealing the intended purpose of the view.
741  * As a remedy, the framework offers a touch filtering mechanism that can be used to
742  * improve the security of views that provide access to sensitive functionality.
743  * </p><p>
744  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
745  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
746  * will discard touches that are received whenever the view's window is obscured by
747  * another visible window.  As a result, the view will not receive touches whenever a
748  * toast, dialog or other window appears above the view's window.
749  * </p><p>
750  * For more fine-grained control over security, consider overriding the
751  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
752  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
753  * </p>
754  *
755  * @attr ref android.R.styleable#View_accessibilityHeading
756  * @attr ref android.R.styleable#View_allowClickWhenDisabled
757  * @attr ref android.R.styleable#View_alpha
758  * @attr ref android.R.styleable#View_background
759  * @attr ref android.R.styleable#View_clickable
760  * @attr ref android.R.styleable#View_clipToOutline
761  * @attr ref android.R.styleable#View_contentDescription
762  * @attr ref android.R.styleable#View_drawingCacheQuality
763  * @attr ref android.R.styleable#View_duplicateParentState
764  * @attr ref android.R.styleable#View_id
765  * @attr ref android.R.styleable#View_requiresFadingEdge
766  * @attr ref android.R.styleable#View_fadeScrollbars
767  * @attr ref android.R.styleable#View_fadingEdgeLength
768  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
769  * @attr ref android.R.styleable#View_fitsSystemWindows
770  * @attr ref android.R.styleable#View_isScrollContainer
771  * @attr ref android.R.styleable#View_focusable
772  * @attr ref android.R.styleable#View_focusableInTouchMode
773  * @attr ref android.R.styleable#View_focusedByDefault
774  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
775  * @attr ref android.R.styleable#View_keepScreenOn
776  * @attr ref android.R.styleable#View_keyboardNavigationCluster
777  * @attr ref android.R.styleable#View_layerType
778  * @attr ref android.R.styleable#View_layoutDirection
779  * @attr ref android.R.styleable#View_longClickable
780  * @attr ref android.R.styleable#View_minHeight
781  * @attr ref android.R.styleable#View_minWidth
782  * @attr ref android.R.styleable#View_nextClusterForward
783  * @attr ref android.R.styleable#View_nextFocusDown
784  * @attr ref android.R.styleable#View_nextFocusLeft
785  * @attr ref android.R.styleable#View_nextFocusRight
786  * @attr ref android.R.styleable#View_nextFocusUp
787  * @attr ref android.R.styleable#View_onClick
788  * @attr ref android.R.styleable#View_outlineSpotShadowColor
789  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
790  * @attr ref android.R.styleable#View_padding
791  * @attr ref android.R.styleable#View_paddingHorizontal
792  * @attr ref android.R.styleable#View_paddingVertical
793  * @attr ref android.R.styleable#View_paddingBottom
794  * @attr ref android.R.styleable#View_paddingLeft
795  * @attr ref android.R.styleable#View_paddingRight
796  * @attr ref android.R.styleable#View_paddingTop
797  * @attr ref android.R.styleable#View_paddingStart
798  * @attr ref android.R.styleable#View_paddingEnd
799  * @attr ref android.R.styleable#View_saveEnabled
800  * @attr ref android.R.styleable#View_rotation
801  * @attr ref android.R.styleable#View_rotationX
802  * @attr ref android.R.styleable#View_rotationY
803  * @attr ref android.R.styleable#View_scaleX
804  * @attr ref android.R.styleable#View_scaleY
805  * @attr ref android.R.styleable#View_scrollX
806  * @attr ref android.R.styleable#View_scrollY
807  * @attr ref android.R.styleable#View_scrollbarSize
808  * @attr ref android.R.styleable#View_scrollbarStyle
809  * @attr ref android.R.styleable#View_scrollbars
810  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
811  * @attr ref android.R.styleable#View_scrollbarFadeDuration
812  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
813  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
814  * @attr ref android.R.styleable#View_scrollbarThumbVertical
815  * @attr ref android.R.styleable#View_scrollbarTrackVertical
816  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
817  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
818  * @attr ref android.R.styleable#View_stateListAnimator
819  * @attr ref android.R.styleable#View_transitionName
820  * @attr ref android.R.styleable#View_soundEffectsEnabled
821  * @attr ref android.R.styleable#View_tag
822  * @attr ref android.R.styleable#View_textAlignment
823  * @attr ref android.R.styleable#View_textDirection
824  * @attr ref android.R.styleable#View_transformPivotX
825  * @attr ref android.R.styleable#View_transformPivotY
826  * @attr ref android.R.styleable#View_translationX
827  * @attr ref android.R.styleable#View_translationY
828  * @attr ref android.R.styleable#View_translationZ
829  * @attr ref android.R.styleable#View_visibility
830  * @attr ref android.R.styleable#View_theme
831  *
832  * @see android.view.ViewGroup
833  */
834 @UiThread
835 public class View implements Drawable.Callback, KeyEvent.Callback,
836         AccessibilityEventSource {
837     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
838     private static final boolean DBG = false;
839 
840     /** @hide */
841     public static boolean DEBUG_DRAW = false;
842 
843     /**
844      * The logging tag used by this class with android.util.Log.
845      */
846     protected static final String VIEW_LOG_TAG = "View";
847 
848     /**
849      * The logging tag used by this class when logging verbose, autofill-related messages.
850      */
851     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
852     // set if a session is not started.
853     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
854 
855     /**
856      * The logging tag used by this class when logging content capture-related messages.
857      */
858     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
859 
860     private static final boolean DEBUG_CONTENT_CAPTURE = false;
861 
862     /**
863      * When set to true, this view will save its attribute data.
864      *
865      * @hide
866      */
867     public static boolean sDebugViewAttributes = false;
868 
869     /**
870      * When set to this application package view will save its attribute data.
871      *
872      * @hide
873      */
874     public static String sDebugViewAttributesApplicationPackage;
875 
876     /**
877      * Used to mark a View that has no ID.
878      */
879     public static final int NO_ID = -1;
880 
881     /**
882      * Last ID that is given to Views that are no part of activities.
883      *
884      * {@hide}
885      */
886     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
887 
888     /**
889      * Attribute to find the autofilled highlight
890      *
891      * @see #getAutofilledDrawable()
892      */
893     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
894             new int[]{android.R.attr.autofilledHighlight};
895 
896     /**
897      * Signals that compatibility booleans have been initialized according to
898      * target SDK versions.
899      */
900     private static boolean sCompatibilityDone = false;
901 
902     /**
903      * Use the old (broken) way of building MeasureSpecs.
904      */
905     private static boolean sUseBrokenMakeMeasureSpec = false;
906 
907     /**
908      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
909      */
910     static boolean sUseZeroUnspecifiedMeasureSpec = false;
911 
912     /**
913      * Ignore any optimizations using the measure cache.
914      */
915     private static boolean sIgnoreMeasureCache = false;
916 
917     /**
918      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
919      */
920     private static boolean sAlwaysRemeasureExactly = false;
921 
922     /**
923      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
924      * without throwing
925      */
926     static boolean sTextureViewIgnoresDrawableSetters = false;
927 
928     /**
929      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
930      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
931      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
932      * check is implemented for backwards compatibility.
933      *
934      * {@hide}
935      */
936     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
937 
938     /**
939      * Prior to N, when drag enters into child of a view that has already received an
940      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
941      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
942      * false from its event handler for these events.
943      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
944      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
945      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
946      */
947     static boolean sCascadedDragDrop;
948 
949     /**
950      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
951      * to determine things like whether or not to permit item click events. We can't break
952      * apps that do this just because more things (clickable things) are now auto-focusable
953      * and they would get different results, so give old behavior to old apps.
954      */
955     static boolean sHasFocusableExcludeAutoFocusable;
956 
957     /**
958      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
959      * made focusable by default. As a result, apps could (incorrectly) change the clickable
960      * setting of views off the UI thread. Now that clickable can effect the focusable state,
961      * changing the clickable attribute off the UI thread will cause an exception (since changing
962      * the focusable state checks). In order to prevent apps from crashing, we will handle this
963      * specific case and just not notify parents on new focusables resulting from marking views
964      * clickable from outside the UI thread.
965      */
966     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
967 
968     /**
969      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
970      * Float.NaN. If the app is targetting P or later then passing these values will result in an
971      * exception being thrown. If the app is targetting an earlier SDK version, then we will
972      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
973      * these bogus values.
974      */
975     private static boolean sThrowOnInvalidFloatProperties;
976 
977     /**
978      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
979      * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead.
980      */
981     private static boolean sAcceptZeroSizeDragShadow;
982 
983     /**
984      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
985      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
986      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
987      * further down the hierarchy. This violates the basic concepts of the view hierarchy, and
988      * thus, the hierarchical dispatching mechanism was hard to use for apps.
989      * <p>
990      * In order to make window inset dispatching work properly, we dispatch window insets
991      * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}.
992      */
993     static boolean sBrokenInsetsDispatch;
994 
995     /**
996      * Prior to Q, calling
997      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
998      * did not call update the window format so the opacity of the background was not correctly
999      * applied to the window. Some applications rely on this misbehavior to work properly.
1000      * <p>
1001      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
1002      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
1003      * which updates the window format.
1004      * @hide
1005      */
1006     protected static boolean sBrokenWindowBackground;
1007 
1008     /**
1009      * Prior to R, we were always forcing a layout of the entire hierarchy when insets changed from
1010      * the server. This is inefficient and not all apps use it. Instead, we want to rely on apps
1011      * calling {@link #requestLayout} when they need to relayout based on an insets change.
1012      */
1013     static boolean sForceLayoutWhenInsetsChanged;
1014 
1015     /** @hide */
1016     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
1017     @Retention(RetentionPolicy.SOURCE)
1018     public @interface Focusable {}
1019 
1020     /**
1021      * This view does not want keystrokes.
1022      * <p>
1023      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1024      * android:focusable}.
1025      */
1026     public static final int NOT_FOCUSABLE = 0x00000000;
1027 
1028     /**
1029      * This view wants keystrokes.
1030      * <p>
1031      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1032      * android:focusable}.
1033      */
1034     public static final int FOCUSABLE = 0x00000001;
1035 
1036     /**
1037      * This view determines focusability automatically. This is the default.
1038      * <p>
1039      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1040      * android:focusable}.
1041      */
1042     public static final int FOCUSABLE_AUTO = 0x00000010;
1043 
1044     /**
1045      * Mask for use with setFlags indicating bits used for focus.
1046      */
1047     private static final int FOCUSABLE_MASK = 0x00000011;
1048 
1049     /**
1050      * This view will adjust its padding to fit sytem windows (e.g. status bar)
1051      */
1052     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1053 
1054     /** @hide */
1055     @IntDef({VISIBLE, INVISIBLE, GONE})
1056     @Retention(RetentionPolicy.SOURCE)
1057     public @interface Visibility {}
1058 
1059     /**
1060      * This view is visible.
1061      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1062      * android:visibility}.
1063      */
1064     public static final int VISIBLE = 0x00000000;
1065 
1066     /**
1067      * This view is invisible, but it still takes up space for layout purposes.
1068      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1069      * android:visibility}.
1070      */
1071     public static final int INVISIBLE = 0x00000004;
1072 
1073     /**
1074      * This view is invisible, and it doesn't take any space for layout
1075      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1076      * android:visibility}.
1077      */
1078     public static final int GONE = 0x00000008;
1079 
1080     /**
1081      * Mask for use with setFlags indicating bits used for visibility.
1082      * {@hide}
1083      */
1084     static final int VISIBILITY_MASK = 0x0000000C;
1085 
1086     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1087 
1088     /**
1089      * Hint indicating that this view can be autofilled with an email address.
1090      *
1091      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1092      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1093      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1094      *
1095      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1096      */
1097     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1098 
1099     /**
1100      * Hint indicating that this view can be autofilled with a user's real name.
1101      *
1102      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1103      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1104      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1105      *
1106      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1107      */
1108     public static final String AUTOFILL_HINT_NAME = "name";
1109 
1110     /**
1111      * Hint indicating that this view can be autofilled with a username.
1112      *
1113      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1114      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1115      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1116      *
1117      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1118      */
1119     public static final String AUTOFILL_HINT_USERNAME = "username";
1120 
1121     /**
1122      * Hint indicating that this view can be autofilled with a password.
1123      *
1124      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1125      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1126      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1127      *
1128      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1129      */
1130     public static final String AUTOFILL_HINT_PASSWORD = "password";
1131 
1132     /**
1133      * Hint indicating that this view can be autofilled with a phone number.
1134      *
1135      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1136      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1137      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1138      *
1139      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1140      */
1141     public static final String AUTOFILL_HINT_PHONE = "phone";
1142 
1143     /**
1144      * Hint indicating that this view can be autofilled with a postal address.
1145      *
1146      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1147      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1148      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1149      *
1150      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1151      */
1152     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1153 
1154     /**
1155      * Hint indicating that this view can be autofilled with a postal code.
1156      *
1157      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1158      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1159      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1160      *
1161      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1162      */
1163     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1164 
1165     /**
1166      * Hint indicating that this view can be autofilled with a credit card number.
1167      *
1168      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1169      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1170      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1171      *
1172      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1173      */
1174     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1175 
1176     /**
1177      * Hint indicating that this view can be autofilled with a credit card security code.
1178      *
1179      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1180      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1181      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1182      *
1183      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1184      */
1185     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1186 
1187     /**
1188      * Hint indicating that this view can be autofilled with a credit card expiration date.
1189      *
1190      * <p>It should be used when the credit card expiration date is represented by just one view;
1191      * if it is represented by more than one (for example, one view for the month and another view
1192      * for the year), then each of these views should use the hint specific for the unit
1193      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1194      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1195      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1196      *
1197      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1198      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1199      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1200      *
1201      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1202      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1203      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1204      * the following options:
1205      *
1206      * <ul>
1207      *   <li>{@code "04/2020"}
1208      *   <li>{@code "4/2020"}
1209      *   <li>{@code "2020/04"}
1210      *   <li>{@code "2020/4"}
1211      *   <li>{@code "April/2020"}
1212      *   <li>{@code "Apr/2020"}
1213      * </ul>
1214      *
1215      * <p>You define a date autofill value for the view by overriding the following methods:
1216      *
1217      * <ol>
1218      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1219      *   <li>{@link #getAutofillValue()} to return a
1220      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1221      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1222      * </ol>
1223      *
1224      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1225      */
1226     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1227             "creditCardExpirationDate";
1228 
1229     /**
1230      * Hint indicating that this view can be autofilled with a credit card expiration month.
1231      *
1232      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1233      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1234      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1235      *
1236      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1237      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1238      * ambiguity when the autofill service provides a value for it. To understand why a
1239      * value can be ambiguous, consider "January", which could be represented as either of
1240      *
1241      * <ul>
1242      *   <li>{@code "1"}: recommended way.
1243      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1244      *   <li>{@code "January"}: full name, in English.
1245      *   <li>{@code "jan"}: abbreviated name, in English.
1246      *   <li>{@code "Janeiro"}: full name, in another language.
1247      * </ul>
1248      *
1249      * <p>Another recommended approach is to use a date autofill value - see
1250      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1251      *
1252      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1253      */
1254     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1255             "creditCardExpirationMonth";
1256 
1257     /**
1258      * Hint indicating that this view can be autofilled with a credit card expiration year.
1259      *
1260      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1261      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1262      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1263      *
1264      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1265      */
1266     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1267             "creditCardExpirationYear";
1268 
1269     /**
1270      * Hint indicating that this view can be autofilled with a credit card expiration day.
1271      *
1272      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1273      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1274      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1275      *
1276      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1277      */
1278     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1279 
1280     /**
1281      * Hints for the autofill services that describes the content of the view.
1282      */
1283     private @Nullable String[] mAutofillHints;
1284 
1285     /**
1286      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1287      */
1288     private AutofillId mAutofillId;
1289 
1290     /** @hide */
1291     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1292             AUTOFILL_TYPE_NONE,
1293             AUTOFILL_TYPE_TEXT,
1294             AUTOFILL_TYPE_TOGGLE,
1295             AUTOFILL_TYPE_LIST,
1296             AUTOFILL_TYPE_DATE,
1297     })
1298     @Retention(RetentionPolicy.SOURCE)
1299     public @interface AutofillType {}
1300 
1301     /**
1302      * Autofill type for views that cannot be autofilled.
1303      *
1304      * <p>Typically used when the view is read-only; for example, a text label.
1305      *
1306      * @see #getAutofillType()
1307      */
1308     public static final int AUTOFILL_TYPE_NONE = 0;
1309 
1310     /**
1311      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1312      *
1313      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1314      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1315      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1316      *
1317      * @see #getAutofillType()
1318      */
1319     public static final int AUTOFILL_TYPE_TEXT = 1;
1320 
1321     /**
1322      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1323      *
1324      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1325      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1326      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1327      *
1328      * @see #getAutofillType()
1329      */
1330     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1331 
1332     /**
1333      * Autofill type for a selection list field, which is filled by an {@code int}
1334      * representing the element index inside the list (starting at {@code 0}).
1335      *
1336      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1337      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1338      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1339      *
1340      * <p>The available options in the selection list are typically provided by
1341      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1342      *
1343      * @see #getAutofillType()
1344      */
1345     public static final int AUTOFILL_TYPE_LIST = 3;
1346 
1347     /**
1348      * Autofill type for a field that contains a date, which is represented by a long representing
1349      * the number of milliseconds since the standard base time known as "the epoch", namely
1350      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1351      *
1352      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1353      * {@link AutofillValue#forDate(long)}, and the values passed to
1354      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1355      *
1356      * @see #getAutofillType()
1357      */
1358     public static final int AUTOFILL_TYPE_DATE = 4;
1359 
1360 
1361     /** @hide */
1362     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1363             IMPORTANT_FOR_AUTOFILL_AUTO,
1364             IMPORTANT_FOR_AUTOFILL_YES,
1365             IMPORTANT_FOR_AUTOFILL_NO,
1366             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1367             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1368     })
1369     @Retention(RetentionPolicy.SOURCE)
1370     public @interface AutofillImportance {}
1371 
1372     /**
1373      * Automatically determine whether a view is important for autofill.
1374      *
1375      * @see #isImportantForAutofill()
1376      * @see #setImportantForAutofill(int)
1377      */
1378     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1379 
1380     /**
1381      * The view is important for autofill, and its children (if any) will be traversed.
1382      *
1383      * @see #isImportantForAutofill()
1384      * @see #setImportantForAutofill(int)
1385      */
1386     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1387 
1388     /**
1389      * The view is not important for autofill, but its children (if any) will be traversed.
1390      *
1391      * @see #isImportantForAutofill()
1392      * @see #setImportantForAutofill(int)
1393      */
1394     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1395 
1396     /**
1397      * The view is important for autofill, but its children (if any) will not be traversed.
1398      *
1399      * @see #isImportantForAutofill()
1400      * @see #setImportantForAutofill(int)
1401      */
1402     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1403 
1404     /**
1405      * The view is not important for autofill, and its children (if any) will not be traversed.
1406      *
1407      * @see #isImportantForAutofill()
1408      * @see #setImportantForAutofill(int)
1409      */
1410     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1411 
1412     /** @hide */
1413     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1414             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1415     })
1416     @Retention(RetentionPolicy.SOURCE)
1417     public @interface AutofillFlags {}
1418 
1419     /**
1420      * Flag requesting you to add views that are marked as not important for autofill
1421      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1422      */
1423     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1424 
1425     /** @hide */
1426     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1427             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1428             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1429             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1430             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1431             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1432     })
1433     @Retention(RetentionPolicy.SOURCE)
1434     public @interface ContentCaptureImportance {}
1435 
1436     /**
1437      * Automatically determine whether a view is important for content capture.
1438      *
1439      * @see #isImportantForContentCapture()
1440      * @see #setImportantForContentCapture(int)
1441      */
1442     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1443 
1444     /**
1445      * The view is important for content capture, and its children (if any) will be traversed.
1446      *
1447      * @see #isImportantForContentCapture()
1448      * @see #setImportantForContentCapture(int)
1449      */
1450     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1451 
1452     /**
1453      * The view is not important for content capture, but its children (if any) will be traversed.
1454      *
1455      * @see #isImportantForContentCapture()
1456      * @see #setImportantForContentCapture(int)
1457      */
1458     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1459 
1460     /**
1461      * The view is important for content capture, but its children (if any) will not be traversed.
1462      *
1463      * @see #isImportantForContentCapture()
1464      * @see #setImportantForContentCapture(int)
1465      */
1466     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1467 
1468     /**
1469      * The view is not important for content capture, and its children (if any) will not be
1470      * traversed.
1471      *
1472      * @see #isImportantForContentCapture()
1473      * @see #setImportantForContentCapture(int)
1474      */
1475     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1476 
1477     /** {@hide} */
1478     @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
1479             value = {
1480                     SCROLL_CAPTURE_HINT_AUTO,
1481                     SCROLL_CAPTURE_HINT_EXCLUDE,
1482                     SCROLL_CAPTURE_HINT_INCLUDE,
1483                     SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
1484     })
1485     @Retention(RetentionPolicy.SOURCE)
1486     public @interface ScrollCaptureHint {}
1487 
1488     /**
1489      * The content of this view will be considered for scroll capture if scrolling is possible.
1490      *
1491      * @see #getScrollCaptureHint()
1492      * @see #setScrollCaptureHint(int)
1493      */
1494     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
1495 
1496     /**
1497      * Explicitly exclude this view as a potential scroll capture target. The system will not
1498      * consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
1499      * takes precedence over.
1500      *
1501      * @see #getScrollCaptureHint()
1502      * @see #setScrollCaptureHint(int)
1503      */
1504     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
1505 
1506     /**
1507      * Explicitly include this view as a potential scroll capture target. When locating a scroll
1508      * capture target, this view will be prioritized before others without this flag. Mutually
1509      * exclusive with {@link #SCROLL_CAPTURE_HINT_EXCLUDE}, which takes precedence.
1510      *
1511      * @see #getScrollCaptureHint()
1512      * @see #setScrollCaptureHint(int)
1513      */
1514     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
1515 
1516     /**
1517      * Explicitly exclude all children of this view as potential scroll capture targets. This view
1518      * is unaffected. Note: Excluded children are not considered, regardless of {@link
1519      * #SCROLL_CAPTURE_HINT_INCLUDE}.
1520      *
1521      * @see #getScrollCaptureHint()
1522      * @see #setScrollCaptureHint(int)
1523      */
1524     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
1525 
1526     /**
1527      * This view is enabled. Interpretation varies by subclass.
1528      * Use with ENABLED_MASK when calling setFlags.
1529      * {@hide}
1530      */
1531     static final int ENABLED = 0x00000000;
1532 
1533     /**
1534      * This view is disabled. Interpretation varies by subclass.
1535      * Use with ENABLED_MASK when calling setFlags.
1536      * {@hide}
1537      */
1538     static final int DISABLED = 0x00000020;
1539 
1540    /**
1541     * Mask for use with setFlags indicating bits used for indicating whether
1542     * this view is enabled
1543     * {@hide}
1544     */
1545     static final int ENABLED_MASK = 0x00000020;
1546 
1547     /**
1548      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1549      * called and further optimizations will be performed. It is okay to have
1550      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1551      * {@hide}
1552      */
1553     static final int WILL_NOT_DRAW = 0x00000080;
1554 
1555     /**
1556      * Mask for use with setFlags indicating bits used for indicating whether
1557      * this view is will draw
1558      * {@hide}
1559      */
1560     static final int DRAW_MASK = 0x00000080;
1561 
1562     /**
1563      * <p>This view doesn't show scrollbars.</p>
1564      * {@hide}
1565      */
1566     static final int SCROLLBARS_NONE = 0x00000000;
1567 
1568     /**
1569      * <p>This view shows horizontal scrollbars.</p>
1570      * {@hide}
1571      */
1572     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1573 
1574     /**
1575      * <p>This view shows vertical scrollbars.</p>
1576      * {@hide}
1577      */
1578     static final int SCROLLBARS_VERTICAL = 0x00000200;
1579 
1580     /**
1581      * <p>Mask for use with setFlags indicating bits used for indicating which
1582      * scrollbars are enabled.</p>
1583      * {@hide}
1584      */
1585     static final int SCROLLBARS_MASK = 0x00000300;
1586 
1587     /**
1588      * Indicates that the view should filter touches when its window is obscured.
1589      * Refer to the class comments for more information about this security feature.
1590      * {@hide}
1591      */
1592     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1593 
1594     /**
1595      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1596      * that they are optional and should be skipped if the window has
1597      * requested system UI flags that ignore those insets for layout.
1598      * <p>
1599      * This is only used for support library as of Android R. The framework now uses
1600      * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
1601      * insets path that loses insets information.
1602      */
1603     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1604 
1605     /**
1606      * <p>This view doesn't show fading edges.</p>
1607      * {@hide}
1608      */
1609     static final int FADING_EDGE_NONE = 0x00000000;
1610 
1611     /**
1612      * <p>This view shows horizontal fading edges.</p>
1613      * {@hide}
1614      */
1615     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1616 
1617     /**
1618      * <p>This view shows vertical fading edges.</p>
1619      * {@hide}
1620      */
1621     static final int FADING_EDGE_VERTICAL = 0x00002000;
1622 
1623     /**
1624      * <p>Mask for use with setFlags indicating bits used for indicating which
1625      * fading edges are enabled.</p>
1626      * {@hide}
1627      */
1628     static final int FADING_EDGE_MASK = 0x00003000;
1629 
1630     /**
1631      * <p>Indicates this view can be clicked. When clickable, a View reacts
1632      * to clicks by notifying the OnClickListener.<p>
1633      * {@hide}
1634      */
1635     static final int CLICKABLE = 0x00004000;
1636 
1637     /**
1638      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1639      * {@hide}
1640      */
1641     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1642 
1643     /**
1644      * <p>Indicates that no icicle should be saved for this view.<p>
1645      * {@hide}
1646      */
1647     static final int SAVE_DISABLED = 0x000010000;
1648 
1649     /**
1650      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1651      * property.</p>
1652      * {@hide}
1653      */
1654     static final int SAVE_DISABLED_MASK = 0x000010000;
1655 
1656     /**
1657      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1658      * {@hide}
1659      */
1660     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1661 
1662     /**
1663      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1664      * {@hide}
1665      */
1666     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1667 
1668     /** @hide */
1669     @Retention(RetentionPolicy.SOURCE)
1670     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1671             DRAWING_CACHE_QUALITY_LOW,
1672             DRAWING_CACHE_QUALITY_HIGH,
1673             DRAWING_CACHE_QUALITY_AUTO
1674     })
1675     public @interface DrawingCacheQuality {}
1676 
1677     /**
1678      * <p>Enables low quality mode for the drawing cache.</p>
1679      *
1680      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1681      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1682      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1683      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1684      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1685      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1686      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1687      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1688      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1689      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1690      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1691      * reports or unit testing the {@link PixelCopy} API is recommended.
1692      */
1693     @Deprecated
1694     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1695 
1696     /**
1697      * <p>Enables high quality mode for the drawing cache.</p>
1698      *
1699      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1700      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1701      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1702      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1703      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1704      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1705      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1706      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1707      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1708      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1709      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1710      * reports or unit testing the {@link PixelCopy} API is recommended.
1711      */
1712     @Deprecated
1713     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1714 
1715     /**
1716      * <p>Enables automatic quality mode for the drawing cache.</p>
1717      *
1718      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1719      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1720      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1721      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1722      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1723      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1724      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1725      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1726      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1727      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1728      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1729      * reports or unit testing the {@link PixelCopy} API is recommended.
1730      */
1731     @Deprecated
1732     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1733 
1734     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1735             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1736     };
1737 
1738     /**
1739      * <p>Mask for use with setFlags indicating bits used for the cache
1740      * quality property.</p>
1741      * {@hide}
1742      */
1743     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1744 
1745     /**
1746      * <p>
1747      * Indicates this view can be long clicked. When long clickable, a View
1748      * reacts to long clicks by notifying the OnLongClickListener or showing a
1749      * context menu.
1750      * </p>
1751      * {@hide}
1752      */
1753     static final int LONG_CLICKABLE = 0x00200000;
1754 
1755     /**
1756      * <p>Indicates that this view gets its drawable states from its direct parent
1757      * and ignores its original internal states.</p>
1758      *
1759      * @hide
1760      */
1761     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1762 
1763     /**
1764      * <p>
1765      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1766      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1767      * OnContextClickListener.
1768      * </p>
1769      * {@hide}
1770      */
1771     static final int CONTEXT_CLICKABLE = 0x00800000;
1772 
1773     /** @hide */
1774     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1775             SCROLLBARS_INSIDE_OVERLAY,
1776             SCROLLBARS_INSIDE_INSET,
1777             SCROLLBARS_OUTSIDE_OVERLAY,
1778             SCROLLBARS_OUTSIDE_INSET
1779     })
1780     @Retention(RetentionPolicy.SOURCE)
1781     public @interface ScrollBarStyle {}
1782 
1783     /**
1784      * The scrollbar style to display the scrollbars inside the content area,
1785      * without increasing the padding. The scrollbars will be overlaid with
1786      * translucency on the view's content.
1787      */
1788     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1789 
1790     /**
1791      * The scrollbar style to display the scrollbars inside the padded area,
1792      * increasing the padding of the view. The scrollbars will not overlap the
1793      * content area of the view.
1794      */
1795     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1796 
1797     /**
1798      * The scrollbar style to display the scrollbars at the edge of the view,
1799      * without increasing the padding. The scrollbars will be overlaid with
1800      * translucency.
1801      */
1802     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1803 
1804     /**
1805      * The scrollbar style to display the scrollbars at the edge of the view,
1806      * increasing the padding of the view. The scrollbars will only overlap the
1807      * background, if any.
1808      */
1809     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1810 
1811     /**
1812      * Mask to check if the scrollbar style is overlay or inset.
1813      * {@hide}
1814      */
1815     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1816 
1817     /**
1818      * Mask to check if the scrollbar style is inside or outside.
1819      * {@hide}
1820      */
1821     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1822 
1823     /**
1824      * Mask for scrollbar style.
1825      * {@hide}
1826      */
1827     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1828 
1829     /**
1830      * View flag indicating that the screen should remain on while the
1831      * window containing this view is visible to the user.  This effectively
1832      * takes care of automatically setting the WindowManager's
1833      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1834      */
1835     public static final int KEEP_SCREEN_ON = 0x04000000;
1836 
1837     /**
1838      * View flag indicating whether this view should have sound effects enabled
1839      * for events such as clicking and touching.
1840      */
1841     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1842 
1843     /**
1844      * View flag indicating whether this view should have haptic feedback
1845      * enabled for events such as long presses.
1846      */
1847     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1848 
1849     /**
1850      * <p>Indicates that the view hierarchy should stop saving state when
1851      * it reaches this view.  If state saving is initiated immediately at
1852      * the view, it will be allowed.
1853      * {@hide}
1854      */
1855     static final int PARENT_SAVE_DISABLED = 0x20000000;
1856 
1857     /**
1858      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1859      * {@hide}
1860      */
1861     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1862 
1863     private static Paint sDebugPaint;
1864 
1865     /**
1866      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1867      * {@hide}
1868      */
1869     static final int TOOLTIP = 0x40000000;
1870 
1871     /** @hide */
1872     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1873             FOCUSABLES_ALL,
1874             FOCUSABLES_TOUCH_MODE
1875     })
1876     @Retention(RetentionPolicy.SOURCE)
1877     public @interface FocusableMode {}
1878 
1879     /**
1880      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1881      * should add all focusable Views regardless if they are focusable in touch mode.
1882      */
1883     public static final int FOCUSABLES_ALL = 0x00000000;
1884 
1885     /**
1886      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1887      * should add only Views focusable in touch mode.
1888      */
1889     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1890 
1891     /** @hide */
1892     @IntDef(prefix = { "FOCUS_" }, value = {
1893             FOCUS_BACKWARD,
1894             FOCUS_FORWARD,
1895             FOCUS_LEFT,
1896             FOCUS_UP,
1897             FOCUS_RIGHT,
1898             FOCUS_DOWN
1899     })
1900     @Retention(RetentionPolicy.SOURCE)
1901     public @interface FocusDirection {}
1902 
1903     /** @hide */
1904     @IntDef(prefix = { "FOCUS_" }, value = {
1905             FOCUS_LEFT,
1906             FOCUS_UP,
1907             FOCUS_RIGHT,
1908             FOCUS_DOWN
1909     })
1910     @Retention(RetentionPolicy.SOURCE)
1911     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1912 
1913     /**
1914      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1915      * item.
1916      */
1917     public static final int FOCUS_BACKWARD = 0x00000001;
1918 
1919     /**
1920      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1921      * item.
1922      */
1923     public static final int FOCUS_FORWARD = 0x00000002;
1924 
1925     /**
1926      * Use with {@link #focusSearch(int)}. Move focus to the left.
1927      */
1928     public static final int FOCUS_LEFT = 0x00000011;
1929 
1930     /**
1931      * Use with {@link #focusSearch(int)}. Move focus up.
1932      */
1933     public static final int FOCUS_UP = 0x00000021;
1934 
1935     /**
1936      * Use with {@link #focusSearch(int)}. Move focus to the right.
1937      */
1938     public static final int FOCUS_RIGHT = 0x00000042;
1939 
1940     /**
1941      * Use with {@link #focusSearch(int)}. Move focus down.
1942      */
1943     public static final int FOCUS_DOWN = 0x00000082;
1944 
1945     /**
1946      * Bits of {@link #getMeasuredWidthAndState()} and
1947      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1948      */
1949     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1950 
1951     /**
1952      * Bits of {@link #getMeasuredWidthAndState()} and
1953      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1954      */
1955     public static final int MEASURED_STATE_MASK = 0xff000000;
1956 
1957     /**
1958      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1959      * for functions that combine both width and height into a single int,
1960      * such as {@link #getMeasuredState()} and the childState argument of
1961      * {@link #resolveSizeAndState(int, int, int)}.
1962      */
1963     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1964 
1965     /**
1966      * Bit of {@link #getMeasuredWidthAndState()} and
1967      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1968      * is smaller that the space the view would like to have.
1969      */
1970     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1971 
1972     /**
1973      * Base View state sets
1974      */
1975     // Singles
1976     /**
1977      * Indicates the view has no states set. States are used with
1978      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1979      * view depending on its state.
1980      *
1981      * @see android.graphics.drawable.Drawable
1982      * @see #getDrawableState()
1983      */
1984     protected static final int[] EMPTY_STATE_SET;
1985     /**
1986      * Indicates the view is enabled. States are used with
1987      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1988      * view depending on its state.
1989      *
1990      * @see android.graphics.drawable.Drawable
1991      * @see #getDrawableState()
1992      */
1993     protected static final int[] ENABLED_STATE_SET;
1994     /**
1995      * Indicates the view is focused. States are used with
1996      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1997      * view depending on its state.
1998      *
1999      * @see android.graphics.drawable.Drawable
2000      * @see #getDrawableState()
2001      */
2002     protected static final int[] FOCUSED_STATE_SET;
2003     /**
2004      * Indicates the view is selected. States are used with
2005      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2006      * view depending on its state.
2007      *
2008      * @see android.graphics.drawable.Drawable
2009      * @see #getDrawableState()
2010      */
2011     protected static final int[] SELECTED_STATE_SET;
2012     /**
2013      * Indicates the view is pressed. States are used with
2014      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2015      * view depending on its state.
2016      *
2017      * @see android.graphics.drawable.Drawable
2018      * @see #getDrawableState()
2019      */
2020     protected static final int[] PRESSED_STATE_SET;
2021     /**
2022      * Indicates the view's window has focus. States are used with
2023      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2024      * view depending on its state.
2025      *
2026      * @see android.graphics.drawable.Drawable
2027      * @see #getDrawableState()
2028      */
2029     protected static final int[] WINDOW_FOCUSED_STATE_SET;
2030     // Doubles
2031     /**
2032      * Indicates the view is enabled and has the focus.
2033      *
2034      * @see #ENABLED_STATE_SET
2035      * @see #FOCUSED_STATE_SET
2036      */
2037     protected static final int[] ENABLED_FOCUSED_STATE_SET;
2038     /**
2039      * Indicates the view is enabled and selected.
2040      *
2041      * @see #ENABLED_STATE_SET
2042      * @see #SELECTED_STATE_SET
2043      */
2044     protected static final int[] ENABLED_SELECTED_STATE_SET;
2045     /**
2046      * Indicates the view is enabled and that its window has focus.
2047      *
2048      * @see #ENABLED_STATE_SET
2049      * @see #WINDOW_FOCUSED_STATE_SET
2050      */
2051     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
2052     /**
2053      * Indicates the view is focused and selected.
2054      *
2055      * @see #FOCUSED_STATE_SET
2056      * @see #SELECTED_STATE_SET
2057      */
2058     protected static final int[] FOCUSED_SELECTED_STATE_SET;
2059     /**
2060      * Indicates the view has the focus and that its window has the focus.
2061      *
2062      * @see #FOCUSED_STATE_SET
2063      * @see #WINDOW_FOCUSED_STATE_SET
2064      */
2065     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
2066     /**
2067      * Indicates the view is selected and that its window has the focus.
2068      *
2069      * @see #SELECTED_STATE_SET
2070      * @see #WINDOW_FOCUSED_STATE_SET
2071      */
2072     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2073     // Triples
2074     /**
2075      * Indicates the view is enabled, focused and selected.
2076      *
2077      * @see #ENABLED_STATE_SET
2078      * @see #FOCUSED_STATE_SET
2079      * @see #SELECTED_STATE_SET
2080      */
2081     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2082     /**
2083      * Indicates the view is enabled, focused and its window has the focus.
2084      *
2085      * @see #ENABLED_STATE_SET
2086      * @see #FOCUSED_STATE_SET
2087      * @see #WINDOW_FOCUSED_STATE_SET
2088      */
2089     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2090     /**
2091      * Indicates the view is enabled, selected and its window has the focus.
2092      *
2093      * @see #ENABLED_STATE_SET
2094      * @see #SELECTED_STATE_SET
2095      * @see #WINDOW_FOCUSED_STATE_SET
2096      */
2097     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2098     /**
2099      * Indicates the view is focused, selected and its window has the focus.
2100      *
2101      * @see #FOCUSED_STATE_SET
2102      * @see #SELECTED_STATE_SET
2103      * @see #WINDOW_FOCUSED_STATE_SET
2104      */
2105     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2106     /**
2107      * Indicates the view is enabled, focused, selected and its window
2108      * has the focus.
2109      *
2110      * @see #ENABLED_STATE_SET
2111      * @see #FOCUSED_STATE_SET
2112      * @see #SELECTED_STATE_SET
2113      * @see #WINDOW_FOCUSED_STATE_SET
2114      */
2115     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2116     /**
2117      * Indicates the view is pressed and its window has the focus.
2118      *
2119      * @see #PRESSED_STATE_SET
2120      * @see #WINDOW_FOCUSED_STATE_SET
2121      */
2122     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2123     /**
2124      * Indicates the view is pressed and selected.
2125      *
2126      * @see #PRESSED_STATE_SET
2127      * @see #SELECTED_STATE_SET
2128      */
2129     protected static final int[] PRESSED_SELECTED_STATE_SET;
2130     /**
2131      * Indicates the view is pressed, selected and its window has the focus.
2132      *
2133      * @see #PRESSED_STATE_SET
2134      * @see #SELECTED_STATE_SET
2135      * @see #WINDOW_FOCUSED_STATE_SET
2136      */
2137     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2138     /**
2139      * Indicates the view is pressed and focused.
2140      *
2141      * @see #PRESSED_STATE_SET
2142      * @see #FOCUSED_STATE_SET
2143      */
2144     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2145     /**
2146      * Indicates the view is pressed, focused and its window has the focus.
2147      *
2148      * @see #PRESSED_STATE_SET
2149      * @see #FOCUSED_STATE_SET
2150      * @see #WINDOW_FOCUSED_STATE_SET
2151      */
2152     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2153     /**
2154      * Indicates the view is pressed, focused and selected.
2155      *
2156      * @see #PRESSED_STATE_SET
2157      * @see #SELECTED_STATE_SET
2158      * @see #FOCUSED_STATE_SET
2159      */
2160     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2161     /**
2162      * Indicates the view is pressed, focused, selected and its window has the focus.
2163      *
2164      * @see #PRESSED_STATE_SET
2165      * @see #FOCUSED_STATE_SET
2166      * @see #SELECTED_STATE_SET
2167      * @see #WINDOW_FOCUSED_STATE_SET
2168      */
2169     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2170     /**
2171      * Indicates the view is pressed and enabled.
2172      *
2173      * @see #PRESSED_STATE_SET
2174      * @see #ENABLED_STATE_SET
2175      */
2176     protected static final int[] PRESSED_ENABLED_STATE_SET;
2177     /**
2178      * Indicates the view is pressed, enabled and its window has the focus.
2179      *
2180      * @see #PRESSED_STATE_SET
2181      * @see #ENABLED_STATE_SET
2182      * @see #WINDOW_FOCUSED_STATE_SET
2183      */
2184     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2185     /**
2186      * Indicates the view is pressed, enabled and selected.
2187      *
2188      * @see #PRESSED_STATE_SET
2189      * @see #ENABLED_STATE_SET
2190      * @see #SELECTED_STATE_SET
2191      */
2192     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2193     /**
2194      * Indicates the view is pressed, enabled, selected and its window has the
2195      * focus.
2196      *
2197      * @see #PRESSED_STATE_SET
2198      * @see #ENABLED_STATE_SET
2199      * @see #SELECTED_STATE_SET
2200      * @see #WINDOW_FOCUSED_STATE_SET
2201      */
2202     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2203     /**
2204      * Indicates the view is pressed, enabled and focused.
2205      *
2206      * @see #PRESSED_STATE_SET
2207      * @see #ENABLED_STATE_SET
2208      * @see #FOCUSED_STATE_SET
2209      */
2210     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2211     /**
2212      * Indicates the view is pressed, enabled, focused and its window has the
2213      * focus.
2214      *
2215      * @see #PRESSED_STATE_SET
2216      * @see #ENABLED_STATE_SET
2217      * @see #FOCUSED_STATE_SET
2218      * @see #WINDOW_FOCUSED_STATE_SET
2219      */
2220     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2221     /**
2222      * Indicates the view is pressed, enabled, focused and selected.
2223      *
2224      * @see #PRESSED_STATE_SET
2225      * @see #ENABLED_STATE_SET
2226      * @see #SELECTED_STATE_SET
2227      * @see #FOCUSED_STATE_SET
2228      */
2229     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2230     /**
2231      * Indicates the view is pressed, enabled, focused, selected and its window
2232      * has the focus.
2233      *
2234      * @see #PRESSED_STATE_SET
2235      * @see #ENABLED_STATE_SET
2236      * @see #SELECTED_STATE_SET
2237      * @see #FOCUSED_STATE_SET
2238      * @see #WINDOW_FOCUSED_STATE_SET
2239      */
2240     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2241 
2242     static {
2243         EMPTY_STATE_SET = StateSet.get(0);
2244 
2245         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2246 
2247         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2248         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2249                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2250 
2251         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2252         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2253                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2254         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2255                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2256         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2257                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2258                         | StateSet.VIEW_STATE_FOCUSED);
2259 
2260         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2261         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2262                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2263         ENABLED_SELECTED_STATE_SET = StateSet.get(
2264                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2265         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2266                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2267                         | StateSet.VIEW_STATE_ENABLED);
2268         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2269                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2270         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2271                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2272                         | StateSet.VIEW_STATE_ENABLED);
2273         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2274                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2275                         | StateSet.VIEW_STATE_ENABLED);
2276         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2277                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2278                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2279 
2280         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2281         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2282                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2283         PRESSED_SELECTED_STATE_SET = StateSet.get(
2284                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2285         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2286                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2287                         | StateSet.VIEW_STATE_PRESSED);
2288         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2289                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2290         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2291                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2292                         | StateSet.VIEW_STATE_PRESSED);
2293         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2294                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2295                         | StateSet.VIEW_STATE_PRESSED);
2296         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2297                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2298                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2299         PRESSED_ENABLED_STATE_SET = StateSet.get(
2300                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2301         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2302                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2303                         | StateSet.VIEW_STATE_PRESSED);
2304         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2305                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2306                         | StateSet.VIEW_STATE_PRESSED);
2307         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2308                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2309                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2310         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2311                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2312                         | StateSet.VIEW_STATE_PRESSED);
2313         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2314                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2315                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2316         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2317                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2318                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2319         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2320                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2321                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2322                         | StateSet.VIEW_STATE_PRESSED);
2323     }
2324 
2325     /**
2326      * Accessibility event types that are dispatched for text population.
2327      */
2328     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2329             AccessibilityEvent.TYPE_VIEW_CLICKED
2330             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2331             | AccessibilityEvent.TYPE_VIEW_SELECTED
2332             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2333             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2334             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2335             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2336             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2337             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2338             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2339             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2340 
2341     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2342 
2343     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2344 
2345     /**
2346      * Temporary Rect currently for use in setBackground().  This will probably
2347      * be extended in the future to hold our own class with more than just
2348      * a Rect. :)
2349      */
2350     static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
2351 
2352     /**
2353      * Map used to store views' tags.
2354      */
2355     @UnsupportedAppUsage
2356     private SparseArray<Object> mKeyedTags;
2357 
2358     /**
2359      * The next available accessibility id.
2360      */
2361     private static int sNextAccessibilityViewId;
2362 
2363     /**
2364      * The animation currently associated with this view.
2365      * @hide
2366      */
2367     protected Animation mCurrentAnimation = null;
2368 
2369     /**
2370      * Width as measured during measure pass.
2371      * {@hide}
2372      */
2373     @ViewDebug.ExportedProperty(category = "measurement")
2374     @UnsupportedAppUsage
2375     int mMeasuredWidth;
2376 
2377     /**
2378      * Height as measured during measure pass.
2379      * {@hide}
2380      */
2381     @ViewDebug.ExportedProperty(category = "measurement")
2382     @UnsupportedAppUsage
2383     int mMeasuredHeight;
2384 
2385     /**
2386      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2387      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2388      * its display list. This flag, used only when hw accelerated, allows us to clear the
2389      * flag while retaining this information until it's needed (at getDisplayList() time and
2390      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2391      *
2392      * {@hide}
2393      */
2394     @UnsupportedAppUsage
2395     boolean mRecreateDisplayList = false;
2396 
2397     /**
2398      * The view's identifier.
2399      * {@hide}
2400      *
2401      * @see #setId(int)
2402      * @see #getId()
2403      */
2404     @IdRes
2405     @ViewDebug.ExportedProperty(resolveId = true)
2406     int mID = NO_ID;
2407 
2408     /** The ID of this view for autofill purposes.
2409      * <ul>
2410      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2411      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2412      *                                                  unique in the process. This might change
2413      *                                                  over activity lifecycle events.
2414      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2415      *                                                  unique in the activity. This stays the same
2416      *                                                  over activity lifecycle events.
2417      */
2418     private int mAutofillViewId = NO_ID;
2419 
2420     // ID for accessibility purposes. This ID must be unique for every window
2421     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2422     private int mAccessibilityViewId = NO_ID;
2423 
2424     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2425 
2426     /**
2427      * The view's tag.
2428      * {@hide}
2429      *
2430      * @see #setTag(Object)
2431      * @see #getTag()
2432      */
2433     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2434     protected Object mTag = null;
2435 
2436     /*
2437      * Masks for mPrivateFlags, as generated by dumpFlags():
2438      *
2439      * |-------|-------|-------|-------|
2440      *                                 1 PFLAG_WANTS_FOCUS
2441      *                                1  PFLAG_FOCUSED
2442      *                               1   PFLAG_SELECTED
2443      *                              1    PFLAG_IS_ROOT_NAMESPACE
2444      *                             1     PFLAG_HAS_BOUNDS
2445      *                            1      PFLAG_DRAWN
2446      *                           1       PFLAG_DRAW_ANIMATION
2447      *                          1        PFLAG_SKIP_DRAW
2448      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2449      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2450      *                      1            PFLAG_MEASURED_DIMENSION_SET
2451      *                     1             PFLAG_FORCE_LAYOUT
2452      *                    1              PFLAG_LAYOUT_REQUIRED
2453      *                   1               PFLAG_PRESSED
2454      *                  1                PFLAG_DRAWING_CACHE_VALID
2455      *                 1                 PFLAG_ANIMATION_STARTED
2456      *                1                  PFLAG_SAVE_STATE_CALLED
2457      *               1                   PFLAG_ALPHA_SET
2458      *              1                    PFLAG_SCROLL_CONTAINER
2459      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2460      *            1                      PFLAG_DIRTY
2461      *            1                      PFLAG_DIRTY_MASK
2462      *          1                        PFLAG_OPAQUE_BACKGROUND
2463      *         1                         PFLAG_OPAQUE_SCROLLBARS
2464      *         11                        PFLAG_OPAQUE_MASK
2465      *        1                          PFLAG_PREPRESSED
2466      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2467      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2468      *     1                             PFLAG_HOVERED
2469      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2470      *   1                               PFLAG_ACTIVATED
2471      *  1                                PFLAG_INVALIDATED
2472      * |-------|-------|-------|-------|
2473      */
2474     /** {@hide} */
2475     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2476     /** {@hide} */
2477     static final int PFLAG_FOCUSED                     = 0x00000002;
2478     /** {@hide} */
2479     static final int PFLAG_SELECTED                    = 0x00000004;
2480     /** {@hide} */
2481     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2482     /** {@hide} */
2483     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2484     /** {@hide} */
2485     static final int PFLAG_DRAWN                       = 0x00000020;
2486     /**
2487      * When this flag is set, this view is running an animation on behalf of its
2488      * children and should therefore not cancel invalidate requests, even if they
2489      * lie outside of this view's bounds.
2490      *
2491      * {@hide}
2492      */
2493     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2494     /** {@hide} */
2495     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2496     /** {@hide} */
2497     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2498     /** {@hide} */
2499     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2500     /** {@hide} */
2501     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2502     /** {@hide} */
2503     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2504     /** {@hide} */
2505     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2506 
2507     private static final int PFLAG_PRESSED             = 0x00004000;
2508 
2509     /** {@hide} */
2510     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2511     /**
2512      * Flag used to indicate that this view should be drawn once more (and only once
2513      * more) after its animation has completed.
2514      * {@hide}
2515      */
2516     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2517 
2518     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2519 
2520     /**
2521      * Indicates that the View returned true when onSetAlpha() was called and that
2522      * the alpha must be restored.
2523      * {@hide}
2524      */
2525     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2526 
2527     /**
2528      * Set by {@link #setScrollContainer(boolean)}.
2529      */
2530     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2531 
2532     /**
2533      * Set by {@link #setScrollContainer(boolean)}.
2534      */
2535     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2536 
2537     /**
2538      * View flag indicating whether this view was invalidated (fully or partially.)
2539      *
2540      * @hide
2541      */
2542     static final int PFLAG_DIRTY                       = 0x00200000;
2543 
2544     /**
2545      * Mask for {@link #PFLAG_DIRTY}.
2546      *
2547      * @hide
2548      */
2549     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2550 
2551     /**
2552      * Indicates whether the background is opaque.
2553      *
2554      * @hide
2555      */
2556     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2557 
2558     /**
2559      * Indicates whether the scrollbars are opaque.
2560      *
2561      * @hide
2562      */
2563     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2564 
2565     /**
2566      * Indicates whether the view is opaque.
2567      *
2568      * @hide
2569      */
2570     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2571 
2572     /**
2573      * Indicates a prepressed state;
2574      * the short time between ACTION_DOWN and recognizing
2575      * a 'real' press. Prepressed is used to recognize quick taps
2576      * even when they are shorter than ViewConfiguration.getTapTimeout().
2577      *
2578      * @hide
2579      */
2580     private static final int PFLAG_PREPRESSED          = 0x02000000;
2581 
2582     /**
2583      * Indicates whether the view is temporarily detached.
2584      *
2585      * @hide
2586      */
2587     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2588 
2589     /**
2590      * Indicates that we should awaken scroll bars once attached
2591      *
2592      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2593      * during window attachment and it is no longer needed. Feel free to repurpose it.
2594      *
2595      * @hide
2596      */
2597     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2598 
2599     /**
2600      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2601      * @hide
2602      */
2603     private static final int PFLAG_HOVERED             = 0x10000000;
2604 
2605     /**
2606      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2607      */
2608     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2609 
2610     /** {@hide} */
2611     static final int PFLAG_ACTIVATED                   = 0x40000000;
2612 
2613     /**
2614      * Indicates that this view was specifically invalidated, not just dirtied because some
2615      * child view was invalidated. The flag is used to determine when we need to recreate
2616      * a view's display list (as opposed to just returning a reference to its existing
2617      * display list).
2618      *
2619      * @hide
2620      */
2621     static final int PFLAG_INVALIDATED                 = 0x80000000;
2622 
2623     /* End of masks for mPrivateFlags */
2624 
2625     /*
2626      * Masks for mPrivateFlags2, as generated by dumpFlags():
2627      *
2628      * |-------|-------|-------|-------|
2629      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2630      *                                1  PFLAG2_DRAG_HOVERED
2631      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2632      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2633      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2634      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2635      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2636      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2637      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2638      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2639      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2640      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2641      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2642      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2643      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2644      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2645      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2646      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2647      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2648      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2649      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2650      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2651      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2652      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2653      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2654      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2655      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2656      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2657      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2658      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2659      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2660      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2661      *    1                              PFLAG2_PADDING_RESOLVED
2662      *   1                               PFLAG2_DRAWABLE_RESOLVED
2663      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2664      * |-------|-------|-------|-------|
2665      */
2666 
2667     /**
2668      * Indicates that this view has reported that it can accept the current drag's content.
2669      * Cleared when the drag operation concludes.
2670      * @hide
2671      */
2672     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2673 
2674     /**
2675      * Indicates that this view is currently directly under the drag location in a
2676      * drag-and-drop operation involving content that it can accept.  Cleared when
2677      * the drag exits the view, or when the drag operation concludes.
2678      * @hide
2679      */
2680     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2681 
2682     /** @hide */
2683     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2684             LAYOUT_DIRECTION_LTR,
2685             LAYOUT_DIRECTION_RTL,
2686             LAYOUT_DIRECTION_INHERIT,
2687             LAYOUT_DIRECTION_LOCALE
2688     })
2689     @Retention(RetentionPolicy.SOURCE)
2690     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2691     public @interface LayoutDir {}
2692 
2693     /** @hide */
2694     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2695             LAYOUT_DIRECTION_LTR,
2696             LAYOUT_DIRECTION_RTL
2697     })
2698     @Retention(RetentionPolicy.SOURCE)
2699     public @interface ResolvedLayoutDir {}
2700 
2701     /**
2702      * A flag to indicate that the layout direction of this view has not been defined yet.
2703      * @hide
2704      */
2705     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2706 
2707     /**
2708      * Horizontal layout direction of this view is from Left to Right.
2709      * Use with {@link #setLayoutDirection}.
2710      */
2711     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2712 
2713     /**
2714      * Horizontal layout direction of this view is from Right to Left.
2715      * Use with {@link #setLayoutDirection}.
2716      */
2717     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2718 
2719     /**
2720      * Horizontal layout direction of this view is inherited from its parent.
2721      * Use with {@link #setLayoutDirection}.
2722      */
2723     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2724 
2725     /**
2726      * Horizontal layout direction of this view is from deduced from the default language
2727      * script for the locale. Use with {@link #setLayoutDirection}.
2728      */
2729     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2730 
2731     /**
2732      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2733      * @hide
2734      */
2735     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2736 
2737     /**
2738      * Mask for use with private flags indicating bits used for horizontal layout direction.
2739      * @hide
2740      */
2741     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2742 
2743     /**
2744      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2745      * right-to-left direction.
2746      * @hide
2747      */
2748     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2749 
2750     /**
2751      * Indicates whether the view horizontal layout direction has been resolved.
2752      * @hide
2753      */
2754     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2755 
2756     /**
2757      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2758      * @hide
2759      */
2760     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2761             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2762 
2763     /*
2764      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2765      * flag value.
2766      * @hide
2767      */
2768     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2769             LAYOUT_DIRECTION_LTR,
2770             LAYOUT_DIRECTION_RTL,
2771             LAYOUT_DIRECTION_INHERIT,
2772             LAYOUT_DIRECTION_LOCALE
2773     };
2774 
2775     /**
2776      * Default horizontal layout direction.
2777      */
2778     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2779 
2780     /**
2781      * Default horizontal layout direction.
2782      * @hide
2783      */
2784     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2785 
2786     /**
2787      * Text direction is inherited through {@link ViewGroup}
2788      */
2789     public static final int TEXT_DIRECTION_INHERIT = 0;
2790 
2791     /**
2792      * Text direction is using "first strong algorithm". The first strong directional character
2793      * determines the paragraph direction. If there is no strong directional character, the
2794      * paragraph direction is the view's resolved layout direction.
2795      */
2796     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2797 
2798     /**
2799      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2800      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2801      * If there are neither, the paragraph direction is the view's resolved layout direction.
2802      */
2803     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2804 
2805     /**
2806      * Text direction is forced to LTR.
2807      */
2808     public static final int TEXT_DIRECTION_LTR = 3;
2809 
2810     /**
2811      * Text direction is forced to RTL.
2812      */
2813     public static final int TEXT_DIRECTION_RTL = 4;
2814 
2815     /**
2816      * Text direction is coming from the system Locale.
2817      */
2818     public static final int TEXT_DIRECTION_LOCALE = 5;
2819 
2820     /**
2821      * Text direction is using "first strong algorithm". The first strong directional character
2822      * determines the paragraph direction. If there is no strong directional character, the
2823      * paragraph direction is LTR.
2824      */
2825     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2826 
2827     /**
2828      * Text direction is using "first strong algorithm". The first strong directional character
2829      * determines the paragraph direction. If there is no strong directional character, the
2830      * paragraph direction is RTL.
2831      */
2832     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2833 
2834     /**
2835      * Default text direction is inherited
2836      */
2837     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2838 
2839     /**
2840      * Default resolved text direction
2841      * @hide
2842      */
2843     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2844 
2845     /**
2846      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2847      * @hide
2848      */
2849     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2850 
2851     /**
2852      * Mask for use with private flags indicating bits used for text direction.
2853      * @hide
2854      */
2855     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2856             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2857 
2858     /**
2859      * Array of text direction flags for mapping attribute "textDirection" to correct
2860      * flag value.
2861      * @hide
2862      */
2863     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2864             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2865             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2866             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2867             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2868             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2869             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2870             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2871             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2872     };
2873 
2874     /**
2875      * Indicates whether the view text direction has been resolved.
2876      * @hide
2877      */
2878     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2879             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2880 
2881     /**
2882      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2883      * @hide
2884      */
2885     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2886 
2887     /**
2888      * Mask for use with private flags indicating bits used for resolved text direction.
2889      * @hide
2890      */
2891     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2892             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2893 
2894     /**
2895      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2896      * @hide
2897      */
2898     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2899             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2900 
2901     /** @hide */
2902     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2903             TEXT_ALIGNMENT_INHERIT,
2904             TEXT_ALIGNMENT_GRAVITY,
2905             TEXT_ALIGNMENT_CENTER,
2906             TEXT_ALIGNMENT_TEXT_START,
2907             TEXT_ALIGNMENT_TEXT_END,
2908             TEXT_ALIGNMENT_VIEW_START,
2909             TEXT_ALIGNMENT_VIEW_END
2910     })
2911     @Retention(RetentionPolicy.SOURCE)
2912     public @interface TextAlignment {}
2913 
2914     /**
2915      * Default text alignment. The text alignment of this View is inherited from its parent.
2916      * Use with {@link #setTextAlignment(int)}
2917      */
2918     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2919 
2920     /**
2921      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2922      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
2923      *
2924      * Use with {@link #setTextAlignment(int)}
2925      */
2926     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2927 
2928     /**
2929      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2930      *
2931      * Use with {@link #setTextAlignment(int)}
2932      */
2933     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2934 
2935     /**
2936      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2937      *
2938      * Use with {@link #setTextAlignment(int)}
2939      */
2940     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2941 
2942     /**
2943      * Center the paragraph, e.g. ALIGN_CENTER.
2944      *
2945      * Use with {@link #setTextAlignment(int)}
2946      */
2947     public static final int TEXT_ALIGNMENT_CENTER = 4;
2948 
2949     /**
2950      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
2951      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2952      *
2953      * Use with {@link #setTextAlignment(int)}
2954      */
2955     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2956 
2957     /**
2958      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
2959      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2960      *
2961      * Use with {@link #setTextAlignment(int)}
2962      */
2963     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2964 
2965     /**
2966      * Default text alignment is inherited
2967      */
2968     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2969 
2970     /**
2971      * Default resolved text alignment
2972      * @hide
2973      */
2974     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2975 
2976     /**
2977       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2978       * @hide
2979       */
2980     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2981 
2982     /**
2983       * Mask for use with private flags indicating bits used for text alignment.
2984       * @hide
2985       */
2986     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2987 
2988     /**
2989      * Array of text direction flags for mapping attribute "textAlignment" to correct
2990      * flag value.
2991      * @hide
2992      */
2993     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2994             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2995             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2996             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2997             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2998             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2999             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3000             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
3001     };
3002 
3003     /**
3004      * Indicates whether the view text alignment has been resolved.
3005      * @hide
3006      */
3007     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3008 
3009     /**
3010      * Bit shift to get the resolved text alignment.
3011      * @hide
3012      */
3013     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
3014 
3015     /**
3016      * Mask for use with private flags indicating bits used for text alignment.
3017      * @hide
3018      */
3019     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
3020             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3021 
3022     /**
3023      * Indicates whether if the view text alignment has been resolved to gravity
3024      */
3025     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
3026             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3027 
3028     // Accessiblity constants for mPrivateFlags2
3029 
3030     /**
3031      * Shift for the bits in {@link #mPrivateFlags2} related to the
3032      * "importantForAccessibility" attribute.
3033      */
3034     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
3035 
3036     /**
3037      * Automatically determine whether a view is important for accessibility.
3038      */
3039     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
3040 
3041     /**
3042      * The view is important for accessibility.
3043      */
3044     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
3045 
3046     /**
3047      * The view is not important for accessibility.
3048      */
3049     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
3050 
3051     /**
3052      * The view is not important for accessibility, nor are any of its
3053      * descendant views.
3054      */
3055     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
3056 
3057     /**
3058      * The default whether the view is important for accessibility.
3059      */
3060     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3061 
3062     /**
3063      * Mask for obtaining the bits which specify how to determine
3064      * whether a view is important for accessibility.
3065      */
3066     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
3067         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
3068         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
3069         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3070 
3071     /**
3072      * Shift for the bits in {@link #mPrivateFlags2} related to the
3073      * "accessibilityLiveRegion" attribute.
3074      */
3075     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3076 
3077     /**
3078      * Live region mode specifying that accessibility services should not
3079      * automatically announce changes to this view. This is the default live
3080      * region mode for most views.
3081      * <p>
3082      * Use with {@link #setAccessibilityLiveRegion(int)}.
3083      */
3084     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3085 
3086     /**
3087      * Live region mode specifying that accessibility services should announce
3088      * changes to this view.
3089      * <p>
3090      * Use with {@link #setAccessibilityLiveRegion(int)}.
3091      */
3092     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3093 
3094     /**
3095      * Live region mode specifying that accessibility services should interrupt
3096      * ongoing speech to immediately announce changes to this view.
3097      * <p>
3098      * Use with {@link #setAccessibilityLiveRegion(int)}.
3099      */
3100     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3101 
3102     /**
3103      * The default whether the view is important for accessibility.
3104      */
3105     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3106 
3107     /**
3108      * Mask for obtaining the bits which specify a view's accessibility live
3109      * region mode.
3110      */
3111     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3112             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3113             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3114 
3115     /**
3116      * Flag indicating whether a view has accessibility focus.
3117      */
3118     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3119 
3120     /**
3121      * Flag whether the accessibility state of the subtree rooted at this view changed.
3122      */
3123     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3124 
3125     /**
3126      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3127      * is used to check whether later changes to the view's transform should invalidate the
3128      * view to force the quickReject test to run again.
3129      */
3130     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3131 
3132     /**
3133      * Flag indicating that start/end padding has been resolved into left/right padding
3134      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3135      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3136      * during measurement. In some special cases this is required such as when an adapter-based
3137      * view measures prospective children without attaching them to a window.
3138      */
3139     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3140 
3141     /**
3142      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3143      */
3144     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3145 
3146     /**
3147      * Indicates that the view is tracking some sort of transient state
3148      * that the app should not need to be aware of, but that the framework
3149      * should take special care to preserve.
3150      */
3151     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3152 
3153     /**
3154      * Group of bits indicating that RTL properties resolution is done.
3155      */
3156     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3157             PFLAG2_TEXT_DIRECTION_RESOLVED |
3158             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3159             PFLAG2_PADDING_RESOLVED |
3160             PFLAG2_DRAWABLE_RESOLVED;
3161 
3162     // There are a couple of flags left in mPrivateFlags2
3163 
3164     /* End of masks for mPrivateFlags2 */
3165 
3166     /*
3167      * Masks for mPrivateFlags3, as generated by dumpFlags():
3168      *
3169      * |-------|-------|-------|-------|
3170      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3171      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3172      *                               1   PFLAG3_IS_LAID_OUT
3173      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3174      *                             1     PFLAG3_CALLED_SUPER
3175      *                            1      PFLAG3_APPLYING_INSETS
3176      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3177      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3178      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3179      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3180      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3181      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3182      *                     1             PFLAG3_SCROLL_INDICATOR_START
3183      *                    1              PFLAG3_SCROLL_INDICATOR_END
3184      *                   1               PFLAG3_ASSIST_BLOCKED
3185      *                  1                PFLAG3_CLUSTER
3186      *                 1                 PFLAG3_IS_AUTOFILLED
3187      *                1                  PFLAG3_FINGER_DOWN
3188      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3189      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3190      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3191      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3192      *        1                          PFLAG3_TEMPORARY_DETACH
3193      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3194      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3195      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3196      *    1                              PFLAG3_AGGREGATED_VISIBLE
3197      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3198      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3199      * |-------|-------|-------|-------|
3200      */
3201 
3202     /**
3203      * Flag indicating that view has a transform animation set on it. This is used to track whether
3204      * an animation is cleared between successive frames, in order to tell the associated
3205      * DisplayList to clear its animation matrix.
3206      */
3207     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3208 
3209     /**
3210      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3211      * animation is cleared between successive frames, in order to tell the associated
3212      * DisplayList to restore its alpha value.
3213      */
3214     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3215 
3216     /**
3217      * Flag indicating that the view has been through at least one layout since it
3218      * was last attached to a window.
3219      */
3220     static final int PFLAG3_IS_LAID_OUT = 0x4;
3221 
3222     /**
3223      * Flag indicating that a call to measure() was skipped and should be done
3224      * instead when layout() is invoked.
3225      */
3226     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3227 
3228     /**
3229      * Flag indicating that an overridden method correctly called down to
3230      * the superclass implementation as required by the API spec.
3231      */
3232     static final int PFLAG3_CALLED_SUPER = 0x10;
3233 
3234     /**
3235      * Flag indicating that we're in the process of applying window insets.
3236      */
3237     static final int PFLAG3_APPLYING_INSETS = 0x20;
3238 
3239     /**
3240      * Flag indicating that we're in the process of fitting system windows using the old method.
3241      */
3242     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3243 
3244     /**
3245      * Flag indicating that nested scrolling is enabled for this view.
3246      * The view will optionally cooperate with views up its parent chain to allow for
3247      * integrated nested scrolling along the same axis.
3248      */
3249     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3250 
3251     /**
3252      * Flag indicating that the bottom scroll indicator should be displayed
3253      * when this view can scroll up.
3254      */
3255     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3256 
3257     /**
3258      * Flag indicating that the bottom scroll indicator should be displayed
3259      * when this view can scroll down.
3260      */
3261     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3262 
3263     /**
3264      * Flag indicating that the left scroll indicator should be displayed
3265      * when this view can scroll left.
3266      */
3267     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3268 
3269     /**
3270      * Flag indicating that the right scroll indicator should be displayed
3271      * when this view can scroll right.
3272      */
3273     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3274 
3275     /**
3276      * Flag indicating that the start scroll indicator should be displayed
3277      * when this view can scroll in the start direction.
3278      */
3279     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3280 
3281     /**
3282      * Flag indicating that the end scroll indicator should be displayed
3283      * when this view can scroll in the end direction.
3284      */
3285     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3286 
3287     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3288 
3289     static final int SCROLL_INDICATORS_NONE = 0x0000;
3290 
3291     /**
3292      * Mask for use with setFlags indicating bits used for indicating which
3293      * scroll indicators are enabled.
3294      */
3295     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3296             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3297             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3298             | PFLAG3_SCROLL_INDICATOR_END;
3299 
3300     /**
3301      * Left-shift required to translate between public scroll indicator flags
3302      * and internal PFLAGS3 flags. When used as a right-shift, translates
3303      * PFLAGS3 flags to public flags.
3304      */
3305     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3306 
3307     /** @hide */
3308     @Retention(RetentionPolicy.SOURCE)
3309     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3310             SCROLL_INDICATOR_TOP,
3311             SCROLL_INDICATOR_BOTTOM,
3312             SCROLL_INDICATOR_LEFT,
3313             SCROLL_INDICATOR_RIGHT,
3314             SCROLL_INDICATOR_START,
3315             SCROLL_INDICATOR_END,
3316     })
3317     public @interface ScrollIndicators {}
3318 
3319     /**
3320      * Scroll indicator direction for the top edge of the view.
3321      *
3322      * @see #setScrollIndicators(int)
3323      * @see #setScrollIndicators(int, int)
3324      * @see #getScrollIndicators()
3325      */
3326     public static final int SCROLL_INDICATOR_TOP =
3327             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3328 
3329     /**
3330      * Scroll indicator direction for the bottom edge of the view.
3331      *
3332      * @see #setScrollIndicators(int)
3333      * @see #setScrollIndicators(int, int)
3334      * @see #getScrollIndicators()
3335      */
3336     public static final int SCROLL_INDICATOR_BOTTOM =
3337             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3338 
3339     /**
3340      * Scroll indicator direction for the left edge of the view.
3341      *
3342      * @see #setScrollIndicators(int)
3343      * @see #setScrollIndicators(int, int)
3344      * @see #getScrollIndicators()
3345      */
3346     public static final int SCROLL_INDICATOR_LEFT =
3347             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3348 
3349     /**
3350      * Scroll indicator direction for the right edge of the view.
3351      *
3352      * @see #setScrollIndicators(int)
3353      * @see #setScrollIndicators(int, int)
3354      * @see #getScrollIndicators()
3355      */
3356     public static final int SCROLL_INDICATOR_RIGHT =
3357             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3358 
3359     /**
3360      * Scroll indicator direction for the starting edge of the view.
3361      * <p>
3362      * Resolved according to the view's layout direction, see
3363      * {@link #getLayoutDirection()} for more information.
3364      *
3365      * @see #setScrollIndicators(int)
3366      * @see #setScrollIndicators(int, int)
3367      * @see #getScrollIndicators()
3368      */
3369     public static final int SCROLL_INDICATOR_START =
3370             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3371 
3372     /**
3373      * Scroll indicator direction for the ending edge of the view.
3374      * <p>
3375      * Resolved according to the view's layout direction, see
3376      * {@link #getLayoutDirection()} for more information.
3377      *
3378      * @see #setScrollIndicators(int)
3379      * @see #setScrollIndicators(int, int)
3380      * @see #getScrollIndicators()
3381      */
3382     public static final int SCROLL_INDICATOR_END =
3383             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3384 
3385     /**
3386      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3387      * into this view.<p>
3388      */
3389     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3390 
3391     /**
3392      * Flag indicating that the view is a root of a keyboard navigation cluster.
3393      *
3394      * @see #isKeyboardNavigationCluster()
3395      * @see #setKeyboardNavigationCluster(boolean)
3396      */
3397     private static final int PFLAG3_CLUSTER = 0x8000;
3398 
3399     /**
3400      * Flag indicating that the view is autofilled
3401      *
3402      * @see #isAutofilled()
3403      * @see #setAutofilled(boolean, boolean)
3404      */
3405     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3406 
3407     /**
3408      * Indicates that the user is currently touching the screen.
3409      * Currently used for the tooltip positioning only.
3410      */
3411     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3412 
3413     /**
3414      * Flag indicating that this view is the default-focus view.
3415      *
3416      * @see #isFocusedByDefault()
3417      * @see #setFocusedByDefault(boolean)
3418      */
3419     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3420 
3421     /**
3422      * Shift for the bits in {@link #mPrivateFlags3} related to the
3423      * "importantForAutofill" attribute.
3424      */
3425     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3426 
3427     /**
3428      * Mask for obtaining the bits which specify how to determine
3429      * whether a view is important for autofill.
3430      */
3431     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3432             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3433             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3434             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3435             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3436 
3437     /**
3438      * Whether this view has rendered elements that overlap (see {@link
3439      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3440      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3441      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3442      * determined by whatever {@link #hasOverlappingRendering()} returns.
3443      */
3444     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3445 
3446     /**
3447      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3448      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3449      */
3450     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3451 
3452     /**
3453      * Flag indicating that the view is temporarily detached from the parent view.
3454      *
3455      * @see #onStartTemporaryDetach()
3456      * @see #onFinishTemporaryDetach()
3457      */
3458     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3459 
3460     /**
3461      * Flag indicating that the view does not wish to be revealed within its parent
3462      * hierarchy when it gains focus. Expressed in the negative since the historical
3463      * default behavior is to reveal on focus; this flag suppresses that behavior.
3464      *
3465      * @see #setRevealOnFocusHint(boolean)
3466      * @see #getRevealOnFocusHint()
3467      */
3468     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3469 
3470     /**
3471      * Flag indicating that when layout is completed we should notify
3472      * that the view was entered for autofill purposes. To minimize
3473      * showing autofill for views not visible to the user we evaluate
3474      * user visibility which cannot be done until the view is laid out.
3475      */
3476     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3477 
3478     /**
3479      * Works like focusable for screen readers, but without the side effects on input focus.
3480      * @see #setScreenReaderFocusable(boolean)
3481      */
3482     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3483 
3484     /**
3485      * The last aggregated visibility. Used to detect when it truly changes.
3486      */
3487     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3488 
3489     /**
3490      * Used to indicate that {@link #mAutofillId} was explicitly set through
3491      * {@link #setAutofillId(AutofillId)}.
3492      */
3493     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3494 
3495     /**
3496      * Indicates if the View is a heading for accessibility purposes
3497      */
3498     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3499 
3500     /* End of masks for mPrivateFlags3 */
3501 
3502     /*
3503      * Masks for mPrivateFlags4, as generated by dumpFlags():
3504      *
3505      * |-------|-------|-------|-------|
3506      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3507      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3508      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3509      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3510      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3511      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3512      *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
3513      *                       1          PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
3514      *                     11           PFLAG4_SCROLL_CAPTURE_HINT_MASK
3515      *                    1             PFLAG4_ALLOW_CLICK_WHEN_DISABLED
3516      *                   1              PFLAG4_DETACHED
3517      *                  1               PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
3518      *                 1                PFLAG4_DRAG_A11Y_STARTED
3519      * |-------|-------|-------|-------|
3520      */
3521 
3522     /**
3523      * Mask for obtaining the bits which specify how to determine
3524      * whether a view is important for autofill.
3525      *
3526      * <p>NOTE: the important for content capture values were the first flags added and are set in
3527      * the rightmost position, so we don't need to shift them
3528      */
3529     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3530             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3531             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3532             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3533             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3534 
3535     /*
3536      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3537      * should be called.
3538      *
3539      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3540      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3541      */
3542     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3543     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3544 
3545     /*
3546      * Flags used to cache the value returned by isImportantForContentCapture while the view
3547      * hierarchy is being traversed.
3548      */
3549     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3550     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3551 
3552     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3553             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3554             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3555 
3556     /**
3557      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3558      */
3559     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3560 
3561     /**
3562      * Flag indicating the field should not have yellow highlight when autofilled.
3563      */
3564     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3565 
3566     /**
3567      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3568      */
3569     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3570 
3571     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3572             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3573             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3574 
3575     /**
3576      * Indicates if the view can receive click events when disabled.
3577      */
3578     private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
3579 
3580     /**
3581      * Indicates if the view is just detached.
3582      */
3583     private static final int PFLAG4_DETACHED = 0x000002000;
3584 
3585     /**
3586      * Indicates that the view has transient state because the system is translating it.
3587      */
3588     private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
3589 
3590     /**
3591      * Indicates that the view has started a drag with {@link AccessibilityAction#ACTION_DRAG_START}
3592      */
3593     private static final int PFLAG4_DRAG_A11Y_STARTED = 0x000008000;
3594 
3595     /* End of masks for mPrivateFlags4 */
3596 
3597     /** @hide */
3598     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3599     /** @hide */
3600     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3601     /** @hide */
3602     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3603 
3604     /** @hide */
3605     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3606             VIEW_STRUCTURE_FOR_ASSIST,
3607             VIEW_STRUCTURE_FOR_AUTOFILL,
3608             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3609     })
3610     @Retention(RetentionPolicy.SOURCE)
3611     public @interface ViewStructureType {}
3612 
3613     /**
3614      * Always allow a user to over-scroll this view, provided it is a
3615      * view that can scroll.
3616      *
3617      * @see #getOverScrollMode()
3618      * @see #setOverScrollMode(int)
3619      */
3620     public static final int OVER_SCROLL_ALWAYS = 0;
3621 
3622     /**
3623      * Allow a user to over-scroll this view only if the content is large
3624      * enough to meaningfully scroll, provided it is a view that can scroll.
3625      *
3626      * @see #getOverScrollMode()
3627      * @see #setOverScrollMode(int)
3628      */
3629     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3630 
3631     /**
3632      * Never allow a user to over-scroll this view.
3633      *
3634      * @see #getOverScrollMode()
3635      * @see #setOverScrollMode(int)
3636      */
3637     public static final int OVER_SCROLL_NEVER = 2;
3638 
3639     /**
3640      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3641      * requested the system UI (status bar) to be visible (the default).
3642      *
3643      * @see #setSystemUiVisibility(int)
3644      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
3645      * instead.
3646      */
3647     @Deprecated
3648     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3649 
3650     /**
3651      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3652      * system UI to enter an unobtrusive "low profile" mode.
3653      *
3654      * <p>This is for use in games, book readers, video players, or any other
3655      * "immersive" application where the usual system chrome is deemed too distracting.
3656      *
3657      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3658      *
3659      * @see #setSystemUiVisibility(int)
3660      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
3661      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
3662      * {@link Type#systemBars()}.
3663      */
3664     @Deprecated
3665     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3666 
3667     /**
3668      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3669      * system navigation be temporarily hidden.
3670      *
3671      * <p>This is an even less obtrusive state than that called for by
3672      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3673      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3674      * those to disappear. This is useful (in conjunction with the
3675      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3676      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3677      * window flags) for displaying content using every last pixel on the display.
3678      *
3679      * <p>There is a limitation: because navigation controls are so important, the least user
3680      * interaction will cause them to reappear immediately.  When this happens, both
3681      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3682      * so that both elements reappear at the same time.
3683      *
3684      * @see #setSystemUiVisibility(int)
3685      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
3686      * instead.
3687      */
3688     @Deprecated
3689     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3690 
3691     /**
3692      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3693      * into the normal fullscreen mode so that its content can take over the screen
3694      * while still allowing the user to interact with the application.
3695      *
3696      * <p>This has the same visual effect as
3697      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3698      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3699      * meaning that non-critical screen decorations (such as the status bar) will be
3700      * hidden while the user is in the View's window, focusing the experience on
3701      * that content.  Unlike the window flag, if you are using ActionBar in
3702      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3703      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3704      * hide the action bar.
3705      *
3706      * <p>This approach to going fullscreen is best used over the window flag when
3707      * it is a transient state -- that is, the application does this at certain
3708      * points in its user interaction where it wants to allow the user to focus
3709      * on content, but not as a continuous state.  For situations where the application
3710      * would like to simply stay full screen the entire time (such as a game that
3711      * wants to take over the screen), the
3712      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3713      * is usually a better approach.  The state set here will be removed by the system
3714      * in various situations (such as the user moving to another application) like
3715      * the other system UI states.
3716      *
3717      * <p>When using this flag, the application should provide some easy facility
3718      * for the user to go out of it.  A common example would be in an e-book
3719      * reader, where tapping on the screen brings back whatever screen and UI
3720      * decorations that had been hidden while the user was immersed in reading
3721      * the book.
3722      *
3723      * @see #setSystemUiVisibility(int)
3724      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
3725      * instead.
3726      */
3727     @Deprecated
3728     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3729 
3730     /**
3731      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3732      * flags, we would like a stable view of the content insets given to
3733      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3734      * will always represent the worst case that the application can expect
3735      * as a continuous state.  In the stock Android UI this is the space for
3736      * the system bar, nav bar, and status bar, but not more transient elements
3737      * such as an input method.
3738      *
3739      * The stable layout your UI sees is based on the system UI modes you can
3740      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3741      * then you will get a stable layout for changes of the
3742      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3743      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3744      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3745      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3746      * with a stable layout.  (Note that you should avoid using
3747      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3748      *
3749      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3750      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3751      * then a hidden status bar will be considered a "stable" state for purposes
3752      * here.  This allows your UI to continually hide the status bar, while still
3753      * using the system UI flags to hide the action bar while still retaining
3754      * a stable layout.  Note that changing the window fullscreen flag will never
3755      * provide a stable layout for a clean transition.
3756      *
3757      * <p>If you are using ActionBar in
3758      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3759      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3760      * insets it adds to those given to the application.
3761      *
3762      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
3763      * insets that don't change when system bars change visibility state.
3764      */
3765     @Deprecated
3766     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3767 
3768     /**
3769      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3770      * to be laid out as if it has requested
3771      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3772      * allows it to avoid artifacts when switching in and out of that mode, at
3773      * the expense that some of its user interface may be covered by screen
3774      * decorations when they are shown.  You can perform layout of your inner
3775      * UI elements to account for the navigation system UI through the
3776      * {@link #fitSystemWindows(Rect)} method.
3777      *
3778      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3779      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
3780      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3781      */
3782     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3783 
3784     /**
3785      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3786      * to be laid out as if it has requested
3787      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3788      * allows it to avoid artifacts when switching in and out of that mode, at
3789      * the expense that some of its user interface may be covered by screen
3790      * decorations when they are shown.  You can perform layout of your inner
3791      * UI elements to account for non-fullscreen system UI through the
3792      * {@link #fitSystemWindows(Rect)} method.
3793      *
3794      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3795      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3796      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3797      *  layoutInDisplayCutoutMode} is
3798      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3799      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3800      *
3801      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3802      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3803      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3804      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3805      *
3806      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3807      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
3808      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3809      */
3810     @Deprecated
3811     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3812 
3813     /**
3814      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3815      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3816      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3817      * user interaction.
3818      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3819      * has an effect when used in combination with that flag.</p>
3820      *
3821      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_DEFAULT} instead.
3822      */
3823     @Deprecated
3824     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3825 
3826     /**
3827      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3828      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3829      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3830      * experience while also hiding the system bars.  If this flag is not set,
3831      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3832      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3833      * if the user swipes from the top of the screen.
3834      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3835      * system gestures, such as swiping from the top of the screen.  These transient system bars
3836      * will overlay app's content, may have some degree of transparency, and will automatically
3837      * hide after a short timeout.
3838      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3839      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3840      * with one or both of those flags.</p>
3841      *
3842      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
3843      */
3844     @Deprecated
3845     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3846 
3847     /**
3848      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3849      * is compatible with light status bar backgrounds.
3850      *
3851      * <p>For this to take effect, the window must request
3852      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3853      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3854      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3855      *         FLAG_TRANSLUCENT_STATUS}.
3856      *
3857      * @see android.R.attr#windowLightStatusBar
3858      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
3859      */
3860     @Deprecated
3861     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3862 
3863     /**
3864      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3865      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3866      */
3867     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3868 
3869     /**
3870      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3871      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3872      */
3873     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3874 
3875     /**
3876      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3877      * that is compatible with light navigation bar backgrounds.
3878      *
3879      * <p>For this to take effect, the window must request
3880      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3881      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3882      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3883      *         FLAG_TRANSLUCENT_NAVIGATION}.
3884      *
3885      * @see android.R.attr#windowLightNavigationBar
3886      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
3887      */
3888     @Deprecated
3889     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3890 
3891     /**
3892      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3893      */
3894     @Deprecated
3895     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3896 
3897     /**
3898      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3899      */
3900     @Deprecated
3901     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3902 
3903     /**
3904      * @hide
3905      *
3906      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3907      * out of the public fields to keep the undefined bits out of the developer's way.
3908      *
3909      * Flag to make the status bar not expandable.  Unless you also
3910      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3911      */
3912     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3913     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3914 
3915     /**
3916      * @hide
3917      *
3918      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3919      * out of the public fields to keep the undefined bits out of the developer's way.
3920      *
3921      * Flag to hide notification icons and scrolling ticker text.
3922      */
3923     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3924 
3925     /**
3926      * @hide
3927      *
3928      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3929      * out of the public fields to keep the undefined bits out of the developer's way.
3930      *
3931      * Flag to disable incoming notification alerts.  This will not block
3932      * icons, but it will block sound, vibrating and other visual or aural notifications.
3933      */
3934     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3935 
3936     /**
3937      * @hide
3938      *
3939      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3940      * out of the public fields to keep the undefined bits out of the developer's way.
3941      *
3942      * Flag to hide only the scrolling ticker.  Note that
3943      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3944      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3945      */
3946     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3947 
3948     /**
3949      * @hide
3950      *
3951      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3952      * out of the public fields to keep the undefined bits out of the developer's way.
3953      *
3954      * Flag to hide the center system info area.
3955      */
3956     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3957 
3958     /**
3959      * @hide
3960      *
3961      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3962      * out of the public fields to keep the undefined bits out of the developer's way.
3963      *
3964      * Flag to hide only the home button.  Don't use this
3965      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3966      */
3967     @UnsupportedAppUsage
3968     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3969 
3970     /**
3971      * @hide
3972      *
3973      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3974      * out of the public fields to keep the undefined bits out of the developer's way.
3975      *
3976      * Flag to hide only the back button. Don't use this
3977      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3978      */
3979     @UnsupportedAppUsage
3980     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3981 
3982     /**
3983      * @hide
3984      *
3985      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3986      * out of the public fields to keep the undefined bits out of the developer's way.
3987      *
3988      * Flag to hide only the clock.  You might use this if your activity has
3989      * its own clock making the status bar's clock redundant.
3990      */
3991     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3992 
3993     /**
3994      * @hide
3995      *
3996      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3997      * out of the public fields to keep the undefined bits out of the developer's way.
3998      *
3999      * Flag to hide only the recent apps button. Don't use this
4000      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4001      */
4002     @UnsupportedAppUsage
4003     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
4004 
4005     /**
4006      * @hide
4007      *
4008      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4009      * out of the public fields to keep the undefined bits out of the developer's way.
4010      *
4011      * Flag to disable the global search gesture. Don't use this
4012      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4013      */
4014     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
4015 
4016     /**
4017      * @hide
4018      *
4019      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4020      * out of the public fields to keep the undefined bits out of the developer's way.
4021      *
4022      * Flag to disable the ongoing call chip.
4023      */
4024     public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
4025 
4026     /**
4027      * @hide
4028      */
4029     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4030 
4031     /**
4032      * These are the system UI flags that can be cleared by events outside
4033      * of an application.  Currently this is just the ability to tap on the
4034      * screen while hiding the navigation bar to have it return.
4035      * @hide
4036      */
4037     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4038             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4039             | SYSTEM_UI_FLAG_FULLSCREEN;
4040 
4041     /**
4042      * Flags that can impact the layout in relation to system UI.
4043      *
4044      * @deprecated System UI layout flags are deprecated.
4045      */
4046     @Deprecated
4047     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4048             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4049             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4050 
4051     /** @hide */
4052     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4053             FIND_VIEWS_WITH_TEXT,
4054             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4055     })
4056     @Retention(RetentionPolicy.SOURCE)
4057     public @interface FindViewFlags {}
4058 
4059     /**
4060      * Find views that render the specified text.
4061      *
4062      * @see #findViewsWithText(ArrayList, CharSequence, int)
4063      */
4064     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4065 
4066     /**
4067      * Find find views that contain the specified content description.
4068      *
4069      * @see #findViewsWithText(ArrayList, CharSequence, int)
4070      */
4071     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4072 
4073     /**
4074      * Find views that contain {@link AccessibilityNodeProvider}. Such
4075      * a View is a root of virtual view hierarchy and may contain the searched
4076      * text. If this flag is set Views with providers are automatically
4077      * added and it is a responsibility of the client to call the APIs of
4078      * the provider to determine whether the virtual tree rooted at this View
4079      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4080      * representing the virtual views with this text.
4081      *
4082      * @see #findViewsWithText(ArrayList, CharSequence, int)
4083      *
4084      * @hide
4085      */
4086     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4087 
4088     /**
4089      * The undefined cursor position.
4090      *
4091      * @hide
4092      */
4093     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4094 
4095     /**
4096      * Indicates that the screen has changed state and is now off.
4097      *
4098      * @see #onScreenStateChanged(int)
4099      */
4100     public static final int SCREEN_STATE_OFF = 0x0;
4101 
4102     /**
4103      * Indicates that the screen has changed state and is now on.
4104      *
4105      * @see #onScreenStateChanged(int)
4106      */
4107     public static final int SCREEN_STATE_ON = 0x1;
4108 
4109     /**
4110      * Indicates no axis of view scrolling.
4111      */
4112     public static final int SCROLL_AXIS_NONE = 0;
4113 
4114     /**
4115      * Indicates scrolling along the horizontal axis.
4116      */
4117     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4118 
4119     /**
4120      * Indicates scrolling along the vertical axis.
4121      */
4122     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4123 
4124     /**
4125      * Controls the over-scroll mode for this view.
4126      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4127      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4128      * and {@link #OVER_SCROLL_NEVER}.
4129      */
4130     private int mOverScrollMode;
4131 
4132     /**
4133      * The parent this view is attached to.
4134      * {@hide}
4135      *
4136      * @see #getParent()
4137      */
4138     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4139     protected ViewParent mParent;
4140 
4141     /**
4142      * {@hide}
4143      *
4144      * Not available for general use. If you need help, hang up and then dial one of the following
4145      * public APIs:
4146      *
4147      * @see #isAttachedToWindow() for current attach state
4148      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4149      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4150      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4151      * @see #getHandler() for posting messages to this view's UI thread/looper
4152      * @see #getParent() for interacting with the parent chain
4153      * @see #getWindowToken() for the current window token
4154      * @see #getRootView() for the view at the root of the attached hierarchy
4155      * @see #getDisplay() for the Display this view is presented on
4156      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4157      * @see #hasWindowFocus() for whether the attached window is currently focused
4158      * @see #getWindowVisibility() for checking the visibility of the attached window
4159      */
4160     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4161     AttachInfo mAttachInfo;
4162 
4163     /**
4164      * {@hide}
4165      */
4166     @ViewDebug.ExportedProperty(flagMapping = {
4167         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4168                 name = "FORCE_LAYOUT"),
4169         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4170                 name = "LAYOUT_REQUIRED"),
4171         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4172             name = "DRAWING_CACHE_INVALID", outputIf = false),
4173         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4174         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4175         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4176     }, formatToHexString = true)
4177 
4178     /* @hide */
4179     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4180     public int mPrivateFlags;
4181     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4182     int mPrivateFlags2;
4183     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4184     int mPrivateFlags3;
4185 
4186     private int mPrivateFlags4;
4187 
4188     /**
4189      * This view's request for the visibility of the status bar.
4190      * @hide
4191      */
4192     @ViewDebug.ExportedProperty(flagMapping = {
4193             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4194                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4195                     name = "LOW_PROFILE"),
4196             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4197                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4198                     name = "HIDE_NAVIGATION"),
4199             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4200                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4201                     name = "FULLSCREEN"),
4202             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4203                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4204                     name = "LAYOUT_STABLE"),
4205             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4206                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4207                     name = "LAYOUT_HIDE_NAVIGATION"),
4208             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4209                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4210                     name = "LAYOUT_FULLSCREEN"),
4211             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4212                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4213                     name = "IMMERSIVE"),
4214             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4215                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4216                     name = "IMMERSIVE_STICKY"),
4217             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4218                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4219                     name = "LIGHT_STATUS_BAR"),
4220             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4221                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4222                     name = "LIGHT_NAVIGATION_BAR"),
4223             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4224                     equals = STATUS_BAR_DISABLE_EXPAND,
4225                     name = "STATUS_BAR_DISABLE_EXPAND"),
4226             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4227                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4228                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4229             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4230                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4231                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4232             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4233                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4234                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4235             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4236                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4237                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4238             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4239                     equals = STATUS_BAR_DISABLE_HOME,
4240                     name = "STATUS_BAR_DISABLE_HOME"),
4241             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4242                     equals = STATUS_BAR_DISABLE_BACK,
4243                     name = "STATUS_BAR_DISABLE_BACK"),
4244             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4245                     equals = STATUS_BAR_DISABLE_CLOCK,
4246                     name = "STATUS_BAR_DISABLE_CLOCK"),
4247             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4248                     equals = STATUS_BAR_DISABLE_RECENT,
4249                     name = "STATUS_BAR_DISABLE_RECENT"),
4250             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4251                     equals = STATUS_BAR_DISABLE_SEARCH,
4252                     name = "STATUS_BAR_DISABLE_SEARCH"),
4253             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4254                     equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4255                     name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
4256     }, formatToHexString = true)
4257     @SystemUiVisibility
4258     int mSystemUiVisibility;
4259 
4260     /**
4261      * @hide
4262      */
4263     @IntDef(flag = true, prefix = "", value = {
4264             SYSTEM_UI_FLAG_LOW_PROFILE,
4265             SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4266             SYSTEM_UI_FLAG_FULLSCREEN,
4267             SYSTEM_UI_FLAG_LAYOUT_STABLE,
4268             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4269             SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4270             SYSTEM_UI_FLAG_IMMERSIVE,
4271             SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4272             SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4273             SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4274             STATUS_BAR_DISABLE_EXPAND,
4275             STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4276             STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4277             STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4278             STATUS_BAR_DISABLE_SYSTEM_INFO,
4279             STATUS_BAR_DISABLE_HOME,
4280             STATUS_BAR_DISABLE_BACK,
4281             STATUS_BAR_DISABLE_CLOCK,
4282             STATUS_BAR_DISABLE_RECENT,
4283             STATUS_BAR_DISABLE_SEARCH,
4284             STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4285     })
4286     @Retention(RetentionPolicy.SOURCE)
4287     public @interface SystemUiVisibility {}
4288 
4289     /**
4290      * Reference count for transient state.
4291      * @see #setHasTransientState(boolean)
4292      */
4293     int mTransientStateCount = 0;
4294 
4295     /**
4296      * Count of how many windows this view has been attached to.
4297      */
4298     int mWindowAttachCount;
4299 
4300     /**
4301      * The layout parameters associated with this view and used by the parent
4302      * {@link android.view.ViewGroup} to determine how this view should be
4303      * laid out.
4304      *
4305      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4306      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4307      * state correctness of the class.
4308      * {@hide}
4309      */
4310     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4311     protected ViewGroup.LayoutParams mLayoutParams;
4312 
4313     /**
4314      * The view flags hold various views states.
4315      *
4316      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4317      * triggering updates.
4318      * {@hide}
4319      */
4320     @ViewDebug.ExportedProperty(formatToHexString = true)
4321     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4322     int mViewFlags;
4323 
4324     static class TransformationInfo {
4325         /**
4326          * The transform matrix for the View. This transform is calculated internally
4327          * based on the translation, rotation, and scale properties.
4328          *
4329          * Do *not* use this variable directly; instead call getMatrix(), which will
4330          * load the value from the View's RenderNode.
4331          */
4332         private final Matrix mMatrix = new Matrix();
4333 
4334         /**
4335          * The inverse transform matrix for the View. This transform is calculated
4336          * internally based on the translation, rotation, and scale properties.
4337          *
4338          * Do *not* use this variable directly; instead call getInverseMatrix(),
4339          * which will load the value from the View's RenderNode.
4340          */
4341         private Matrix mInverseMatrix;
4342 
4343         /**
4344          * The opacity of the View. This is a value from 0 to 1, where 0 means
4345          * completely transparent and 1 means completely opaque.
4346          */
4347         @ViewDebug.ExportedProperty
4348         private float mAlpha = 1f;
4349 
4350         /**
4351          * The opacity of the view as manipulated by the Fade transition. This is a
4352          * property only used by transitions, which is composited with the other alpha
4353          * values to calculate the final visual alpha value.
4354          */
4355         float mTransitionAlpha = 1f;
4356     }
4357 
4358     /** @hide */
4359     @UnsupportedAppUsage
4360     public TransformationInfo mTransformationInfo;
4361 
4362     /**
4363      * Current clip bounds. to which all drawing of this view are constrained.
4364      */
4365     @ViewDebug.ExportedProperty(category = "drawing")
4366     Rect mClipBounds = null;
4367 
4368     private boolean mLastIsOpaque;
4369 
4370     /**
4371      * The distance in pixels from the left edge of this view's parent
4372      * to the left edge of this view.
4373      * {@hide}
4374      */
4375     @ViewDebug.ExportedProperty(category = "layout")
4376     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4377     protected int mLeft;
4378     /**
4379      * The distance in pixels from the left edge of this view's parent
4380      * to the right edge of this view.
4381      * {@hide}
4382      */
4383     @ViewDebug.ExportedProperty(category = "layout")
4384     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4385     protected int mRight;
4386     /**
4387      * The distance in pixels from the top edge of this view's parent
4388      * to the top edge of this view.
4389      * {@hide}
4390      */
4391     @ViewDebug.ExportedProperty(category = "layout")
4392     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4393     protected int mTop;
4394     /**
4395      * The distance in pixels from the top edge of this view's parent
4396      * to the bottom edge of this view.
4397      * {@hide}
4398      */
4399     @ViewDebug.ExportedProperty(category = "layout")
4400     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4401     protected int mBottom;
4402 
4403     /**
4404      * The offset, in pixels, by which the content of this view is scrolled
4405      * horizontally.
4406      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4407      * accessing these directly.
4408      * {@hide}
4409      */
4410     @ViewDebug.ExportedProperty(category = "scrolling")
4411     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4412     protected int mScrollX;
4413     /**
4414      * The offset, in pixels, by which the content of this view is scrolled
4415      * vertically.
4416      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4417      * accessing these directly.
4418      * {@hide}
4419      */
4420     @ViewDebug.ExportedProperty(category = "scrolling")
4421     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4422     protected int mScrollY;
4423 
4424     /**
4425      * The final computed left padding in pixels that is used for drawing. This is the distance in
4426      * pixels between the left edge of this view and the left edge of its content.
4427      * {@hide}
4428      */
4429     @ViewDebug.ExportedProperty(category = "padding")
4430     @UnsupportedAppUsage
4431     protected int mPaddingLeft = 0;
4432     /**
4433      * The final computed right padding in pixels that is used for drawing. This is the distance in
4434      * pixels between the right edge of this view and the right edge of its content.
4435      * {@hide}
4436      */
4437     @ViewDebug.ExportedProperty(category = "padding")
4438     @UnsupportedAppUsage
4439     protected int mPaddingRight = 0;
4440     /**
4441      * The final computed top padding in pixels that is used for drawing. This is the distance in
4442      * pixels between the top edge of this view and the top edge of its content.
4443      * {@hide}
4444      */
4445     @ViewDebug.ExportedProperty(category = "padding")
4446     @UnsupportedAppUsage
4447     protected int mPaddingTop;
4448     /**
4449      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4450      * pixels between the bottom edge of this view and the bottom edge of its content.
4451      * {@hide}
4452      */
4453     @ViewDebug.ExportedProperty(category = "padding")
4454     @UnsupportedAppUsage
4455     protected int mPaddingBottom;
4456 
4457     /**
4458      * The layout insets in pixels, that is the distance in pixels between the
4459      * visible edges of this view its bounds.
4460      */
4461     private Insets mLayoutInsets;
4462 
4463     /**
4464      * Briefly describes the state of the view and is primarily used for accessibility support.
4465      */
4466     private CharSequence mStateDescription;
4467 
4468     /**
4469      * Briefly describes the view and is primarily used for accessibility support.
4470      */
4471     private CharSequence mContentDescription;
4472 
4473     /**
4474      * If this view represents a distinct part of the window, it can have a title that labels the
4475      * area.
4476      */
4477     private CharSequence mAccessibilityPaneTitle;
4478 
4479     /**
4480      * Specifies the id of a view for which this view serves as a label for
4481      * accessibility purposes.
4482      */
4483     private int mLabelForId = View.NO_ID;
4484 
4485     /**
4486      * Predicate for matching labeled view id with its label for
4487      * accessibility purposes.
4488      */
4489     private MatchLabelForPredicate mMatchLabelForPredicate;
4490 
4491     /**
4492      * Specifies a view before which this one is visited in accessibility traversal.
4493      */
4494     private int mAccessibilityTraversalBeforeId = NO_ID;
4495 
4496     /**
4497      * Specifies a view after which this one is visited in accessibility traversal.
4498      */
4499     private int mAccessibilityTraversalAfterId = NO_ID;
4500 
4501     /**
4502      * Predicate for matching a view by its id.
4503      */
4504     private MatchIdPredicate mMatchIdPredicate;
4505 
4506     /**
4507      * The right padding after RTL resolution, but before taking account of scroll bars.
4508      *
4509      * @hide
4510      */
4511     @ViewDebug.ExportedProperty(category = "padding")
4512     protected int mUserPaddingRight;
4513 
4514     /**
4515      * The resolved bottom padding before taking account of scroll bars.
4516      *
4517      * @hide
4518      */
4519     @ViewDebug.ExportedProperty(category = "padding")
4520     protected int mUserPaddingBottom;
4521 
4522     /**
4523      * The left padding after RTL resolution, but before taking account of scroll bars.
4524      *
4525      * @hide
4526      */
4527     @ViewDebug.ExportedProperty(category = "padding")
4528     protected int mUserPaddingLeft;
4529 
4530     /**
4531      * Cache the paddingStart set by the user to append to the scrollbar's size.
4532      *
4533      */
4534     @ViewDebug.ExportedProperty(category = "padding")
4535     int mUserPaddingStart;
4536 
4537     /**
4538      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4539      *
4540      */
4541     @ViewDebug.ExportedProperty(category = "padding")
4542     int mUserPaddingEnd;
4543 
4544     /**
4545      * The left padding as set by a setter method, a background's padding, or via XML property
4546      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4547      *
4548      * @hide
4549      */
4550     int mUserPaddingLeftInitial;
4551 
4552     /**
4553      * The right padding as set by a setter method, a background's padding, or via XML property
4554      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4555      *
4556      * @hide
4557      */
4558     int mUserPaddingRightInitial;
4559 
4560     /**
4561      * Default undefined padding
4562      */
4563     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4564 
4565     /**
4566      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4567      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4568      */
4569     private boolean mLeftPaddingDefined = false;
4570 
4571     /**
4572      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4573      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4574      */
4575     private boolean mRightPaddingDefined = false;
4576 
4577     /**
4578      * @hide
4579      */
4580     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4581     /**
4582      * @hide
4583      */
4584     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4585 
4586     private LongSparseLongArray mMeasureCache;
4587 
4588     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4589     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4590     private Drawable mBackground;
4591     private TintInfo mBackgroundTint;
4592 
4593     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4594     private ForegroundInfo mForegroundInfo;
4595 
4596     private Drawable mScrollIndicatorDrawable;
4597 
4598     /**
4599      * RenderNode used for backgrounds.
4600      * <p>
4601      * When non-null and valid, this is expected to contain an up-to-date copy
4602      * of the background drawable. It is cleared on temporary detach, and reset
4603      * on cleanup.
4604      * @hide
4605      */
4606     RenderNode mBackgroundRenderNode;
4607 
4608     @UnsupportedAppUsage
4609     private int mBackgroundResource;
4610     private boolean mBackgroundSizeChanged;
4611 
4612     /** The default focus highlight.
4613      * @see #mDefaultFocusHighlightEnabled
4614      * @see Drawable#hasFocusStateSpecified()
4615      */
4616     private Drawable mDefaultFocusHighlight;
4617     private Drawable mDefaultFocusHighlightCache;
4618     private boolean mDefaultFocusHighlightSizeChanged;
4619     /**
4620      * True if the default focus highlight is needed on the target device.
4621      */
4622     private static boolean sUseDefaultFocusHighlight;
4623 
4624     /**
4625      * True if zero-sized views can be focused.
4626      */
4627     private static boolean sCanFocusZeroSized;
4628 
4629     /**
4630      * Always assign focus if a focusable View is available.
4631      */
4632     private static boolean sAlwaysAssignFocus;
4633 
4634     private String mTransitionName;
4635 
4636     static class TintInfo {
4637         ColorStateList mTintList;
4638         BlendMode mBlendMode;
4639         boolean mHasTintMode;
4640         boolean mHasTintList;
4641     }
4642 
4643     private static class ForegroundInfo {
4644         private Drawable mDrawable;
4645         private TintInfo mTintInfo;
4646         private int mGravity = Gravity.FILL;
4647         private boolean mInsidePadding = true;
4648         private boolean mBoundsChanged = true;
4649         private final Rect mSelfBounds = new Rect();
4650         private final Rect mOverlayBounds = new Rect();
4651     }
4652 
4653     static class ListenerInfo {
4654 
4655         @UnsupportedAppUsage
ListenerInfo()4656         ListenerInfo() {
4657         }
4658 
4659         /**
4660          * Listener used to dispatch focus change events.
4661          * This field should be made private, so it is hidden from the SDK.
4662          * {@hide}
4663          */
4664         @UnsupportedAppUsage
4665         protected OnFocusChangeListener mOnFocusChangeListener;
4666 
4667         /**
4668          * Listeners for layout change events.
4669          */
4670         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4671 
4672         protected OnScrollChangeListener mOnScrollChangeListener;
4673 
4674         /**
4675          * Listeners for attach events.
4676          */
4677         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4678 
4679         /**
4680          * Listener used to dispatch click events.
4681          * This field should be made private, so it is hidden from the SDK.
4682          * {@hide}
4683          */
4684         @UnsupportedAppUsage
4685         public OnClickListener mOnClickListener;
4686 
4687         /**
4688          * Listener used to dispatch long click events.
4689          * This field should be made private, so it is hidden from the SDK.
4690          * {@hide}
4691          */
4692         @UnsupportedAppUsage
4693         protected OnLongClickListener mOnLongClickListener;
4694 
4695         /**
4696          * Listener used to dispatch context click events. This field should be made private, so it
4697          * is hidden from the SDK.
4698          * {@hide}
4699          */
4700         protected OnContextClickListener mOnContextClickListener;
4701 
4702         /**
4703          * Listener used to build the context menu.
4704          * This field should be made private, so it is hidden from the SDK.
4705          * {@hide}
4706          */
4707         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4708         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4709 
4710         @UnsupportedAppUsage
4711         private OnKeyListener mOnKeyListener;
4712 
4713         @UnsupportedAppUsage
4714         private OnTouchListener mOnTouchListener;
4715 
4716         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4717         private OnHoverListener mOnHoverListener;
4718 
4719         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4720         private OnGenericMotionListener mOnGenericMotionListener;
4721 
4722         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4723         private OnDragListener mOnDragListener;
4724 
4725         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4726 
4727         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4728 
4729         OnCapturedPointerListener mOnCapturedPointerListener;
4730 
4731         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4732 
4733         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
4734 
4735         /**
4736          * This lives here since it's only valid for interactive views. This list is null until the
4737          * first use.
4738          */
4739         private List<Rect> mSystemGestureExclusionRects = null;
4740 
4741         /**
4742          * Used to track {@link #mSystemGestureExclusionRects}
4743          */
4744         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4745 
4746         /**
4747          * Allows the application to implement custom scroll capture support.
4748          */
4749         ScrollCaptureCallback mScrollCaptureCallback;
4750 
4751         @Nullable
4752         private OnReceiveContentListener mOnReceiveContentListener;
4753     }
4754 
4755     @UnsupportedAppUsage
4756     ListenerInfo mListenerInfo;
4757 
4758     private static class TooltipInfo {
4759         /**
4760          * Text to be displayed in a tooltip popup.
4761          */
4762         @Nullable
4763         CharSequence mTooltipText;
4764 
4765         /**
4766          * View-relative position of the tooltip anchor point.
4767          */
4768         int mAnchorX;
4769         int mAnchorY;
4770 
4771         /**
4772          * The tooltip popup.
4773          */
4774         @Nullable
4775         TooltipPopup mTooltipPopup;
4776 
4777         /**
4778          * Set to true if the tooltip was shown as a result of a long click.
4779          */
4780         boolean mTooltipFromLongClick;
4781 
4782         /**
4783          * Keep these Runnables so that they can be used to reschedule.
4784          */
4785         Runnable mShowTooltipRunnable;
4786         Runnable mHideTooltipRunnable;
4787 
4788         /**
4789          * Hover move is ignored if it is within this distance in pixels from the previous one.
4790          */
4791         int mHoverSlop;
4792 
4793         /**
4794          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4795          * different from the previously stored position. Ignoring insignificant changes
4796          * filters out the jitter which is typical for such input sources as stylus.
4797          *
4798          * @return True if the position has been updated.
4799          */
updateAnchorPos(MotionEvent event)4800         private boolean updateAnchorPos(MotionEvent event) {
4801             final int newAnchorX = (int) event.getX();
4802             final int newAnchorY = (int) event.getY();
4803             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4804                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4805                 return false;
4806             }
4807             mAnchorX = newAnchorX;
4808             mAnchorY = newAnchorY;
4809             return true;
4810         }
4811 
4812         /**
4813          *  Clear the anchor position to ensure that the next change is considered significant.
4814          */
clearAnchorPos()4815         private void clearAnchorPos() {
4816             mAnchorX = Integer.MAX_VALUE;
4817             mAnchorY = Integer.MAX_VALUE;
4818         }
4819     }
4820 
4821     TooltipInfo mTooltipInfo;
4822 
4823     // Temporary values used to hold (x,y) coordinates when delegating from the
4824     // two-arg performLongClick() method to the legacy no-arg version.
4825     private float mLongClickX = Float.NaN;
4826     private float mLongClickY = Float.NaN;
4827 
4828     /**
4829      * The application environment this view lives in.
4830      * This field should be made private, so it is hidden from the SDK.
4831      * {@hide}
4832      */
4833     @ViewDebug.ExportedProperty(deepExport = true)
4834     @UnsupportedAppUsage
4835     @UiContext
4836     protected Context mContext;
4837 
4838     @UnsupportedAppUsage
4839     private final Resources mResources;
4840 
4841     @UnsupportedAppUsage
4842     private ScrollabilityCache mScrollCache;
4843 
4844     private int[] mDrawableState = null;
4845 
4846     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4847 
4848     /**
4849      * Animator that automatically runs based on state changes.
4850      */
4851     private StateListAnimator mStateListAnimator;
4852 
4853     /**
4854      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4855      * the user may specify which view to go to next.
4856      */
4857     private int mNextFocusLeftId = View.NO_ID;
4858 
4859     /**
4860      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4861      * the user may specify which view to go to next.
4862      */
4863     private int mNextFocusRightId = View.NO_ID;
4864 
4865     /**
4866      * When this view has focus and the next focus is {@link #FOCUS_UP},
4867      * the user may specify which view to go to next.
4868      */
4869     private int mNextFocusUpId = View.NO_ID;
4870 
4871     /**
4872      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4873      * the user may specify which view to go to next.
4874      */
4875     private int mNextFocusDownId = View.NO_ID;
4876 
4877     /**
4878      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4879      * the user may specify which view to go to next.
4880      */
4881     int mNextFocusForwardId = View.NO_ID;
4882 
4883     /**
4884      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4885      *
4886      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4887      */
4888     int mNextClusterForwardId = View.NO_ID;
4889 
4890     /**
4891      * Whether this View should use a default focus highlight when it gets focused but doesn't
4892      * have {@link android.R.attr#state_focused} defined in its background.
4893      */
4894     boolean mDefaultFocusHighlightEnabled = true;
4895 
4896     private CheckForLongPress mPendingCheckForLongPress;
4897     @UnsupportedAppUsage
4898     private CheckForTap mPendingCheckForTap = null;
4899     private PerformClick mPerformClick;
4900     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4901     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
4902     private UnsetPressedState mUnsetPressedState;
4903 
4904     /**
4905      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4906      * up event while a long press is invoked as soon as the long press duration is reached, so
4907      * a long press could be performed before the tap is checked, in which case the tap's action
4908      * should not be invoked.
4909      */
4910     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4911     private boolean mHasPerformedLongPress;
4912 
4913     /**
4914      * Whether a context click button is currently pressed down. This is true when the stylus is
4915      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4916      * pressed. This is false once the button is released or if the stylus has been lifted.
4917      */
4918     private boolean mInContextButtonPress;
4919 
4920     /**
4921      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4922      * true after a stylus button press has occured, when the next up event should not be recognized
4923      * as a tap.
4924      */
4925     private boolean mIgnoreNextUpEvent;
4926 
4927     /**
4928      * The minimum height of the view. We'll try our best to have the height
4929      * of this view to at least this amount.
4930      */
4931     @ViewDebug.ExportedProperty(category = "measurement")
4932     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4933     private int mMinHeight;
4934 
4935     /**
4936      * The minimum width of the view. We'll try our best to have the width
4937      * of this view to at least this amount.
4938      */
4939     @ViewDebug.ExportedProperty(category = "measurement")
4940     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4941     private int mMinWidth;
4942 
4943     /**
4944      * The delegate to handle touch events that are physically in this view
4945      * but should be handled by another view.
4946      */
4947     private TouchDelegate mTouchDelegate = null;
4948 
4949     /**
4950      * While touch exploration is in use, set to true when hovering across boundaries and
4951      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
4952      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
4953      * {@link MotionEvent#ACTION_HOVER_EXIT}.
4954      * Note that children of view group are excluded in the touch area.
4955      * @see #dispatchTouchExplorationHoverEvent
4956      */
4957     private boolean mHoveringTouchDelegate = false;
4958 
4959     /**
4960      * Solid color to use as a background when creating the drawing cache. Enables
4961      * the cache to use 16 bit bitmaps instead of 32 bit.
4962      */
4963     private int mDrawingCacheBackgroundColor = 0;
4964 
4965     /**
4966      * Special tree observer used when mAttachInfo is null.
4967      */
4968     private ViewTreeObserver mFloatingTreeObserver;
4969 
4970     /**
4971      * Cache the touch slop from the context that created the view.
4972      */
4973     private int mTouchSlop;
4974 
4975     /**
4976      * Cache the ambiguous gesture multiplier from the context that created the view.
4977      */
4978     private float mAmbiguousGestureMultiplier;
4979 
4980     /**
4981      * Object that handles automatic animation of view properties.
4982      */
4983     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4984     private ViewPropertyAnimator mAnimator = null;
4985 
4986     /**
4987      * List of registered FrameMetricsObservers.
4988      */
4989     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4990 
4991     /**
4992      * Flag indicating that a drag can cross window boundaries.  When
4993      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4994      * with this flag set, all visible applications with targetSdkVersion >=
4995      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4996      * in the drag operation and receive the dragged content.
4997      *
4998      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4999      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
5000      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
5001      */
5002     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
5003 
5004     /**
5005      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5006      * request read access to the content URI(s) contained in the {@link ClipData} object.
5007      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5008      */
5009     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5010 
5011     /**
5012      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5013      * request write access to the content URI(s) contained in the {@link ClipData} object.
5014      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5015      */
5016     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5017 
5018     /**
5019      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5020      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5021      * reboots until explicitly revoked with
5022      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5023      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5024      */
5025     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5026             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5027 
5028     /**
5029      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5030      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5031      * match against the original granted URI.
5032      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5033      */
5034     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5035             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5036 
5037     /**
5038      * Flag indicating that the drag shadow will be opaque.  When
5039      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5040      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5041      */
5042     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5043 
5044     /**
5045      * Flag indicating that the drag was initiated with
5046      * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START}. When
5047      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called, this
5048      * is used by the system to perform a drag without animations.
5049      */
5050     public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
5051 
5052     /**
5053      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5054      */
5055     private float mVerticalScrollFactor;
5056 
5057     /**
5058      * Position of the vertical scroll bar.
5059      */
5060     @UnsupportedAppUsage
5061     private int mVerticalScrollbarPosition;
5062 
5063     /**
5064      * Position the scroll bar at the default position as determined by the system.
5065      */
5066     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5067 
5068     /**
5069      * Position the scroll bar along the left edge.
5070      */
5071     public static final int SCROLLBAR_POSITION_LEFT = 1;
5072 
5073     /**
5074      * Position the scroll bar along the right edge.
5075      */
5076     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5077 
5078     /**
5079      * Indicates that the view does not have a layer.
5080      *
5081      * @see #getLayerType()
5082      * @see #setLayerType(int, android.graphics.Paint)
5083      * @see #LAYER_TYPE_SOFTWARE
5084      * @see #LAYER_TYPE_HARDWARE
5085      */
5086     public static final int LAYER_TYPE_NONE = 0;
5087 
5088     /**
5089      * <p>Indicates that the view has a software layer. A software layer is backed
5090      * by a bitmap and causes the view to be rendered using Android's software
5091      * rendering pipeline, even if hardware acceleration is enabled.</p>
5092      *
5093      * <p>Software layers have various usages:</p>
5094      * <p>When the application is not using hardware acceleration, a software layer
5095      * is useful to apply a specific color filter and/or blending mode and/or
5096      * translucency to a view and all its children.</p>
5097      * <p>When the application is using hardware acceleration, a software layer
5098      * is useful to render drawing primitives not supported by the hardware
5099      * accelerated pipeline. It can also be used to cache a complex view tree
5100      * into a texture and reduce the complexity of drawing operations. For instance,
5101      * when animating a complex view tree with a translation, a software layer can
5102      * be used to render the view tree only once.</p>
5103      * <p>Software layers should be avoided when the affected view tree updates
5104      * often. Every update will require to re-render the software layer, which can
5105      * potentially be slow (particularly when hardware acceleration is turned on
5106      * since the layer will have to be uploaded into a hardware texture after every
5107      * update.)</p>
5108      *
5109      * @see #getLayerType()
5110      * @see #setLayerType(int, android.graphics.Paint)
5111      * @see #LAYER_TYPE_NONE
5112      * @see #LAYER_TYPE_HARDWARE
5113      */
5114     public static final int LAYER_TYPE_SOFTWARE = 1;
5115 
5116     /**
5117      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5118      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5119      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5120      * rendering pipeline, but only if hardware acceleration is turned on for the
5121      * view hierarchy. When hardware acceleration is turned off, hardware layers
5122      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5123      *
5124      * <p>A hardware layer is useful to apply a specific color filter and/or
5125      * blending mode and/or translucency to a view and all its children.</p>
5126      * <p>A hardware layer can be used to cache a complex view tree into a
5127      * texture and reduce the complexity of drawing operations. For instance,
5128      * when animating a complex view tree with a translation, a hardware layer can
5129      * be used to render the view tree only once.</p>
5130      * <p>A hardware layer can also be used to increase the rendering quality when
5131      * rotation transformations are applied on a view. It can also be used to
5132      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5133      *
5134      * @see #getLayerType()
5135      * @see #setLayerType(int, android.graphics.Paint)
5136      * @see #LAYER_TYPE_NONE
5137      * @see #LAYER_TYPE_SOFTWARE
5138      */
5139     public static final int LAYER_TYPE_HARDWARE = 2;
5140 
5141     /** @hide */
5142     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5143             LAYER_TYPE_NONE,
5144             LAYER_TYPE_SOFTWARE,
5145             LAYER_TYPE_HARDWARE
5146     })
5147     @Retention(RetentionPolicy.SOURCE)
5148     public @interface LayerType {}
5149 
5150     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
5151             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
5152             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
5153             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
5154     })
5155     int mLayerType = LAYER_TYPE_NONE;
5156     Paint mLayerPaint;
5157 
5158     /**
5159      * Set to true when drawing cache is enabled and cannot be created.
5160      *
5161      * @hide
5162      */
5163     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5164     public boolean mCachingFailed;
5165     @UnsupportedAppUsage
5166     private Bitmap mDrawingCache;
5167     @UnsupportedAppUsage
5168     private Bitmap mUnscaledDrawingCache;
5169 
5170     /**
5171      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5172      * <p>
5173      * When non-null and valid, this is expected to contain an up-to-date copy
5174      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5175      * cleanup.
5176      */
5177     @UnsupportedAppUsage
5178     final RenderNode mRenderNode;
5179 
5180     /**
5181      * Set to true when the view is sending hover accessibility events because it
5182      * is the innermost hovered view.
5183      */
5184     private boolean mSendingHoverAccessibilityEvents;
5185 
5186     /**
5187      * Delegate for injecting accessibility functionality.
5188      */
5189     @UnsupportedAppUsage
5190     AccessibilityDelegate mAccessibilityDelegate;
5191 
5192     /**
5193      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5194      * and add/remove objects to/from the overlay directly through the Overlay methods.
5195      */
5196     ViewOverlay mOverlay;
5197 
5198     /**
5199      * The currently active parent view for receiving delegated nested scrolling events.
5200      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5201      * by {@link #stopNestedScroll()} at the same point where we clear
5202      * requestDisallowInterceptTouchEvent.
5203      */
5204     private ViewParent mNestedScrollingParent;
5205 
5206     /**
5207      * Consistency verifier for debugging purposes.
5208      * @hide
5209      */
5210     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5211             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5212                     new InputEventConsistencyVerifier(this, 0) : null;
5213 
5214     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5215 
5216     private int[] mTempNestedScrollConsumed;
5217 
5218     /**
5219      * An overlay is going to draw this View instead of being drawn as part of this
5220      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5221      * when this view is invalidated.
5222      */
5223     GhostView mGhostView;
5224 
5225     /**
5226      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5227      * @hide
5228      */
5229     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5230     public String[] mAttributes;
5231 
5232     /**
5233      * Maps a Resource id to its name.
5234      */
5235     private static SparseArray<String> mAttributeMap;
5236 
5237     /**
5238      * Queue of pending runnables. Used to postpone calls to post() until this
5239      * view is attached and has a handler.
5240      */
5241     private HandlerActionQueue mRunQueue;
5242 
5243     /**
5244      * The pointer icon when the mouse hovers on this view. The default is null.
5245      */
5246     private PointerIcon mPointerIcon;
5247 
5248     /**
5249      * @hide
5250      */
5251     @UnsupportedAppUsage
5252     String mStartActivityRequestWho;
5253 
5254     @Nullable
5255     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5256 
5257     /** Used to delay visibility updates sent to the autofill manager */
5258     private Handler mVisibilityChangeForAutofillHandler;
5259 
5260     /**
5261      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5262      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5263      */
5264     @Nullable
5265     private ContentCaptureSession mContentCaptureSession;
5266 
5267     /**
5268      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5269      */
5270     private boolean mContentCaptureSessionCached;
5271 
5272     @LayoutRes
5273     private int mSourceLayoutId = ID_NULL;
5274 
5275     @Nullable
5276     private SparseIntArray mAttributeSourceResId;
5277 
5278     @Nullable
5279     private SparseArray<int[]> mAttributeResolutionStacks;
5280 
5281     @StyleRes
5282     private int mExplicitStyle;
5283 
5284     /**
5285      * Specifies which input source classes should provide unbuffered input events to this view
5286      *
5287      * @see View#requestUnbufferedDispatch(int)
5288      */
5289     @InputSourceClass
5290     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5291 
5292     @Nullable
5293     private String[] mReceiveContentMimeTypes;
5294 
5295     @Nullable
5296     private ViewTranslationCallback mViewTranslationCallback;
5297 
5298     @Nullable
5299 
5300     private ViewTranslationResponse mViewTranslationResponse;
5301 
5302     /**
5303      * Simple constructor to use when creating a view from code.
5304      *
5305      * @param context The Context the view is running in, through which it can
5306      *        access the current theme, resources, etc.
5307      */
View(Context context)5308     public View(Context context) {
5309         mContext = context;
5310         mResources = context != null ? context.getResources() : null;
5311         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5312         // Set some flags defaults
5313         mPrivateFlags2 =
5314                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5315                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5316                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5317                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5318                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5319                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5320 
5321         final ViewConfiguration configuration = ViewConfiguration.get(context);
5322         mTouchSlop = configuration.getScaledTouchSlop();
5323         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5324 
5325         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5326         mUserPaddingStart = UNDEFINED_PADDING;
5327         mUserPaddingEnd = UNDEFINED_PADDING;
5328         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5329 
5330         if (!sCompatibilityDone && context != null) {
5331             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5332 
5333             // Older apps may need this compatibility hack for measurement.
5334             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5335 
5336             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5337             // of whether a layout was requested on that View.
5338             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5339 
5340             // In M and newer, our widgets can pass a "hint" value in the size
5341             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5342             // know what the expected parent size is going to be, so e.g. list items can size
5343             // themselves at 1/3 the size of their container. It breaks older apps though,
5344             // specifically apps that use some popular open source libraries.
5345             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5346 
5347             // Old versions of the platform would give different results from
5348             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5349             // modes, so we always need to run an additional EXACTLY pass.
5350             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5351 
5352             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5353             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5354             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5355 
5356             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5357             // in apps so we target check it to avoid breaking existing apps.
5358             sPreserveMarginParamsInLayoutParamConversion =
5359                     targetSdkVersion >= Build.VERSION_CODES.N;
5360 
5361             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5362 
5363             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5364 
5365             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5366 
5367             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5368                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5369 
5370             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5371 
5372             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5373 
5374             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5375 
5376             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5377 
5378             sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
5379 
5380             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5381 
5382             GradientDrawable.sWrapNegativeAngleMeasurements =
5383                     targetSdkVersion >= Build.VERSION_CODES.Q;
5384 
5385             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5386 
5387             sCompatibilityDone = true;
5388         }
5389     }
5390 
5391     /**
5392      * Constructor that is called when inflating a view from XML. This is called
5393      * when a view is being constructed from an XML file, supplying attributes
5394      * that were specified in the XML file. This version uses a default style of
5395      * 0, so the only attribute values applied are those in the Context's Theme
5396      * and the given AttributeSet.
5397      *
5398      * <p>
5399      * The method onFinishInflate() will be called after all children have been
5400      * added.
5401      *
5402      * @param context The Context the view is running in, through which it can
5403      *        access the current theme, resources, etc.
5404      * @param attrs The attributes of the XML tag that is inflating the view.
5405      * @see #View(Context, AttributeSet, int)
5406      */
5407     public View(Context context, @Nullable AttributeSet attrs) {
5408         this(context, attrs, 0);
5409     }
5410 
5411     /**
5412      * Perform inflation from XML and apply a class-specific base style from a
5413      * theme attribute. This constructor of View allows subclasses to use their
5414      * own base style when they are inflating. For example, a Button class's
5415      * constructor would call this version of the super class constructor and
5416      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5417      * allows the theme's button style to modify all of the base view attributes
5418      * (in particular its background) as well as the Button class's attributes.
5419      *
5420      * @param context The Context the view is running in, through which it can
5421      *        access the current theme, resources, etc.
5422      * @param attrs The attributes of the XML tag that is inflating the view.
5423      * @param defStyleAttr An attribute in the current theme that contains a
5424      *        reference to a style resource that supplies default values for
5425      *        the view. Can be 0 to not look for defaults.
5426      * @see #View(Context, AttributeSet)
5427      */
5428     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5429         this(context, attrs, defStyleAttr, 0);
5430     }
5431 
5432     /**
5433      * Perform inflation from XML and apply a class-specific base style from a
5434      * theme attribute or style resource. This constructor of View allows
5435      * subclasses to use their own base style when they are inflating.
5436      * <p>
5437      * When determining the final value of a particular attribute, there are
5438      * four inputs that come into play:
5439      * <ol>
5440      * <li>Any attribute values in the given AttributeSet.
5441      * <li>The style resource specified in the AttributeSet (named "style").
5442      * <li>The default style specified by <var>defStyleAttr</var>.
5443      * <li>The default style specified by <var>defStyleRes</var>.
5444      * <li>The base values in this theme.
5445      * </ol>
5446      * <p>
5447      * Each of these inputs is considered in-order, with the first listed taking
5448      * precedence over the following ones. In other words, if in the
5449      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5450      * , then the button's text will <em>always</em> be black, regardless of
5451      * what is specified in any of the styles.
5452      *
5453      * @param context The Context the view is running in, through which it can
5454      *        access the current theme, resources, etc.
5455      * @param attrs The attributes of the XML tag that is inflating the view.
5456      * @param defStyleAttr An attribute in the current theme that contains a
5457      *        reference to a style resource that supplies default values for
5458      *        the view. Can be 0 to not look for defaults.
5459      * @param defStyleRes A resource identifier of a style resource that
5460      *        supplies default values for the view, used only if
5461      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5462      *        to not look for defaults.
5463      * @see #View(Context, AttributeSet, int)
5464      */
5465     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5466         this(context);
5467 
5468         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5469 
5470         final TypedArray a = context.obtainStyledAttributes(
5471                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5472 
5473         retrieveExplicitStyle(context.getTheme(), attrs);
5474         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5475                 defStyleAttr, defStyleRes);
5476 
5477         if (sDebugViewAttributes) {
5478             saveAttributeData(attrs, a);
5479         }
5480 
5481         Drawable background = null;
5482 
5483         int leftPadding = -1;
5484         int topPadding = -1;
5485         int rightPadding = -1;
5486         int bottomPadding = -1;
5487         int startPadding = UNDEFINED_PADDING;
5488         int endPadding = UNDEFINED_PADDING;
5489 
5490         int padding = -1;
5491         int paddingHorizontal = -1;
5492         int paddingVertical = -1;
5493 
5494         int viewFlagValues = 0;
5495         int viewFlagMasks = 0;
5496 
5497         boolean setScrollContainer = false;
5498 
5499         int x = 0;
5500         int y = 0;
5501 
5502         float tx = 0;
5503         float ty = 0;
5504         float tz = 0;
5505         float elevation = 0;
5506         float rotation = 0;
5507         float rotationX = 0;
5508         float rotationY = 0;
5509         float sx = 1f;
5510         float sy = 1f;
5511         boolean transformSet = false;
5512 
5513         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5514         int overScrollMode = mOverScrollMode;
5515         boolean initializeScrollbars = false;
5516         boolean initializeScrollIndicators = false;
5517 
5518         boolean startPaddingDefined = false;
5519         boolean endPaddingDefined = false;
5520         boolean leftPaddingDefined = false;
5521         boolean rightPaddingDefined = false;
5522 
5523         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5524 
5525         // Set default values.
5526         viewFlagValues |= FOCUSABLE_AUTO;
5527         viewFlagMasks |= FOCUSABLE_AUTO;
5528 
5529         final int N = a.getIndexCount();
5530         for (int i = 0; i < N; i++) {
5531             int attr = a.getIndex(i);
5532             switch (attr) {
5533                 case com.android.internal.R.styleable.View_background:
5534                     background = a.getDrawable(attr);
5535                     break;
5536                 case com.android.internal.R.styleable.View_padding:
5537                     padding = a.getDimensionPixelSize(attr, -1);
5538                     mUserPaddingLeftInitial = padding;
5539                     mUserPaddingRightInitial = padding;
5540                     leftPaddingDefined = true;
5541                     rightPaddingDefined = true;
5542                     break;
5543                 case com.android.internal.R.styleable.View_paddingHorizontal:
5544                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5545                     mUserPaddingLeftInitial = paddingHorizontal;
5546                     mUserPaddingRightInitial = paddingHorizontal;
5547                     leftPaddingDefined = true;
5548                     rightPaddingDefined = true;
5549                     break;
5550                 case com.android.internal.R.styleable.View_paddingVertical:
5551                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5552                     break;
5553                 case com.android.internal.R.styleable.View_paddingLeft:
5554                     leftPadding = a.getDimensionPixelSize(attr, -1);
5555                     mUserPaddingLeftInitial = leftPadding;
5556                     leftPaddingDefined = true;
5557                     break;
5558                 case com.android.internal.R.styleable.View_paddingTop:
5559                     topPadding = a.getDimensionPixelSize(attr, -1);
5560                     break;
5561                 case com.android.internal.R.styleable.View_paddingRight:
5562                     rightPadding = a.getDimensionPixelSize(attr, -1);
5563                     mUserPaddingRightInitial = rightPadding;
5564                     rightPaddingDefined = true;
5565                     break;
5566                 case com.android.internal.R.styleable.View_paddingBottom:
5567                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5568                     break;
5569                 case com.android.internal.R.styleable.View_paddingStart:
5570                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5571                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5572                     break;
5573                 case com.android.internal.R.styleable.View_paddingEnd:
5574                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5575                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5576                     break;
5577                 case com.android.internal.R.styleable.View_scrollX:
5578                     x = a.getDimensionPixelOffset(attr, 0);
5579                     break;
5580                 case com.android.internal.R.styleable.View_scrollY:
5581                     y = a.getDimensionPixelOffset(attr, 0);
5582                     break;
5583                 case com.android.internal.R.styleable.View_alpha:
5584                     setAlpha(a.getFloat(attr, 1f));
5585                     break;
5586                 case com.android.internal.R.styleable.View_transformPivotX:
5587                     setPivotX(a.getDimension(attr, 0));
5588                     break;
5589                 case com.android.internal.R.styleable.View_transformPivotY:
5590                     setPivotY(a.getDimension(attr, 0));
5591                     break;
5592                 case com.android.internal.R.styleable.View_translationX:
5593                     tx = a.getDimension(attr, 0);
5594                     transformSet = true;
5595                     break;
5596                 case com.android.internal.R.styleable.View_translationY:
5597                     ty = a.getDimension(attr, 0);
5598                     transformSet = true;
5599                     break;
5600                 case com.android.internal.R.styleable.View_translationZ:
5601                     tz = a.getDimension(attr, 0);
5602                     transformSet = true;
5603                     break;
5604                 case com.android.internal.R.styleable.View_elevation:
5605                     elevation = a.getDimension(attr, 0);
5606                     transformSet = true;
5607                     break;
5608                 case com.android.internal.R.styleable.View_rotation:
5609                     rotation = a.getFloat(attr, 0);
5610                     transformSet = true;
5611                     break;
5612                 case com.android.internal.R.styleable.View_rotationX:
5613                     rotationX = a.getFloat(attr, 0);
5614                     transformSet = true;
5615                     break;
5616                 case com.android.internal.R.styleable.View_rotationY:
5617                     rotationY = a.getFloat(attr, 0);
5618                     transformSet = true;
5619                     break;
5620                 case com.android.internal.R.styleable.View_scaleX:
5621                     sx = a.getFloat(attr, 1f);
5622                     transformSet = true;
5623                     break;
5624                 case com.android.internal.R.styleable.View_scaleY:
5625                     sy = a.getFloat(attr, 1f);
5626                     transformSet = true;
5627                     break;
5628                 case com.android.internal.R.styleable.View_id:
5629                     mID = a.getResourceId(attr, NO_ID);
5630                     break;
5631                 case com.android.internal.R.styleable.View_tag:
5632                     mTag = a.getText(attr);
5633                     break;
5634                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5635                     if (a.getBoolean(attr, false)) {
5636                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5637                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5638                     }
5639                     break;
5640                 case com.android.internal.R.styleable.View_focusable:
5641                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5642                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5643                         viewFlagMasks |= FOCUSABLE_MASK;
5644                     }
5645                     break;
5646                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5647                     if (a.getBoolean(attr, false)) {
5648                         // unset auto focus since focusableInTouchMode implies explicit focusable
5649                         viewFlagValues &= ~FOCUSABLE_AUTO;
5650                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5651                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5652                     }
5653                     break;
5654                 case com.android.internal.R.styleable.View_clickable:
5655                     if (a.getBoolean(attr, false)) {
5656                         viewFlagValues |= CLICKABLE;
5657                         viewFlagMasks |= CLICKABLE;
5658                     }
5659                     break;
5660                 case com.android.internal.R.styleable.View_allowClickWhenDisabled:
5661                     setAllowClickWhenDisabled(a.getBoolean(attr, false));
5662                     break;
5663                 case com.android.internal.R.styleable.View_longClickable:
5664                     if (a.getBoolean(attr, false)) {
5665                         viewFlagValues |= LONG_CLICKABLE;
5666                         viewFlagMasks |= LONG_CLICKABLE;
5667                     }
5668                     break;
5669                 case com.android.internal.R.styleable.View_contextClickable:
5670                     if (a.getBoolean(attr, false)) {
5671                         viewFlagValues |= CONTEXT_CLICKABLE;
5672                         viewFlagMasks |= CONTEXT_CLICKABLE;
5673                     }
5674                     break;
5675                 case com.android.internal.R.styleable.View_saveEnabled:
5676                     if (!a.getBoolean(attr, true)) {
5677                         viewFlagValues |= SAVE_DISABLED;
5678                         viewFlagMasks |= SAVE_DISABLED_MASK;
5679                     }
5680                     break;
5681                 case com.android.internal.R.styleable.View_duplicateParentState:
5682                     if (a.getBoolean(attr, false)) {
5683                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5684                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5685                     }
5686                     break;
5687                 case com.android.internal.R.styleable.View_visibility:
5688                     final int visibility = a.getInt(attr, 0);
5689                     if (visibility != 0) {
5690                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5691                         viewFlagMasks |= VISIBILITY_MASK;
5692                     }
5693                     break;
5694                 case com.android.internal.R.styleable.View_layoutDirection:
5695                     // Clear any layout direction flags (included resolved bits) already set
5696                     mPrivateFlags2 &=
5697                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5698                     // Set the layout direction flags depending on the value of the attribute
5699                     final int layoutDirection = a.getInt(attr, -1);
5700                     final int value = (layoutDirection != -1) ?
5701                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5702                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5703                     break;
5704                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5705                     final int cacheQuality = a.getInt(attr, 0);
5706                     if (cacheQuality != 0) {
5707                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5708                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5709                     }
5710                     break;
5711                 case com.android.internal.R.styleable.View_contentDescription:
5712                     setContentDescription(a.getString(attr));
5713                     break;
5714                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5715                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5716                     break;
5717                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5718                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5719                     break;
5720                 case com.android.internal.R.styleable.View_labelFor:
5721                     setLabelFor(a.getResourceId(attr, NO_ID));
5722                     break;
5723                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5724                     if (!a.getBoolean(attr, true)) {
5725                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5726                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5727                     }
5728                     break;
5729                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5730                     if (!a.getBoolean(attr, true)) {
5731                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5732                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5733                     }
5734                     break;
5735                 case R.styleable.View_scrollbars:
5736                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5737                     if (scrollbars != SCROLLBARS_NONE) {
5738                         viewFlagValues |= scrollbars;
5739                         viewFlagMasks |= SCROLLBARS_MASK;
5740                         initializeScrollbars = true;
5741                     }
5742                     break;
5743                 //noinspection deprecation
5744                 case R.styleable.View_fadingEdge:
5745                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5746                         // Ignore the attribute starting with ICS
5747                         break;
5748                     }
5749                     // With builds < ICS, fall through and apply fading edges
5750                 case R.styleable.View_requiresFadingEdge:
5751                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5752                     if (fadingEdge != FADING_EDGE_NONE) {
5753                         viewFlagValues |= fadingEdge;
5754                         viewFlagMasks |= FADING_EDGE_MASK;
5755                         initializeFadingEdgeInternal(a);
5756                     }
5757                     break;
5758                 case R.styleable.View_scrollbarStyle:
5759                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5760                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5761                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5762                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5763                     }
5764                     break;
5765                 case R.styleable.View_isScrollContainer:
5766                     setScrollContainer = true;
5767                     if (a.getBoolean(attr, false)) {
5768                         setScrollContainer(true);
5769                     }
5770                     break;
5771                 case com.android.internal.R.styleable.View_keepScreenOn:
5772                     if (a.getBoolean(attr, false)) {
5773                         viewFlagValues |= KEEP_SCREEN_ON;
5774                         viewFlagMasks |= KEEP_SCREEN_ON;
5775                     }
5776                     break;
5777                 case R.styleable.View_filterTouchesWhenObscured:
5778                     if (a.getBoolean(attr, false)) {
5779                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5780                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5781                     }
5782                     break;
5783                 case R.styleable.View_nextFocusLeft:
5784                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5785                     break;
5786                 case R.styleable.View_nextFocusRight:
5787                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5788                     break;
5789                 case R.styleable.View_nextFocusUp:
5790                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5791                     break;
5792                 case R.styleable.View_nextFocusDown:
5793                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5794                     break;
5795                 case R.styleable.View_nextFocusForward:
5796                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5797                     break;
5798                 case R.styleable.View_nextClusterForward:
5799                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5800                     break;
5801                 case R.styleable.View_minWidth:
5802                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5803                     break;
5804                 case R.styleable.View_minHeight:
5805                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5806                     break;
5807                 case R.styleable.View_onClick:
5808                     if (context.isRestricted()) {
5809                         throw new IllegalStateException("The android:onClick attribute cannot "
5810                                 + "be used within a restricted context");
5811                     }
5812 
5813                     final String handlerName = a.getString(attr);
5814                     if (handlerName != null) {
5815                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5816                     }
5817                     break;
5818                 case R.styleable.View_overScrollMode:
5819                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5820                     break;
5821                 case R.styleable.View_verticalScrollbarPosition:
5822                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5823                     break;
5824                 case R.styleable.View_layerType:
5825                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5826                     break;
5827                 case R.styleable.View_textDirection:
5828                     // Clear any text direction flag already set
5829                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5830                     // Set the text direction flags depending on the value of the attribute
5831                     final int textDirection = a.getInt(attr, -1);
5832                     if (textDirection != -1) {
5833                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5834                     }
5835                     break;
5836                 case R.styleable.View_textAlignment:
5837                     // Clear any text alignment flag already set
5838                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5839                     // Set the text alignment flag depending on the value of the attribute
5840                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5841                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5842                     break;
5843                 case R.styleable.View_importantForAccessibility:
5844                     setImportantForAccessibility(a.getInt(attr,
5845                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5846                     break;
5847                 case R.styleable.View_accessibilityLiveRegion:
5848                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5849                     break;
5850                 case R.styleable.View_transitionName:
5851                     setTransitionName(a.getString(attr));
5852                     break;
5853                 case R.styleable.View_nestedScrollingEnabled:
5854                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5855                     break;
5856                 case R.styleable.View_stateListAnimator:
5857                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5858                             a.getResourceId(attr, 0)));
5859                     break;
5860                 case R.styleable.View_backgroundTint:
5861                     // This will get applied later during setBackground().
5862                     if (mBackgroundTint == null) {
5863                         mBackgroundTint = new TintInfo();
5864                     }
5865                     mBackgroundTint.mTintList = a.getColorStateList(
5866                             R.styleable.View_backgroundTint);
5867                     mBackgroundTint.mHasTintList = true;
5868                     break;
5869                 case R.styleable.View_backgroundTintMode:
5870                     // This will get applied later during setBackground().
5871                     if (mBackgroundTint == null) {
5872                         mBackgroundTint = new TintInfo();
5873                     }
5874                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
5875                             R.styleable.View_backgroundTintMode, -1), null);
5876                     mBackgroundTint.mHasTintMode = true;
5877                     break;
5878                 case R.styleable.View_outlineProvider:
5879                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5880                             PROVIDER_BACKGROUND));
5881                     break;
5882                 case R.styleable.View_foreground:
5883                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5884                         setForeground(a.getDrawable(attr));
5885                     }
5886                     break;
5887                 case R.styleable.View_foregroundGravity:
5888                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5889                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5890                     }
5891                     break;
5892                 case R.styleable.View_foregroundTintMode:
5893                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5894                         setForegroundTintBlendMode(
5895                                 Drawable.parseBlendMode(a.getInt(attr, -1),
5896                                         null));
5897                     }
5898                     break;
5899                 case R.styleable.View_foregroundTint:
5900                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5901                         setForegroundTintList(a.getColorStateList(attr));
5902                     }
5903                     break;
5904                 case R.styleable.View_foregroundInsidePadding:
5905                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5906                         if (mForegroundInfo == null) {
5907                             mForegroundInfo = new ForegroundInfo();
5908                         }
5909                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5910                                 mForegroundInfo.mInsidePadding);
5911                     }
5912                     break;
5913                 case R.styleable.View_scrollIndicators:
5914                     final int scrollIndicators =
5915                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5916                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5917                     if (scrollIndicators != 0) {
5918                         mPrivateFlags3 |= scrollIndicators;
5919                         initializeScrollIndicators = true;
5920                     }
5921                     break;
5922                 case R.styleable.View_pointerIcon:
5923                     final int resourceId = a.getResourceId(attr, 0);
5924                     if (resourceId != 0) {
5925                         setPointerIcon(PointerIcon.load(
5926                                 context.getResources(), resourceId));
5927                     } else {
5928                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5929                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5930                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5931                         }
5932                     }
5933                     break;
5934                 case R.styleable.View_forceHasOverlappingRendering:
5935                     if (a.peekValue(attr) != null) {
5936                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5937                     }
5938                     break;
5939                 case R.styleable.View_tooltipText:
5940                     setTooltipText(a.getText(attr));
5941                     break;
5942                 case R.styleable.View_keyboardNavigationCluster:
5943                     if (a.peekValue(attr) != null) {
5944                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5945                     }
5946                     break;
5947                 case R.styleable.View_focusedByDefault:
5948                     if (a.peekValue(attr) != null) {
5949                         setFocusedByDefault(a.getBoolean(attr, true));
5950                     }
5951                     break;
5952                 case R.styleable.View_autofillHints:
5953                     if (a.peekValue(attr) != null) {
5954                         CharSequence[] rawHints = null;
5955                         String rawString = null;
5956 
5957                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5958                             int resId = a.getResourceId(attr, 0);
5959 
5960                             try {
5961                                 rawHints = a.getTextArray(attr);
5962                             } catch (Resources.NotFoundException e) {
5963                                 rawString = getResources().getString(resId);
5964                             }
5965                         } else {
5966                             rawString = a.getString(attr);
5967                         }
5968 
5969                         if (rawHints == null) {
5970                             if (rawString == null) {
5971                                 throw new IllegalArgumentException(
5972                                         "Could not resolve autofillHints");
5973                             } else {
5974                                 rawHints = rawString.split(",");
5975                             }
5976                         }
5977 
5978                         String[] hints = new String[rawHints.length];
5979 
5980                         int numHints = rawHints.length;
5981                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5982                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5983                         }
5984                         setAutofillHints(hints);
5985                     }
5986                     break;
5987                 case R.styleable.View_importantForAutofill:
5988                     if (a.peekValue(attr) != null) {
5989                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5990                     }
5991                     break;
5992                 case R.styleable.View_importantForContentCapture:
5993                     if (a.peekValue(attr) != null) {
5994                         setImportantForContentCapture(a.getInt(attr,
5995                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
5996                     }
5997                 case R.styleable.View_defaultFocusHighlightEnabled:
5998                     if (a.peekValue(attr) != null) {
5999                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
6000                     }
6001                     break;
6002                 case R.styleable.View_screenReaderFocusable:
6003                     if (a.peekValue(attr) != null) {
6004                         setScreenReaderFocusable(a.getBoolean(attr, false));
6005                     }
6006                     break;
6007                 case R.styleable.View_accessibilityPaneTitle:
6008                     if (a.peekValue(attr) != null) {
6009                         setAccessibilityPaneTitle(a.getString(attr));
6010                     }
6011                     break;
6012                 case R.styleable.View_outlineSpotShadowColor:
6013                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6014                     break;
6015                 case R.styleable.View_outlineAmbientShadowColor:
6016                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6017                     break;
6018                 case com.android.internal.R.styleable.View_accessibilityHeading:
6019                     setAccessibilityHeading(a.getBoolean(attr, false));
6020                     break;
6021                 case R.styleable.View_forceDarkAllowed:
6022                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6023                     break;
6024                 case R.styleable.View_scrollCaptureHint:
6025                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6026                     break;
6027                 case R.styleable.View_clipToOutline:
6028                     setClipToOutline(a.getBoolean(attr, false));
6029                     break;
6030             }
6031         }
6032 
6033         setOverScrollMode(overScrollMode);
6034 
6035         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6036         // the resolved layout direction). Those cached values will be used later during padding
6037         // resolution.
6038         mUserPaddingStart = startPadding;
6039         mUserPaddingEnd = endPadding;
6040 
6041         if (background != null) {
6042             setBackground(background);
6043         }
6044 
6045         // setBackground above will record that padding is currently provided by the background.
6046         // If we have padding specified via xml, record that here instead and use it.
6047         mLeftPaddingDefined = leftPaddingDefined;
6048         mRightPaddingDefined = rightPaddingDefined;
6049 
6050         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6051         // bottomPadding, and padding set by background.  Valid padding beats everything.
6052         if (padding >= 0) {
6053             leftPadding = padding;
6054             topPadding = padding;
6055             rightPadding = padding;
6056             bottomPadding = padding;
6057             mUserPaddingLeftInitial = padding;
6058             mUserPaddingRightInitial = padding;
6059         } else {
6060             if (paddingHorizontal >= 0) {
6061                 leftPadding = paddingHorizontal;
6062                 rightPadding = paddingHorizontal;
6063                 mUserPaddingLeftInitial = paddingHorizontal;
6064                 mUserPaddingRightInitial = paddingHorizontal;
6065             }
6066             if (paddingVertical >= 0) {
6067                 topPadding = paddingVertical;
6068                 bottomPadding = paddingVertical;
6069             }
6070         }
6071 
6072         if (isRtlCompatibilityMode()) {
6073             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6074             // left / right padding are used if defined (meaning here nothing to do). If they are not
6075             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6076             // start / end and resolve them as left / right (layout direction is not taken into account).
6077             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6078             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6079             // defined.
6080             if (!mLeftPaddingDefined && startPaddingDefined) {
6081                 leftPadding = startPadding;
6082             }
6083             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6084             if (!mRightPaddingDefined && endPaddingDefined) {
6085                 rightPadding = endPadding;
6086             }
6087             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6088         } else {
6089             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6090             // values defined. Otherwise, left /right values are used.
6091             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6092             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6093             // defined.
6094             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6095 
6096             if (mLeftPaddingDefined && !hasRelativePadding) {
6097                 mUserPaddingLeftInitial = leftPadding;
6098             }
6099             if (mRightPaddingDefined && !hasRelativePadding) {
6100                 mUserPaddingRightInitial = rightPadding;
6101             }
6102         }
6103 
6104         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6105         // them on if topPadding or bottomPadding are not valid.
6106         internalSetPadding(
6107                 mUserPaddingLeftInitial,
6108                 topPadding >= 0 ? topPadding : mPaddingTop,
6109                 mUserPaddingRightInitial,
6110                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6111 
6112         if (viewFlagMasks != 0) {
6113             setFlags(viewFlagValues, viewFlagMasks);
6114         }
6115 
6116         if (initializeScrollbars) {
6117             initializeScrollbarsInternal(a);
6118         }
6119 
6120         if (initializeScrollIndicators) {
6121             initializeScrollIndicatorsInternal();
6122         }
6123 
6124         a.recycle();
6125 
6126         // Needs to be called after mViewFlags is set
6127         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6128             recomputePadding();
6129         }
6130 
6131         if (x != 0 || y != 0) {
6132             scrollTo(x, y);
6133         }
6134 
6135         if (transformSet) {
6136             setTranslationX(tx);
6137             setTranslationY(ty);
6138             setTranslationZ(tz);
6139             setElevation(elevation);
6140             setRotation(rotation);
6141             setRotationX(rotationX);
6142             setRotationY(rotationY);
6143             setScaleX(sx);
6144             setScaleY(sy);
6145         }
6146 
6147         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6148             setScrollContainer(true);
6149         }
6150 
6151         computeOpaqueFlags();
6152     }
6153 
6154     /**
6155      * Returns the ordered list of resource ID that are considered when resolving attribute values
6156      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6157      * XML. It will also include a set of explicit styles if specified in XML using
6158      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6159      *
6160      * <p>
6161      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6162      * is enabled in Android developer options.
6163      *
6164      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6165      * @return ordered list of resource ID that are considered when resolving attribute values for
6166      * this {@link View}.
6167      */
6168     @NonNull
6169     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6170         if (!sDebugViewAttributes
6171                 || mAttributeResolutionStacks == null
6172                 || mAttributeResolutionStacks.get(attribute) == null) {
6173             return new int[0];
6174         }
6175         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6176         int stackSize = attributeResolutionStack.length;
6177         if (mSourceLayoutId != ID_NULL) {
6178             stackSize++;
6179         }
6180 
6181         int currentIndex = 0;
6182         int[] stack = new int[stackSize];
6183 
6184         if (mSourceLayoutId != ID_NULL) {
6185             stack[currentIndex] = mSourceLayoutId;
6186             currentIndex++;
6187         }
6188         for (int i = 0; i < attributeResolutionStack.length; i++) {
6189             stack[currentIndex] = attributeResolutionStack[i];
6190             currentIndex++;
6191         }
6192         return stack;
6193     }
6194 
6195     /**
6196      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6197      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6198      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6199      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6200      *
6201      * <p>
6202      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6203      * is enabled in Android developer options.
6204      *
6205      * @return mapping of attribute resource ID to source resource ID where the attribute value
6206      * was set.
6207      */
6208     @NonNull
6209     @SuppressWarnings("AndroidFrameworkEfficientCollections")
6210     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6211         HashMap<Integer, Integer> map = new HashMap<>();
6212         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6213             return map;
6214         }
6215         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6216             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6217         }
6218         return map;
6219     }
6220 
6221     /**
6222      * Returns the resource ID for the style specified using {@code style="..."} in the
6223      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6224      * specified or otherwise not applicable.
6225      * <p>
6226      * Each {@link View} can have an explicit style specified in the layout file.
6227      * This style is used first during the {@link View} attribute resolution, then if an attribute
6228      * is not defined there the resource system looks at default style and theme as fallbacks.
6229      *
6230      * <p>
6231      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6232      * is enabled in Android developer options.
6233      *
6234      * @return The resource ID for the style specified using {@code style="..."} in the
6235      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6236      *      if not specified or otherwise not applicable.
6237      */
6238     @StyleRes
6239     public int getExplicitStyle() {
6240         if (!sDebugViewAttributes) {
6241             return ID_NULL;
6242         }
6243         return mExplicitStyle;
6244     }
6245 
6246     /**
6247      * An implementation of OnClickListener that attempts to lazily load a
6248      * named click handling method from a parent or ancestor context.
6249      */
6250     private static class DeclaredOnClickListener implements OnClickListener {
6251         private final View mHostView;
6252         private final String mMethodName;
6253 
6254         private Method mResolvedMethod;
6255         private Context mResolvedContext;
6256 
6257         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6258             mHostView = hostView;
6259             mMethodName = methodName;
6260         }
6261 
6262         @Override
6263         public void onClick(@NonNull View v) {
6264             if (mResolvedMethod == null) {
6265                 resolveMethod(mHostView.getContext(), mMethodName);
6266             }
6267 
6268             try {
6269                 mResolvedMethod.invoke(mResolvedContext, v);
6270             } catch (IllegalAccessException e) {
6271                 throw new IllegalStateException(
6272                         "Could not execute non-public method for android:onClick", e);
6273             } catch (InvocationTargetException e) {
6274                 throw new IllegalStateException(
6275                         "Could not execute method for android:onClick", e);
6276             }
6277         }
6278 
6279         @NonNull
6280         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6281             while (context != null) {
6282                 try {
6283                     if (!context.isRestricted()) {
6284                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6285                         if (method != null) {
6286                             mResolvedMethod = method;
6287                             mResolvedContext = context;
6288                             return;
6289                         }
6290                     }
6291                 } catch (NoSuchMethodException e) {
6292                     // Failed to find method, keep searching up the hierarchy.
6293                 }
6294 
6295                 if (context instanceof ContextWrapper) {
6296                     context = ((ContextWrapper) context).getBaseContext();
6297                 } else {
6298                     // Can't search up the hierarchy, null out and fail.
6299                     context = null;
6300                 }
6301             }
6302 
6303             final int id = mHostView.getId();
6304             final String idText = id == NO_ID ? "" : " with id '"
6305                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6306             throw new IllegalStateException("Could not find method " + mMethodName
6307                     + "(View) in a parent or ancestor Context for android:onClick "
6308                     + "attribute defined on view " + mHostView.getClass() + idText);
6309         }
6310     }
6311 
6312     /**
6313      * Non-public constructor for use in testing
6314      */
6315     @UnsupportedAppUsage
6316     View() {
6317         mResources = null;
6318         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6319     }
6320 
6321     /**
6322      * Returns {@code true} when the View is attached and the system developer setting to show
6323      * the layout bounds is enabled or {@code false} otherwise.
6324      */
6325     public final boolean isShowingLayoutBounds() {
6326         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6327     }
6328 
6329     /**
6330      * Used to test isShowingLayoutBounds(). This sets the local value used
6331      * by that function. This method does nothing if the layout isn't attached.
6332      *
6333      * @hide
6334      */
6335     @TestApi
6336     public final void setShowingLayoutBounds(boolean debugLayout) {
6337         if (mAttachInfo != null) {
6338             mAttachInfo.mDebugLayout = debugLayout;
6339         }
6340     }
6341 
6342     private static SparseArray<String> getAttributeMap() {
6343         if (mAttributeMap == null) {
6344             mAttributeMap = new SparseArray<>();
6345         }
6346         return mAttributeMap;
6347     }
6348 
6349     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6350             @Nullable AttributeSet attrs) {
6351         if (!sDebugViewAttributes) {
6352             return;
6353         }
6354         mExplicitStyle = theme.getExplicitStyle(attrs);
6355     }
6356 
6357     /**
6358      * Stores debugging information about attributes. This should be called in a constructor by
6359      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6360      * then the custom attributes used by this view will not be visible in layout inspection tools.
6361      *
6362      *  @param context Context under which this view is created.
6363      * @param styleable A reference to styleable array R.styleable.Foo
6364      * @param attrs AttributeSet used to construct this view.
6365      * @param t Resolved {@link TypedArray} returned by a call to
6366      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6367      * @param defStyleAttr Default style attribute passed into the view constructor.
6368      * @param defStyleRes Default style resource passed into the view constructor.
6369      */
6370     public final void saveAttributeDataForStyleable(@NonNull Context context,
6371             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6372             int defStyleAttr, int defStyleRes) {
6373         if (!sDebugViewAttributes) {
6374             return;
6375         }
6376 
6377         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6378                 defStyleAttr, defStyleRes, mExplicitStyle);
6379 
6380         if (mAttributeResolutionStacks == null) {
6381             mAttributeResolutionStacks = new SparseArray<>();
6382         }
6383 
6384         if (mAttributeSourceResId == null) {
6385             mAttributeSourceResId = new SparseIntArray();
6386         }
6387 
6388         final int indexCount = t.getIndexCount();
6389         for (int j = 0; j < indexCount; ++j) {
6390             final int index = t.getIndex(j);
6391             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6392             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6393         }
6394     }
6395 
6396     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6397         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6398         final int indexCount = t.getIndexCount();
6399         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6400 
6401         int i = 0;
6402 
6403         // Store raw XML attributes.
6404         for (int j = 0; j < attrsCount; ++j) {
6405             attributes[i] = attrs.getAttributeName(j);
6406             attributes[i + 1] = attrs.getAttributeValue(j);
6407             i += 2;
6408         }
6409 
6410         // Store resolved styleable attributes.
6411         final Resources res = t.getResources();
6412         final SparseArray<String> attributeMap = getAttributeMap();
6413         for (int j = 0; j < indexCount; ++j) {
6414             final int index = t.getIndex(j);
6415             if (!t.hasValueOrEmpty(index)) {
6416                 // Value is undefined. Skip it.
6417                 continue;
6418             }
6419 
6420             final int resourceId = t.getResourceId(index, 0);
6421             if (resourceId == 0) {
6422                 // Value is not a reference. Skip it.
6423                 continue;
6424             }
6425 
6426             String resourceName = attributeMap.get(resourceId);
6427             if (resourceName == null) {
6428                 try {
6429                     resourceName = res.getResourceName(resourceId);
6430                 } catch (Resources.NotFoundException e) {
6431                     resourceName = "0x" + Integer.toHexString(resourceId);
6432                 }
6433                 attributeMap.put(resourceId, resourceName);
6434             }
6435 
6436             attributes[i] = resourceName;
6437             attributes[i + 1] = t.getString(index);
6438             i += 2;
6439         }
6440 
6441         // Trim to fit contents.
6442         final String[] trimmed = new String[i];
6443         System.arraycopy(attributes, 0, trimmed, 0, i);
6444         mAttributes = trimmed;
6445     }
6446 
6447     @Override
6448     public String toString() {
6449         StringBuilder out = new StringBuilder(128);
6450         out.append(getClass().getName());
6451         out.append('{');
6452         out.append(Integer.toHexString(System.identityHashCode(this)));
6453         out.append(' ');
6454         switch (mViewFlags&VISIBILITY_MASK) {
6455             case VISIBLE: out.append('V'); break;
6456             case INVISIBLE: out.append('I'); break;
6457             case GONE: out.append('G'); break;
6458             default: out.append('.'); break;
6459         }
6460         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6461         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6462         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6463         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6464         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6465         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6466         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6467         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6468         out.append(' ');
6469         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6470         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6471         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6472         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6473             out.append('p');
6474         } else {
6475             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6476         }
6477         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6478         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6479         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6480         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6481         out.append(' ');
6482         out.append(mLeft);
6483         out.append(',');
6484         out.append(mTop);
6485         out.append('-');
6486         out.append(mRight);
6487         out.append(',');
6488         out.append(mBottom);
6489         final int id = getId();
6490         if (id != NO_ID) {
6491             out.append(" #");
6492             out.append(Integer.toHexString(id));
6493             final Resources r = mResources;
6494             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6495                 try {
6496                     String pkgname;
6497                     switch (id&0xff000000) {
6498                         case 0x7f000000:
6499                             pkgname="app";
6500                             break;
6501                         case 0x01000000:
6502                             pkgname="android";
6503                             break;
6504                         default:
6505                             pkgname = r.getResourcePackageName(id);
6506                             break;
6507                     }
6508                     String typename = r.getResourceTypeName(id);
6509                     String entryname = r.getResourceEntryName(id);
6510                     out.append(" ");
6511                     out.append(pkgname);
6512                     out.append(":");
6513                     out.append(typename);
6514                     out.append("/");
6515                     out.append(entryname);
6516                 } catch (Resources.NotFoundException e) {
6517                 }
6518             }
6519         }
6520         if (mAutofillId != null) {
6521             out.append(" aid="); out.append(mAutofillId);
6522         }
6523         out.append("}");
6524         return out.toString();
6525     }
6526 
6527     /**
6528      * <p>
6529      * Initializes the fading edges from a given set of styled attributes. This
6530      * method should be called by subclasses that need fading edges and when an
6531      * instance of these subclasses is created programmatically rather than
6532      * being inflated from XML. This method is automatically called when the XML
6533      * is inflated.
6534      * </p>
6535      *
6536      * @param a the styled attributes set to initialize the fading edges from
6537      *
6538      * @removed
6539      */
6540     protected void initializeFadingEdge(TypedArray a) {
6541         // This method probably shouldn't have been included in the SDK to begin with.
6542         // It relies on 'a' having been initialized using an attribute filter array that is
6543         // not publicly available to the SDK. The old method has been renamed
6544         // to initializeFadingEdgeInternal and hidden for framework use only;
6545         // this one initializes using defaults to make it safe to call for apps.
6546 
6547         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6548 
6549         initializeFadingEdgeInternal(arr);
6550 
6551         arr.recycle();
6552     }
6553 
6554     /**
6555      * <p>
6556      * Initializes the fading edges from a given set of styled attributes. This
6557      * method should be called by subclasses that need fading edges and when an
6558      * instance of these subclasses is created programmatically rather than
6559      * being inflated from XML. This method is automatically called when the XML
6560      * is inflated.
6561      * </p>
6562      *
6563      * @param a the styled attributes set to initialize the fading edges from
6564      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6565      */
6566     protected void initializeFadingEdgeInternal(TypedArray a) {
6567         initScrollCache();
6568 
6569         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6570                 R.styleable.View_fadingEdgeLength,
6571                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6572     }
6573 
6574     /**
6575      * Returns the size of the vertical faded edges used to indicate that more
6576      * content in this view is visible.
6577      *
6578      * @return The size in pixels of the vertical faded edge or 0 if vertical
6579      *         faded edges are not enabled for this view.
6580      * @attr ref android.R.styleable#View_fadingEdgeLength
6581      */
6582     public int getVerticalFadingEdgeLength() {
6583         if (isVerticalFadingEdgeEnabled()) {
6584             ScrollabilityCache cache = mScrollCache;
6585             if (cache != null) {
6586                 return cache.fadingEdgeLength;
6587             }
6588         }
6589         return 0;
6590     }
6591 
6592     /**
6593      * Set the size of the faded edge used to indicate that more content in this
6594      * view is available.  Will not change whether the fading edge is enabled; use
6595      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6596      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6597      * for the vertical or horizontal fading edges.
6598      *
6599      * @param length The size in pixels of the faded edge used to indicate that more
6600      *        content in this view is visible.
6601      */
6602     public void setFadingEdgeLength(int length) {
6603         initScrollCache();
6604         mScrollCache.fadingEdgeLength = length;
6605     }
6606 
6607     /**
6608      * Returns the size of the horizontal faded edges used to indicate that more
6609      * content in this view is visible.
6610      *
6611      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6612      *         faded edges are not enabled for this view.
6613      * @attr ref android.R.styleable#View_fadingEdgeLength
6614      */
6615     public int getHorizontalFadingEdgeLength() {
6616         if (isHorizontalFadingEdgeEnabled()) {
6617             ScrollabilityCache cache = mScrollCache;
6618             if (cache != null) {
6619                 return cache.fadingEdgeLength;
6620             }
6621         }
6622         return 0;
6623     }
6624 
6625     /**
6626      * Returns the width of the vertical scrollbar.
6627      *
6628      * @return The width in pixels of the vertical scrollbar or 0 if there
6629      *         is no vertical scrollbar.
6630      */
6631     public int getVerticalScrollbarWidth() {
6632         ScrollabilityCache cache = mScrollCache;
6633         if (cache != null) {
6634             ScrollBarDrawable scrollBar = cache.scrollBar;
6635             if (scrollBar != null) {
6636                 int size = scrollBar.getSize(true);
6637                 if (size <= 0) {
6638                     size = cache.scrollBarSize;
6639                 }
6640                 return size;
6641             }
6642             return 0;
6643         }
6644         return 0;
6645     }
6646 
6647     /**
6648      * Returns the height of the horizontal scrollbar.
6649      *
6650      * @return The height in pixels of the horizontal scrollbar or 0 if
6651      *         there is no horizontal scrollbar.
6652      */
6653     protected int getHorizontalScrollbarHeight() {
6654         ScrollabilityCache cache = mScrollCache;
6655         if (cache != null) {
6656             ScrollBarDrawable scrollBar = cache.scrollBar;
6657             if (scrollBar != null) {
6658                 int size = scrollBar.getSize(false);
6659                 if (size <= 0) {
6660                     size = cache.scrollBarSize;
6661                 }
6662                 return size;
6663             }
6664             return 0;
6665         }
6666         return 0;
6667     }
6668 
6669     /**
6670      * <p>
6671      * Initializes the scrollbars from a given set of styled attributes. This
6672      * method should be called by subclasses that need scrollbars and when an
6673      * instance of these subclasses is created programmatically rather than
6674      * being inflated from XML. This method is automatically called when the XML
6675      * is inflated.
6676      * </p>
6677      *
6678      * @param a the styled attributes set to initialize the scrollbars from
6679      *
6680      * @removed
6681      */
6682     protected void initializeScrollbars(TypedArray a) {
6683         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6684         // using the View filter array which is not available to the SDK. As such, internal
6685         // framework usage now uses initializeScrollbarsInternal and we grab a default
6686         // TypedArray with the right filter instead here.
6687         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6688 
6689         initializeScrollbarsInternal(arr);
6690 
6691         // We ignored the method parameter. Recycle the one we actually did use.
6692         arr.recycle();
6693     }
6694 
6695     private void initializeScrollBarDrawable() {
6696         initScrollCache();
6697 
6698         if (mScrollCache.scrollBar == null) {
6699             mScrollCache.scrollBar = new ScrollBarDrawable();
6700             mScrollCache.scrollBar.setState(getDrawableState());
6701             mScrollCache.scrollBar.setCallback(this);
6702         }
6703     }
6704 
6705     /**
6706      * <p>
6707      * Initializes the scrollbars from a given set of styled attributes. This
6708      * method should be called by subclasses that need scrollbars and when an
6709      * instance of these subclasses is created programmatically rather than
6710      * being inflated from XML. This method is automatically called when the XML
6711      * is inflated.
6712      * </p>
6713      *
6714      * @param a the styled attributes set to initialize the scrollbars from
6715      * @hide
6716      */
6717     @UnsupportedAppUsage
6718     protected void initializeScrollbarsInternal(TypedArray a) {
6719         initScrollCache();
6720 
6721         final ScrollabilityCache scrollabilityCache = mScrollCache;
6722 
6723         if (scrollabilityCache.scrollBar == null) {
6724             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6725             scrollabilityCache.scrollBar.setState(getDrawableState());
6726             scrollabilityCache.scrollBar.setCallback(this);
6727         }
6728 
6729         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6730 
6731         if (!fadeScrollbars) {
6732             scrollabilityCache.state = ScrollabilityCache.ON;
6733         }
6734         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6735 
6736 
6737         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6738                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6739                         .getScrollBarFadeDuration());
6740         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6741                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6742                 ViewConfiguration.getScrollDefaultDelay());
6743 
6744 
6745         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6746                 com.android.internal.R.styleable.View_scrollbarSize,
6747                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6748 
6749         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6750         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6751 
6752         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6753         if (thumb != null) {
6754             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6755         }
6756 
6757         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6758                 false);
6759         if (alwaysDraw) {
6760             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6761         }
6762 
6763         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6764         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6765 
6766         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6767         if (thumb != null) {
6768             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6769         }
6770 
6771         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6772                 false);
6773         if (alwaysDraw) {
6774             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6775         }
6776 
6777         // Apply layout direction to the new Drawables if needed
6778         final int layoutDirection = getLayoutDirection();
6779         if (track != null) {
6780             track.setLayoutDirection(layoutDirection);
6781         }
6782         if (thumb != null) {
6783             thumb.setLayoutDirection(layoutDirection);
6784         }
6785 
6786         // Re-apply user/background padding so that scrollbar(s) get added
6787         resolvePadding();
6788     }
6789 
6790     /**
6791      * Defines the vertical scrollbar thumb drawable
6792      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6793      *
6794      * @see #awakenScrollBars(int)
6795      * @see #isVerticalScrollBarEnabled()
6796      * @see #setVerticalScrollBarEnabled(boolean)
6797      */
6798     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6799         initializeScrollBarDrawable();
6800         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
6801     }
6802 
6803     /**
6804      * Defines the vertical scrollbar track drawable
6805      * @attr ref android.R.styleable#View_scrollbarTrackVertical
6806      *
6807      * @see #awakenScrollBars(int)
6808      * @see #isVerticalScrollBarEnabled()
6809      * @see #setVerticalScrollBarEnabled(boolean)
6810      */
6811     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6812         initializeScrollBarDrawable();
6813         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
6814     }
6815 
6816     /**
6817      * Defines the horizontal thumb drawable
6818      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
6819      *
6820      * @see #awakenScrollBars(int)
6821      * @see #isHorizontalScrollBarEnabled()
6822      * @see #setHorizontalScrollBarEnabled(boolean)
6823      */
6824     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6825         initializeScrollBarDrawable();
6826         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
6827     }
6828 
6829     /**
6830      * Defines the horizontal track drawable
6831      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
6832      *
6833      * @see #awakenScrollBars(int)
6834      * @see #isHorizontalScrollBarEnabled()
6835      * @see #setHorizontalScrollBarEnabled(boolean)
6836      */
6837     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6838         initializeScrollBarDrawable();
6839         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
6840     }
6841 
6842     /**
6843      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
6844      * exists, null otherwise.
6845      *
6846      * @see #awakenScrollBars(int)
6847      * @see #isVerticalScrollBarEnabled()
6848      * @see #setVerticalScrollBarEnabled(boolean)
6849      */
6850     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
6851         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
6852     }
6853 
6854     /**
6855      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
6856      * exists, null otherwise.
6857      *
6858      * @see #awakenScrollBars(int)
6859      * @see #isVerticalScrollBarEnabled()
6860      * @see #setVerticalScrollBarEnabled(boolean)
6861      */
6862     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
6863         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
6864     }
6865 
6866     /**
6867      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
6868      * exists, null otherwise.
6869      *
6870      * @see #awakenScrollBars(int)
6871      * @see #isHorizontalScrollBarEnabled()
6872      * @see #setHorizontalScrollBarEnabled(boolean)
6873      */
6874     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
6875         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
6876     }
6877 
6878     /**
6879      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
6880      * exists, null otherwise.
6881      *
6882      * @see #awakenScrollBars(int)
6883      * @see #isHorizontalScrollBarEnabled()
6884      * @see #setHorizontalScrollBarEnabled(boolean)
6885      */
6886     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
6887         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
6888     }
6889 
6890     private void initializeScrollIndicatorsInternal() {
6891         // Some day maybe we'll break this into top/left/start/etc. and let the
6892         // client control it. Until then, you can have any scroll indicator you
6893         // want as long as it's a 1dp foreground-colored rectangle.
6894         if (mScrollIndicatorDrawable == null) {
6895             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6896         }
6897     }
6898 
6899     /**
6900      * <p>
6901      * Initalizes the scrollability cache if necessary.
6902      * </p>
6903      */
6904     private void initScrollCache() {
6905         if (mScrollCache == null) {
6906             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6907         }
6908     }
6909 
6910     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
6911     private ScrollabilityCache getScrollCache() {
6912         initScrollCache();
6913         return mScrollCache;
6914     }
6915 
6916     /**
6917      * Set the position of the vertical scroll bar. Should be one of
6918      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
6919      * {@link #SCROLLBAR_POSITION_RIGHT}.
6920      *
6921      * @param position Where the vertical scroll bar should be positioned.
6922      */
6923     public void setVerticalScrollbarPosition(int position) {
6924         if (mVerticalScrollbarPosition != position) {
6925             mVerticalScrollbarPosition = position;
6926             computeOpaqueFlags();
6927             resolvePadding();
6928         }
6929     }
6930 
6931     /**
6932      * @return The position where the vertical scroll bar will show, if applicable.
6933      * @see #setVerticalScrollbarPosition(int)
6934      */
6935     public int getVerticalScrollbarPosition() {
6936         return mVerticalScrollbarPosition;
6937     }
6938 
6939     boolean isOnScrollbar(float x, float y) {
6940         if (mScrollCache == null) {
6941             return false;
6942         }
6943         x += getScrollX();
6944         y += getScrollY();
6945         final boolean canScrollVertically =
6946                 computeVerticalScrollRange() > computeVerticalScrollExtent();
6947         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
6948             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6949             getVerticalScrollBarBounds(null, touchBounds);
6950             if (touchBounds.contains((int) x, (int) y)) {
6951                 return true;
6952             }
6953         }
6954         final boolean canScrollHorizontally =
6955                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
6956         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
6957             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6958             getHorizontalScrollBarBounds(null, touchBounds);
6959             if (touchBounds.contains((int) x, (int) y)) {
6960                 return true;
6961             }
6962         }
6963         return false;
6964     }
6965 
6966     @UnsupportedAppUsage
6967     boolean isOnScrollbarThumb(float x, float y) {
6968         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
6969     }
6970 
6971     private boolean isOnVerticalScrollbarThumb(float x, float y) {
6972         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
6973             return false;
6974         }
6975         final int range = computeVerticalScrollRange();
6976         final int extent = computeVerticalScrollExtent();
6977         if (range > extent) {
6978             x += getScrollX();
6979             y += getScrollY();
6980             final Rect bounds = mScrollCache.mScrollBarBounds;
6981             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6982             getVerticalScrollBarBounds(bounds, touchBounds);
6983             final int offset = computeVerticalScrollOffset();
6984             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
6985                     extent, range);
6986             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
6987                     extent, range, offset);
6988             final int thumbTop = bounds.top + thumbOffset;
6989             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6990             if (x >= touchBounds.left && x <= touchBounds.right
6991                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
6992                 return true;
6993             }
6994         }
6995         return false;
6996     }
6997 
6998     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
6999         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
7000             return false;
7001         }
7002         final int range = computeHorizontalScrollRange();
7003         final int extent = computeHorizontalScrollExtent();
7004         if (range > extent) {
7005             x += getScrollX();
7006             y += getScrollY();
7007             final Rect bounds = mScrollCache.mScrollBarBounds;
7008             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7009             getHorizontalScrollBarBounds(bounds, touchBounds);
7010             final int offset = computeHorizontalScrollOffset();
7011 
7012             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
7013                     extent, range);
7014             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7015                     extent, range, offset);
7016             final int thumbLeft = bounds.left + thumbOffset;
7017             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7018             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7019                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7020                 return true;
7021             }
7022         }
7023         return false;
7024     }
7025 
7026     @UnsupportedAppUsage
7027     boolean isDraggingScrollBar() {
7028         return mScrollCache != null
7029                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7030     }
7031 
7032     /**
7033      * Sets the state of all scroll indicators.
7034      * <p>
7035      * See {@link #setScrollIndicators(int, int)} for usage information.
7036      *
7037      * @param indicators a bitmask of indicators that should be enabled, or
7038      *                   {@code 0} to disable all indicators
7039      * @see #setScrollIndicators(int, int)
7040      * @see #getScrollIndicators()
7041      * @attr ref android.R.styleable#View_scrollIndicators
7042      */
7043     @RemotableViewMethod
7044     public void setScrollIndicators(@ScrollIndicators int indicators) {
7045         setScrollIndicators(indicators,
7046                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7047     }
7048 
7049     /**
7050      * Sets the state of the scroll indicators specified by the mask. To change
7051      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7052      * <p>
7053      * When a scroll indicator is enabled, it will be displayed if the view
7054      * can scroll in the direction of the indicator.
7055      * <p>
7056      * Multiple indicator types may be enabled or disabled by passing the
7057      * logical OR of the desired types. If multiple types are specified, they
7058      * will all be set to the same enabled state.
7059      * <p>
7060      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7061      *
7062      * @param indicators the indicator direction, or the logical OR of multiple
7063      *             indicator directions. One or more of:
7064      *             <ul>
7065      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7066      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7067      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7068      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7069      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7070      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7071      *             </ul>
7072      * @see #setScrollIndicators(int)
7073      * @see #getScrollIndicators()
7074      * @attr ref android.R.styleable#View_scrollIndicators
7075      */
7076     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7077         // Shift and sanitize mask.
7078         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7079         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7080 
7081         // Shift and mask indicators.
7082         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7083         indicators &= mask;
7084 
7085         // Merge with non-masked flags.
7086         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7087 
7088         if (mPrivateFlags3 != updatedFlags) {
7089             mPrivateFlags3 = updatedFlags;
7090 
7091             if (indicators != 0) {
7092                 initializeScrollIndicatorsInternal();
7093             }
7094             invalidate();
7095         }
7096     }
7097 
7098     /**
7099      * Returns a bitmask representing the enabled scroll indicators.
7100      * <p>
7101      * For example, if the top and left scroll indicators are enabled and all
7102      * other indicators are disabled, the return value will be
7103      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7104      * <p>
7105      * To check whether the bottom scroll indicator is enabled, use the value
7106      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7107      *
7108      * @return a bitmask representing the enabled scroll indicators
7109      */
7110     @InspectableProperty(flagMapping = {
7111             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7112             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7113             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7114             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7115             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7116             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7117             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7118     })
7119     @ScrollIndicators
7120     public int getScrollIndicators() {
7121         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7122                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7123     }
7124 
7125     @UnsupportedAppUsage
7126     ListenerInfo getListenerInfo() {
7127         if (mListenerInfo != null) {
7128             return mListenerInfo;
7129         }
7130         mListenerInfo = new ListenerInfo();
7131         return mListenerInfo;
7132     }
7133 
7134     /**
7135      * Register a callback to be invoked when the scroll X or Y positions of
7136      * this view change.
7137      * <p>
7138      * <b>Note:</b> Some views handle scrolling independently from View and may
7139      * have their own separate listeners for scroll-type events. For example,
7140      * {@link android.widget.ListView ListView} allows clients to register an
7141      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7142      * to listen for changes in list scroll position.
7143      *
7144      * @param l The listener to notify when the scroll X or Y position changes.
7145      * @see android.view.View#getScrollX()
7146      * @see android.view.View#getScrollY()
7147      */
7148     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7149         getListenerInfo().mOnScrollChangeListener = l;
7150     }
7151 
7152     /**
7153      * Register a callback to be invoked when focus of this view changed.
7154      *
7155      * @param l The callback that will run.
7156      */
7157     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7158         getListenerInfo().mOnFocusChangeListener = l;
7159     }
7160 
7161     /**
7162      * Add a listener that will be called when the bounds of the view change due to
7163      * layout processing.
7164      *
7165      * @param listener The listener that will be called when layout bounds change.
7166      */
7167     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7168         ListenerInfo li = getListenerInfo();
7169         if (li.mOnLayoutChangeListeners == null) {
7170             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7171         }
7172         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7173             li.mOnLayoutChangeListeners.add(listener);
7174         }
7175     }
7176 
7177     /**
7178      * Remove a listener for layout changes.
7179      *
7180      * @param listener The listener for layout bounds change.
7181      */
7182     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7183         ListenerInfo li = mListenerInfo;
7184         if (li == null || li.mOnLayoutChangeListeners == null) {
7185             return;
7186         }
7187         li.mOnLayoutChangeListeners.remove(listener);
7188     }
7189 
7190     /**
7191      * Add a listener for attach state changes.
7192      *
7193      * This listener will be called whenever this view is attached or detached
7194      * from a window. Remove the listener using
7195      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7196      *
7197      * @param listener Listener to attach
7198      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7199      */
7200     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7201         ListenerInfo li = getListenerInfo();
7202         if (li.mOnAttachStateChangeListeners == null) {
7203             li.mOnAttachStateChangeListeners
7204                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7205         }
7206         li.mOnAttachStateChangeListeners.add(listener);
7207     }
7208 
7209     /**
7210      * Remove a listener for attach state changes. The listener will receive no further
7211      * notification of window attach/detach events.
7212      *
7213      * @param listener Listener to remove
7214      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7215      */
7216     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7217         ListenerInfo li = mListenerInfo;
7218         if (li == null || li.mOnAttachStateChangeListeners == null) {
7219             return;
7220         }
7221         li.mOnAttachStateChangeListeners.remove(listener);
7222     }
7223 
7224     /**
7225      * Returns the focus-change callback registered for this view.
7226      *
7227      * @return The callback, or null if one is not registered.
7228      */
7229     public OnFocusChangeListener getOnFocusChangeListener() {
7230         ListenerInfo li = mListenerInfo;
7231         return li != null ? li.mOnFocusChangeListener : null;
7232     }
7233 
7234     /**
7235      * Register a callback to be invoked when this view is clicked. If this view is not
7236      * clickable, it becomes clickable.
7237      *
7238      * @param l The callback that will run
7239      *
7240      * @see #setClickable(boolean)
7241      */
7242     public void setOnClickListener(@Nullable OnClickListener l) {
7243         if (!isClickable()) {
7244             setClickable(true);
7245         }
7246         getListenerInfo().mOnClickListener = l;
7247     }
7248 
7249     /**
7250      * Return whether this view has an attached OnClickListener.  Returns
7251      * true if there is a listener, false if there is none.
7252      */
7253     public boolean hasOnClickListeners() {
7254         ListenerInfo li = mListenerInfo;
7255         return (li != null && li.mOnClickListener != null);
7256     }
7257 
7258     /**
7259      * Register a callback to be invoked when this view is clicked and held. If this view is not
7260      * long clickable, it becomes long clickable.
7261      *
7262      * @param l The callback that will run
7263      *
7264      * @see #setLongClickable(boolean)
7265      */
7266     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7267         if (!isLongClickable()) {
7268             setLongClickable(true);
7269         }
7270         getListenerInfo().mOnLongClickListener = l;
7271     }
7272 
7273     /**
7274      * Return whether this view has an attached OnLongClickListener.  Returns
7275      * true if there is a listener, false if there is none.
7276      */
7277     public boolean hasOnLongClickListeners() {
7278         ListenerInfo li = mListenerInfo;
7279         return (li != null && li.mOnLongClickListener != null);
7280     }
7281 
7282     /**
7283      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7284      * @hide
7285      */
7286     @Nullable
7287     public OnLongClickListener getOnLongClickListener() {
7288         ListenerInfo li = mListenerInfo;
7289         return (li != null) ? li.mOnLongClickListener : null;
7290     }
7291 
7292     /**
7293      * Register a callback to be invoked when this view is context clicked. If the view is not
7294      * context clickable, it becomes context clickable.
7295      *
7296      * @param l The callback that will run
7297      * @see #setContextClickable(boolean)
7298      */
7299     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7300         if (!isContextClickable()) {
7301             setContextClickable(true);
7302         }
7303         getListenerInfo().mOnContextClickListener = l;
7304     }
7305 
7306     /**
7307      * Register a callback to be invoked when the context menu for this view is
7308      * being built. If this view is not long clickable, it becomes long clickable.
7309      *
7310      * @param l The callback that will run
7311      *
7312      */
7313     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7314         if (!isLongClickable()) {
7315             setLongClickable(true);
7316         }
7317         getListenerInfo().mOnCreateContextMenuListener = l;
7318     }
7319 
7320     /**
7321      * Set an observer to collect stats for each frame rendered for this view.
7322      *
7323      * @hide
7324      */
7325     public void addFrameMetricsListener(Window window,
7326             Window.OnFrameMetricsAvailableListener listener,
7327             Handler handler) {
7328         if (mAttachInfo != null) {
7329             if (mAttachInfo.mThreadedRenderer != null) {
7330                 if (mFrameMetricsObservers == null) {
7331                     mFrameMetricsObservers = new ArrayList<>();
7332                 }
7333 
7334                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7335                 mFrameMetricsObservers.add(fmo);
7336                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7337             } else {
7338                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7339             }
7340         } else {
7341             if (mFrameMetricsObservers == null) {
7342                 mFrameMetricsObservers = new ArrayList<>();
7343             }
7344 
7345             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7346             mFrameMetricsObservers.add(fmo);
7347         }
7348     }
7349 
7350     /**
7351      * Remove observer configured to collect frame stats for this view.
7352      *
7353      * @hide
7354      */
7355     public void removeFrameMetricsListener(
7356             Window.OnFrameMetricsAvailableListener listener) {
7357         ThreadedRenderer renderer = getThreadedRenderer();
7358         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7359         if (fmo == null) {
7360             throw new IllegalArgumentException(
7361                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7362         }
7363 
7364         if (mFrameMetricsObservers != null) {
7365             mFrameMetricsObservers.remove(fmo);
7366             if (renderer != null) {
7367                 renderer.removeObserver(fmo.getRendererObserver());
7368             }
7369         }
7370     }
7371 
7372     private void registerPendingFrameMetricsObservers() {
7373         if (mFrameMetricsObservers != null) {
7374             ThreadedRenderer renderer = getThreadedRenderer();
7375             if (renderer != null) {
7376                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7377                     renderer.addObserver(fmo.getRendererObserver());
7378                 }
7379             } else {
7380                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7381             }
7382         }
7383     }
7384 
7385     private FrameMetricsObserver findFrameMetricsObserver(
7386             Window.OnFrameMetricsAvailableListener listener) {
7387         if (mFrameMetricsObservers != null) {
7388             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7389                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7390                 if (observer.mListener == listener) {
7391                     return observer;
7392                 }
7393             }
7394         }
7395 
7396         return null;
7397     }
7398 
7399     /** @hide */
7400     public void setNotifyAutofillManagerOnClick(boolean notify) {
7401         if (notify) {
7402             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7403         } else {
7404             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7405         }
7406     }
7407 
7408     private void notifyAutofillManagerOnClick() {
7409         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7410             try {
7411                 getAutofillManager().notifyViewClicked(this);
7412             } finally {
7413                 // Set it to already called so it's not called twice when called by
7414                 // performClickInternal()
7415                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7416             }
7417         }
7418     }
7419 
7420     /**
7421      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7422      * {@code performClick()} directly to make sure the autofill manager is notified when
7423      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7424      * method).
7425      */
7426     private boolean performClickInternal() {
7427         // Must notify autofill manager before performing the click actions to avoid scenarios where
7428         // the app has a click listener that changes the state of views the autofill service might
7429         // be interested on.
7430         notifyAutofillManagerOnClick();
7431 
7432         return performClick();
7433     }
7434 
7435     /**
7436      * Call this view's OnClickListener, if it is defined.  Performs all normal
7437      * actions associated with clicking: reporting accessibility event, playing
7438      * a sound, etc.
7439      *
7440      * @return True there was an assigned OnClickListener that was called, false
7441      *         otherwise is returned.
7442      */
7443     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7444     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7445     // could extend this method without calling super.performClick()).
7446     public boolean performClick() {
7447         // We still need to call this method to handle the cases where performClick() was called
7448         // externally, instead of through performClickInternal()
7449         notifyAutofillManagerOnClick();
7450 
7451         final boolean result;
7452         final ListenerInfo li = mListenerInfo;
7453         if (li != null && li.mOnClickListener != null) {
7454             playSoundEffect(SoundEffectConstants.CLICK);
7455             li.mOnClickListener.onClick(this);
7456             result = true;
7457         } else {
7458             result = false;
7459         }
7460 
7461         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7462 
7463         notifyEnterOrExitForAutoFillIfNeeded(true);
7464 
7465         return result;
7466     }
7467 
7468     /**
7469      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7470      * this only calls the listener, and does not do any associated clicking
7471      * actions like reporting an accessibility event.
7472      *
7473      * @return True there was an assigned OnClickListener that was called, false
7474      *         otherwise is returned.
7475      */
7476     public boolean callOnClick() {
7477         ListenerInfo li = mListenerInfo;
7478         if (li != null && li.mOnClickListener != null) {
7479             li.mOnClickListener.onClick(this);
7480             return true;
7481         }
7482         return false;
7483     }
7484 
7485     /**
7486      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7487      * context menu if the OnLongClickListener did not consume the event.
7488      *
7489      * @return {@code true} if one of the above receivers consumed the event,
7490      *         {@code false} otherwise
7491      */
7492     public boolean performLongClick() {
7493         return performLongClickInternal(mLongClickX, mLongClickY);
7494     }
7495 
7496     /**
7497      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7498      * context menu if the OnLongClickListener did not consume the event,
7499      * anchoring it to an (x,y) coordinate.
7500      *
7501      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7502      *          to disable anchoring
7503      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7504      *          to disable anchoring
7505      * @return {@code true} if one of the above receivers consumed the event,
7506      *         {@code false} otherwise
7507      */
7508     public boolean performLongClick(float x, float y) {
7509         mLongClickX = x;
7510         mLongClickY = y;
7511         final boolean handled = performLongClick();
7512         mLongClickX = Float.NaN;
7513         mLongClickY = Float.NaN;
7514         return handled;
7515     }
7516 
7517     /**
7518      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7519      * context menu if the OnLongClickListener did not consume the event,
7520      * optionally anchoring it to an (x,y) coordinate.
7521      *
7522      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7523      *          to disable anchoring
7524      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7525      *          to disable anchoring
7526      * @return {@code true} if one of the above receivers consumed the event,
7527      *         {@code false} otherwise
7528      */
7529     private boolean performLongClickInternal(float x, float y) {
7530         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7531 
7532         boolean handled = false;
7533         final ListenerInfo li = mListenerInfo;
7534         if (li != null && li.mOnLongClickListener != null) {
7535             handled = li.mOnLongClickListener.onLongClick(View.this);
7536         }
7537         if (!handled) {
7538             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7539             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7540         }
7541         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7542             if (!handled) {
7543                 handled = showLongClickTooltip((int) x, (int) y);
7544             }
7545         }
7546         if (handled) {
7547             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7548         }
7549         return handled;
7550     }
7551 
7552     /**
7553      * Call this view's OnContextClickListener, if it is defined.
7554      *
7555      * @param x the x coordinate of the context click
7556      * @param y the y coordinate of the context click
7557      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7558      *         otherwise.
7559      */
7560     public boolean performContextClick(float x, float y) {
7561         return performContextClick();
7562     }
7563 
7564     /**
7565      * Call this view's OnContextClickListener, if it is defined.
7566      *
7567      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7568      *         otherwise.
7569      */
7570     public boolean performContextClick() {
7571         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7572 
7573         boolean handled = false;
7574         ListenerInfo li = mListenerInfo;
7575         if (li != null && li.mOnContextClickListener != null) {
7576             handled = li.mOnContextClickListener.onContextClick(View.this);
7577         }
7578         if (handled) {
7579             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7580         }
7581         return handled;
7582     }
7583 
7584     /**
7585      * Performs button-related actions during a touch down event.
7586      *
7587      * @param event The event.
7588      * @return True if the down was consumed.
7589      *
7590      * @hide
7591      */
7592     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7593         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7594             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7595             showContextMenu(event.getX(), event.getY());
7596             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7597             return true;
7598         }
7599         return false;
7600     }
7601 
7602     /**
7603      * Shows the context menu for this view.
7604      *
7605      * @return {@code true} if the context menu was shown, {@code false}
7606      *         otherwise
7607      * @see #showContextMenu(float, float)
7608      */
7609     public boolean showContextMenu() {
7610         return getParent().showContextMenuForChild(this);
7611     }
7612 
7613     /**
7614      * Shows the context menu for this view anchored to the specified
7615      * view-relative coordinate.
7616      *
7617      * @param x the X coordinate in pixels relative to the view to which the
7618      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7619      * @param y the Y coordinate in pixels relative to the view to which the
7620      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7621      * @return {@code true} if the context menu was shown, {@code false}
7622      *         otherwise
7623      */
7624     public boolean showContextMenu(float x, float y) {
7625         return getParent().showContextMenuForChild(this, x, y);
7626     }
7627 
7628     /**
7629      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7630      *
7631      * @param callback Callback that will control the lifecycle of the action mode
7632      * @return The new action mode if it is started, null otherwise
7633      *
7634      * @see ActionMode
7635      * @see #startActionMode(android.view.ActionMode.Callback, int)
7636      */
7637     public ActionMode startActionMode(ActionMode.Callback callback) {
7638         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7639     }
7640 
7641     /**
7642      * Start an action mode with the given type.
7643      *
7644      * @param callback Callback that will control the lifecycle of the action mode
7645      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7646      * @return The new action mode if it is started, null otherwise
7647      *
7648      * @see ActionMode
7649      */
7650     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7651         ViewParent parent = getParent();
7652         if (parent == null) return null;
7653         try {
7654             return parent.startActionModeForChild(this, callback, type);
7655         } catch (AbstractMethodError ame) {
7656             // Older implementations of custom views might not implement this.
7657             return parent.startActionModeForChild(this, callback);
7658         }
7659     }
7660 
7661     /**
7662      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7663      * Context, creating a unique View identifier to retrieve the result.
7664      *
7665      * @param intent The Intent to be started.
7666      * @param requestCode The request code to use.
7667      * @hide
7668      */
7669     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7670     public void startActivityForResult(Intent intent, int requestCode) {
7671         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7672         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7673     }
7674 
7675     /**
7676      * If this View corresponds to the calling who, dispatches the activity result.
7677      * @param who The identifier for the targeted View to receive the result.
7678      * @param requestCode The integer request code originally supplied to
7679      *                    startActivityForResult(), allowing you to identify who this
7680      *                    result came from.
7681      * @param resultCode The integer result code returned by the child activity
7682      *                   through its setResult().
7683      * @param data An Intent, which can return result data to the caller
7684      *               (various data can be attached to Intent "extras").
7685      * @return {@code true} if the activity result was dispatched.
7686      * @hide
7687      */
7688     public boolean dispatchActivityResult(
7689             String who, int requestCode, int resultCode, Intent data) {
7690         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7691             onActivityResult(requestCode, resultCode, data);
7692             mStartActivityRequestWho = null;
7693             return true;
7694         }
7695         return false;
7696     }
7697 
7698     /**
7699      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7700      *
7701      * @param requestCode The integer request code originally supplied to
7702      *                    startActivityForResult(), allowing you to identify who this
7703      *                    result came from.
7704      * @param resultCode The integer result code returned by the child activity
7705      *                   through its setResult().
7706      * @param data An Intent, which can return result data to the caller
7707      *               (various data can be attached to Intent "extras").
7708      * @hide
7709      */
7710     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7711         // Do nothing.
7712     }
7713 
7714     /**
7715      * Register a callback to be invoked when a hardware key is pressed in this view.
7716      * Key presses in software input methods will generally not trigger the methods of
7717      * this listener.
7718      * @param l the key listener to attach to this view
7719      */
7720     public void setOnKeyListener(OnKeyListener l) {
7721         getListenerInfo().mOnKeyListener = l;
7722     }
7723 
7724     /**
7725      * Register a callback to be invoked when a touch event is sent to this view.
7726      * @param l the touch listener to attach to this view
7727      */
7728     public void setOnTouchListener(OnTouchListener l) {
7729         getListenerInfo().mOnTouchListener = l;
7730     }
7731 
7732     /**
7733      * Register a callback to be invoked when a generic motion event is sent to this view.
7734      * @param l the generic motion listener to attach to this view
7735      */
7736     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7737         getListenerInfo().mOnGenericMotionListener = l;
7738     }
7739 
7740     /**
7741      * Register a callback to be invoked when a hover event is sent to this view.
7742      * @param l the hover listener to attach to this view
7743      */
7744     public void setOnHoverListener(OnHoverListener l) {
7745         getListenerInfo().mOnHoverListener = l;
7746     }
7747 
7748     /**
7749      * Register a drag event listener callback object for this View. The parameter is
7750      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7751      * View, the system calls the
7752      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7753      * @param l An implementation of {@link android.view.View.OnDragListener}.
7754      */
7755     public void setOnDragListener(OnDragListener l) {
7756         getListenerInfo().mOnDragListener = l;
7757     }
7758 
7759     /**
7760      * Give this view focus. This will cause
7761      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7762      *
7763      * Note: this does not check whether this {@link View} should get focus, it just
7764      * gives it focus no matter what.  It should only be called internally by framework
7765      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7766      *
7767      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7768      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7769      *        focus moved when requestFocus() is called. It may not always
7770      *        apply, in which case use the default View.FOCUS_DOWN.
7771      * @param previouslyFocusedRect The rectangle of the view that had focus
7772      *        prior in this View's coordinate system.
7773      */
7774     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7775         if (DBG) {
7776             System.out.println(this + " requestFocus()");
7777         }
7778 
7779         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7780             mPrivateFlags |= PFLAG_FOCUSED;
7781 
7782             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7783 
7784             if (mParent != null) {
7785                 mParent.requestChildFocus(this, this);
7786                 updateFocusedInCluster(oldFocus, direction);
7787             }
7788 
7789             if (mAttachInfo != null) {
7790                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
7791             }
7792 
7793             onFocusChanged(true, direction, previouslyFocusedRect);
7794             refreshDrawableState();
7795         }
7796     }
7797 
7798     /**
7799      * Sets this view's preference for reveal behavior when it gains focus.
7800      *
7801      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
7802      * this view would prefer to be brought fully into view when it gains focus.
7803      * For example, a text field that a user is meant to type into. Other views such
7804      * as scrolling containers may prefer to opt-out of this behavior.</p>
7805      *
7806      * <p>The default value for views is true, though subclasses may change this
7807      * based on their preferred behavior.</p>
7808      *
7809      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
7810      *
7811      * @see #getRevealOnFocusHint()
7812      */
7813     public final void setRevealOnFocusHint(boolean revealOnFocus) {
7814         if (revealOnFocus) {
7815             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
7816         } else {
7817             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
7818         }
7819     }
7820 
7821     /**
7822      * Returns this view's preference for reveal behavior when it gains focus.
7823      *
7824      * <p>When this method returns true for a child view requesting focus, ancestor
7825      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
7826      * should make a best effort to make the newly focused child fully visible to the user.
7827      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
7828      * other properties affecting visibility to the user as part of the focus change.</p>
7829      *
7830      * @return true if this view would prefer to become fully visible when it gains focus,
7831      *         false if it would prefer not to disrupt scroll positioning
7832      *
7833      * @see #setRevealOnFocusHint(boolean)
7834      */
7835     public final boolean getRevealOnFocusHint() {
7836         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
7837     }
7838 
7839     /**
7840      * Populates <code>outRect</code> with the hotspot bounds. By default,
7841      * the hotspot bounds are identical to the screen bounds.
7842      *
7843      * @param outRect rect to populate with hotspot bounds
7844      * @hide Only for internal use by views and widgets.
7845      */
7846     public void getHotspotBounds(Rect outRect) {
7847         final Drawable background = getBackground();
7848         if (background != null) {
7849             background.getHotspotBounds(outRect);
7850         } else {
7851             getBoundsOnScreen(outRect);
7852         }
7853     }
7854 
7855     /**
7856      * Request that a rectangle of this view be visible on the screen,
7857      * scrolling if necessary just enough.
7858      *
7859      * <p>A View should call this if it maintains some notion of which part
7860      * of its content is interesting.  For example, a text editing view
7861      * should call this when its cursor moves.
7862      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7863      * It should not be affected by which part of the View is currently visible or its scroll
7864      * position.
7865      *
7866      * @param rectangle The rectangle in the View's content coordinate space
7867      * @return Whether any parent scrolled.
7868      */
7869     public boolean requestRectangleOnScreen(Rect rectangle) {
7870         return requestRectangleOnScreen(rectangle, false);
7871     }
7872 
7873     /**
7874      * Request that a rectangle of this view be visible on the screen,
7875      * scrolling if necessary just enough.
7876      *
7877      * <p>A View should call this if it maintains some notion of which part
7878      * of its content is interesting.  For example, a text editing view
7879      * should call this when its cursor moves.
7880      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7881      * It should not be affected by which part of the View is currently visible or its scroll
7882      * position.
7883      * <p>When <code>immediate</code> is set to true, scrolling will not be
7884      * animated.
7885      *
7886      * @param rectangle The rectangle in the View's content coordinate space
7887      * @param immediate True to forbid animated scrolling, false otherwise
7888      * @return Whether any parent scrolled.
7889      */
7890     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7891         if (mParent == null) {
7892             return false;
7893         }
7894 
7895         View child = this;
7896 
7897         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7898         position.set(rectangle);
7899 
7900         ViewParent parent = mParent;
7901         boolean scrolled = false;
7902         while (parent != null) {
7903             rectangle.set((int) position.left, (int) position.top,
7904                     (int) position.right, (int) position.bottom);
7905 
7906             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7907 
7908             if (!(parent instanceof View)) {
7909                 break;
7910             }
7911 
7912             // move it from child's content coordinate space to parent's content coordinate space
7913             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
7914 
7915             child = (View) parent;
7916             parent = child.getParent();
7917         }
7918 
7919         return scrolled;
7920     }
7921 
7922     /**
7923      * Called when this view wants to give up focus. If focus is cleared
7924      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
7925      * <p>
7926      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
7927      * to the first focusable View from the top after focus is cleared. Hence, if this
7928      * View is the first from the top that can take focus, then all callbacks
7929      * related to clearing focus will be invoked after which the framework will
7930      * give focus to this view.
7931      * </p>
7932      */
7933     public void clearFocus() {
7934         if (DBG) {
7935             System.out.println(this + " clearFocus()");
7936         }
7937 
7938         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
7939         clearFocusInternal(null, true, refocus);
7940     }
7941 
7942     /**
7943      * Clears focus from the view, optionally propagating the change up through
7944      * the parent hierarchy and requesting that the root view place new focus.
7945      *
7946      * @param propagate whether to propagate the change up through the parent
7947      *            hierarchy
7948      * @param refocus when propagate is true, specifies whether to request the
7949      *            root view place new focus
7950      */
7951     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
7952         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
7953             mPrivateFlags &= ~PFLAG_FOCUSED;
7954             clearParentsWantFocus();
7955 
7956             if (propagate && mParent != null) {
7957                 mParent.clearChildFocus(this);
7958             }
7959 
7960             onFocusChanged(false, 0, null);
7961             refreshDrawableState();
7962 
7963             if (propagate && (!refocus || !rootViewRequestFocus())) {
7964                 notifyGlobalFocusCleared(this);
7965             }
7966         }
7967     }
7968 
7969     void notifyGlobalFocusCleared(View oldFocus) {
7970         if (oldFocus != null && mAttachInfo != null) {
7971             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
7972         }
7973     }
7974 
7975     boolean rootViewRequestFocus() {
7976         final View root = getRootView();
7977         return root != null && root.requestFocus();
7978     }
7979 
7980     /**
7981      * Called internally by the view system when a new view is getting focus.
7982      * This is what clears the old focus.
7983      * <p>
7984      * <b>NOTE:</b> The parent view's focused child must be updated manually
7985      * after calling this method. Otherwise, the view hierarchy may be left in
7986      * an inconstent state.
7987      */
7988     void unFocus(View focused) {
7989         if (DBG) {
7990             System.out.println(this + " unFocus()");
7991         }
7992 
7993         clearFocusInternal(focused, false, false);
7994     }
7995 
7996     /**
7997      * Returns true if this view has focus itself, or is the ancestor of the
7998      * view that has focus.
7999      *
8000      * @return True if this view has or contains focus, false otherwise.
8001      */
8002     @ViewDebug.ExportedProperty(category = "focus")
8003     public boolean hasFocus() {
8004         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8005     }
8006 
8007     /**
8008      * Returns true if this view is focusable or if it contains a reachable View
8009      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
8010      * is a view whose parents do not block descendants focus.
8011      * Only {@link #VISIBLE} views are considered focusable.
8012      *
8013      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8014      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8015      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8016      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8017      * {@code false} for views not explicitly marked as focusable.
8018      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8019      * behavior.</p>
8020      *
8021      * @return {@code true} if the view is focusable or if the view contains a focusable
8022      *         view, {@code false} otherwise
8023      *
8024      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8025      * @see ViewGroup#getTouchscreenBlocksFocus()
8026      * @see #hasExplicitFocusable()
8027      */
8028     public boolean hasFocusable() {
8029         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8030     }
8031 
8032     /**
8033      * Returns true if this view is focusable or if it contains a reachable View
8034      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8035      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8036      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8037      * {@link #FOCUSABLE} are considered focusable.
8038      *
8039      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8040      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8041      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8042      * to focusable will not.</p>
8043      *
8044      * @return {@code true} if the view is focusable or if the view contains a focusable
8045      *         view, {@code false} otherwise
8046      *
8047      * @see #hasFocusable()
8048      */
8049     public boolean hasExplicitFocusable() {
8050         return hasFocusable(false, true);
8051     }
8052 
8053     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8054         if (!isFocusableInTouchMode()) {
8055             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8056                 final ViewGroup g = (ViewGroup) p;
8057                 if (g.shouldBlockFocusForTouchscreen()) {
8058                     return false;
8059                 }
8060             }
8061         }
8062 
8063         // Invisible, gone, or disabled views are never focusable.
8064         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8065                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8066             return false;
8067         }
8068 
8069         // Only use effective focusable value when allowed.
8070         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8071             return true;
8072         }
8073 
8074         return false;
8075     }
8076 
8077     /**
8078      * Called by the view system when the focus state of this view changes.
8079      * When the focus change event is caused by directional navigation, direction
8080      * and previouslyFocusedRect provide insight into where the focus is coming from.
8081      * When overriding, be sure to call up through to the super class so that
8082      * the standard focus handling will occur.
8083      *
8084      * @param gainFocus True if the View has focus; false otherwise.
8085      * @param direction The direction focus has moved when requestFocus()
8086      *                  is called to give this view focus. Values are
8087      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8088      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8089      *                  It may not always apply, in which case use the default.
8090      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8091      *        system, of the previously focused view.  If applicable, this will be
8092      *        passed in as finer grained information about where the focus is coming
8093      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8094      */
8095     @CallSuper
8096     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8097             @Nullable Rect previouslyFocusedRect) {
8098         if (gainFocus) {
8099             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8100         } else {
8101             notifyViewAccessibilityStateChangedIfNeeded(
8102                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8103         }
8104 
8105         // Here we check whether we still need the default focus highlight, and switch it on/off.
8106         switchDefaultFocusHighlight();
8107 
8108         if (!gainFocus) {
8109             if (isPressed()) {
8110                 setPressed(false);
8111             }
8112             if (hasWindowFocus()) {
8113                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8114             }
8115             onFocusLost();
8116         } else if (hasWindowFocus()) {
8117             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8118         }
8119 
8120         invalidate(true);
8121         ListenerInfo li = mListenerInfo;
8122         if (li != null && li.mOnFocusChangeListener != null) {
8123             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8124         }
8125 
8126         if (mAttachInfo != null) {
8127             mAttachInfo.mKeyDispatchState.reset(this);
8128         }
8129 
8130         if (mParent != null) {
8131             mParent.onDescendantUnbufferedRequested();
8132         }
8133 
8134         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8135     }
8136 
8137     /**
8138      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8139      *
8140      * @param hasFocus {@code true} when the {@link View} is being focused.
8141      */
8142     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8143         if (mAttachInfo == null) {
8144             return;
8145         }
8146         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8147     }
8148 
8149     /** @hide */
8150     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8151         if (canNotifyAutofillEnterExitEvent()) {
8152             AutofillManager afm = getAutofillManager();
8153             if (afm != null) {
8154                 if (enter && isFocused()) {
8155                     // We have not been laid out yet, hence cannot evaluate
8156                     // whether this view is visible to the user, we will do
8157                     // the evaluation once layout is complete.
8158                     if (!isLaidOut()) {
8159                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8160                     } else if (isVisibleToUser()) {
8161                         // TODO This is a potential problem that View gets focus before it's visible
8162                         // to User. Ideally View should handle the event when isVisibleToUser()
8163                         // becomes true where it should issue notifyViewEntered().
8164                         afm.notifyViewEntered(this);
8165                     }
8166                 } else if (!enter && !isFocused()) {
8167                     afm.notifyViewExited(this);
8168                 }
8169             }
8170         }
8171     }
8172 
8173     /**
8174      * Visually distinct portion of a window with window-like semantics are considered panes for
8175      * accessibility purposes. One example is the content view of a fragment that is replaced.
8176      * In order for accessibility services to understand a pane's window-like behavior, panes
8177      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
8178      * when they appear, disappear, or change title.
8179      *
8180      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8181      *                               View is not a pane.
8182      *
8183      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8184      *
8185      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8186      */
8187     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8188         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8189             mAccessibilityPaneTitle = accessibilityPaneTitle;
8190             notifyViewAccessibilityStateChangedIfNeeded(
8191                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8192         }
8193     }
8194 
8195     /**
8196      * Get the title of the pane for purposes of accessibility.
8197      *
8198      * @return The current pane title.
8199      *
8200      * {@see #setAccessibilityPaneTitle}.
8201      *
8202      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8203      */
8204     @InspectableProperty
8205     @Nullable
8206     public CharSequence getAccessibilityPaneTitle() {
8207         return mAccessibilityPaneTitle;
8208     }
8209 
8210     private boolean isAccessibilityPane() {
8211         return mAccessibilityPaneTitle != null;
8212     }
8213 
8214     /**
8215      * Sends an accessibility event of the given type. If accessibility is
8216      * not enabled this method has no effect. The default implementation calls
8217      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8218      * to populate information about the event source (this View), then calls
8219      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8220      * populate the text content of the event source including its descendants,
8221      * and last calls
8222      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8223      * on its parent to request sending of the event to interested parties.
8224      * <p>
8225      * If an {@link AccessibilityDelegate} has been specified via calling
8226      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8227      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8228      * responsible for handling this call.
8229      * </p>
8230      *
8231      * @param eventType The type of the event to send, as defined by several types from
8232      * {@link android.view.accessibility.AccessibilityEvent}, such as
8233      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
8234      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8235      *
8236      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8237      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8238      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8239      * @see AccessibilityDelegate
8240      */
8241     public void sendAccessibilityEvent(int eventType) {
8242         if (mAccessibilityDelegate != null) {
8243             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8244         } else {
8245             sendAccessibilityEventInternal(eventType);
8246         }
8247     }
8248 
8249     /**
8250      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8251      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8252      * specified text to its users.
8253      * <p>
8254      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8255      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8256      * accurately supplying the semantics of their UI.
8257      * They should not need to specify what exactly is announced to users.
8258      *
8259      * @param text The announcement text.
8260      */
8261     public void announceForAccessibility(CharSequence text) {
8262         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8263             AccessibilityEvent event = AccessibilityEvent.obtain(
8264                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8265             onInitializeAccessibilityEvent(event);
8266             event.getText().add(text);
8267             event.setContentDescription(null);
8268             mParent.requestSendAccessibilityEvent(this, event);
8269         }
8270     }
8271 
8272     /**
8273      * @see #sendAccessibilityEvent(int)
8274      *
8275      * Note: Called from the default {@link AccessibilityDelegate}.
8276      *
8277      * @hide
8278      */
8279     public void sendAccessibilityEventInternal(int eventType) {
8280         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8281             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8282         }
8283     }
8284 
8285     /**
8286      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8287      * takes as an argument an empty {@link AccessibilityEvent} and does not
8288      * perform a check whether accessibility is enabled.
8289      * <p>
8290      * If an {@link AccessibilityDelegate} has been specified via calling
8291      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8292      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8293      * is responsible for handling this call.
8294      * </p>
8295      *
8296      * @param event The event to send.
8297      *
8298      * @see #sendAccessibilityEvent(int)
8299      */
8300     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8301         if (mAccessibilityDelegate != null) {
8302             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8303         } else {
8304             sendAccessibilityEventUncheckedInternal(event);
8305         }
8306     }
8307 
8308     /**
8309      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8310      *
8311      * Note: Called from the default {@link AccessibilityDelegate}.
8312      *
8313      * @hide
8314      */
8315     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8316         // Panes disappearing are relevant even if though the view is no longer visible.
8317         boolean isWindowStateChanged =
8318                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8319         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8320                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8321         boolean detached = detached();
8322         if (!isShown() && !isWindowDisappearedEvent && !detached) {
8323             return;
8324         }
8325         onInitializeAccessibilityEvent(event);
8326         // Only a subset of accessibility events populates text content.
8327         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8328             dispatchPopulateAccessibilityEvent(event);
8329         }
8330         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
8331         if (throttle != null) {
8332             throttle.post(event);
8333         } else if (!isWindowDisappearedEvent && detached) {
8334             // Views could be attached soon later. Accessibility events during this temporarily
8335             // detached period should be sent too.
8336             postDelayed(() -> {
8337                 if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
8338                     requestParentSendAccessibilityEvent(event);
8339                 }
8340             }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8341         } else {
8342             requestParentSendAccessibilityEvent(event);
8343         }
8344     }
8345 
8346     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
8347         ViewParent parent = getParent();
8348         if (parent != null) {
8349             getParent().requestSendAccessibilityEvent(this, event);
8350         }
8351     }
8352 
8353     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
8354             AccessibilityEvent event) {
8355         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
8356             if (mSendViewScrolledAccessibilityEvent == null) {
8357                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8358             }
8359             return mSendViewScrolledAccessibilityEvent;
8360         }
8361         boolean isStateContentChanged = (event.getContentChangeTypes()
8362                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
8363         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
8364                 && isStateContentChanged) {
8365             if (mSendStateChangedAccessibilityEvent == null) {
8366                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
8367             }
8368             return mSendStateChangedAccessibilityEvent;
8369         }
8370         return null;
8371     }
8372 
8373     private void clearAccessibilityThrottles() {
8374         cancel(mSendViewScrolledAccessibilityEvent);
8375         cancel(mSendStateChangedAccessibilityEvent);
8376     }
8377 
8378     /**
8379      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8380      * to its children for adding their text content to the event. Note that the
8381      * event text is populated in a separate dispatch path since we add to the
8382      * event not only the text of the source but also the text of all its descendants.
8383      * A typical implementation will call
8384      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8385      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8386      * on each child. Override this method if custom population of the event text
8387      * content is required.
8388      * <p>
8389      * If an {@link AccessibilityDelegate} has been specified via calling
8390      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8391      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8392      * is responsible for handling this call.
8393      * </p>
8394      * <p>
8395      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8396      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8397      * </p>
8398      *
8399      * @param event The event.
8400      *
8401      * @return True if the event population was completed.
8402      */
8403     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8404         if (mAccessibilityDelegate != null) {
8405             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8406         } else {
8407             return dispatchPopulateAccessibilityEventInternal(event);
8408         }
8409     }
8410 
8411     /**
8412      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8413      *
8414      * Note: Called from the default {@link AccessibilityDelegate}.
8415      *
8416      * @hide
8417      */
8418     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8419         onPopulateAccessibilityEvent(event);
8420         return false;
8421     }
8422 
8423     /**
8424      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8425      * giving a chance to this View to populate the accessibility event with its
8426      * text content. While this method is free to modify event
8427      * attributes other than text content, doing so should normally be performed in
8428      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8429      * <p>
8430      * Example: Adding formatted date string to an accessibility event in addition
8431      *          to the text added by the super implementation:
8432      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8433      *     super.onPopulateAccessibilityEvent(event);
8434      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8435      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8436      *         mCurrentDate.getTimeInMillis(), flags);
8437      *     event.getText().add(selectedDateUtterance);
8438      * }</pre>
8439      * <p>
8440      * If an {@link AccessibilityDelegate} has been specified via calling
8441      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8442      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8443      * is responsible for handling this call.
8444      * </p>
8445      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8446      * information to the event, in case the default implementation has basic information to add.
8447      * </p>
8448      *
8449      * @param event The accessibility event which to populate.
8450      *
8451      * @see #sendAccessibilityEvent(int)
8452      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8453      */
8454     @CallSuper
8455     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8456         if (mAccessibilityDelegate != null) {
8457             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8458         } else {
8459             onPopulateAccessibilityEventInternal(event);
8460         }
8461     }
8462 
8463     /**
8464      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8465      *
8466      * Note: Called from the default {@link AccessibilityDelegate}.
8467      *
8468      * @hide
8469      */
8470     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8471         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8472                 && isAccessibilityPane()) {
8473             event.getText().add(getAccessibilityPaneTitle());
8474         }
8475     }
8476 
8477     /**
8478      * Initializes an {@link AccessibilityEvent} with information about
8479      * this View which is the event source. In other words, the source of
8480      * an accessibility event is the view whose state change triggered firing
8481      * the event.
8482      * <p>
8483      * Example: Setting the password property of an event in addition
8484      *          to properties set by the super implementation:
8485      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8486      *     super.onInitializeAccessibilityEvent(event);
8487      *     event.setPassword(true);
8488      * }</pre>
8489      * <p>
8490      * If an {@link AccessibilityDelegate} has been specified via calling
8491      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8492      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8493      * is responsible for handling this call.
8494      * </p>
8495      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8496      * information to the event, in case the default implementation has basic information to add.
8497      * </p>
8498      * @param event The event to initialize.
8499      *
8500      * @see #sendAccessibilityEvent(int)
8501      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8502      */
8503     @CallSuper
8504     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8505         if (mAccessibilityDelegate != null) {
8506             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8507         } else {
8508             onInitializeAccessibilityEventInternal(event);
8509         }
8510     }
8511 
8512     /**
8513      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8514      *
8515      * Note: Called from the default {@link AccessibilityDelegate}.
8516      *
8517      * @hide
8518      */
8519     @UnsupportedAppUsage
8520     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8521         event.setSource(this);
8522         event.setClassName(getAccessibilityClassName());
8523         event.setPackageName(getContext().getPackageName());
8524         event.setEnabled(isEnabled());
8525         event.setContentDescription(mContentDescription);
8526         event.setScrollX(getScrollX());
8527         event.setScrollY(getScrollY());
8528 
8529         switch (event.getEventType()) {
8530             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8531                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8532                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8533                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8534                 event.setItemCount(focusablesTempList.size());
8535                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8536                 if (mAttachInfo != null) {
8537                     focusablesTempList.clear();
8538                 }
8539             } break;
8540             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8541                 CharSequence text = getIterableTextForAccessibility();
8542                 if (text != null && text.length() > 0) {
8543                     event.setFromIndex(getAccessibilitySelectionStart());
8544                     event.setToIndex(getAccessibilitySelectionEnd());
8545                     event.setItemCount(text.length());
8546                 }
8547             } break;
8548         }
8549     }
8550 
8551     /**
8552      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8553      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8554      * This method is responsible for obtaining an accessibility node info from a
8555      * pool of reusable instances and calling
8556      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8557      * initialize the former.
8558      * <p>
8559      * Note: The client is responsible for recycling the obtained instance by calling
8560      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8561      * </p>
8562      *
8563      * @return A populated {@link AccessibilityNodeInfo}.
8564      *
8565      * @see AccessibilityNodeInfo
8566      */
8567     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8568         if (mAccessibilityDelegate != null) {
8569             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8570         } else {
8571             return createAccessibilityNodeInfoInternal();
8572         }
8573     }
8574 
8575     /**
8576      * @see #createAccessibilityNodeInfo()
8577      *
8578      * @hide
8579      */
8580     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8581         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8582         if (provider != null) {
8583             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8584         } else {
8585             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8586             onInitializeAccessibilityNodeInfo(info);
8587             return info;
8588         }
8589     }
8590 
8591     /**
8592      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8593      * The base implementation sets:
8594      * <ul>
8595      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8596      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8597      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8598      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8599      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8600      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8601      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8602      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8603      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8604      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8605      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8606      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8607      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8608      * </ul>
8609      * <p>
8610      * Subclasses should override this method, call the super implementation,
8611      * and set additional attributes.
8612      * </p>
8613      * <p>
8614      * If an {@link AccessibilityDelegate} has been specified via calling
8615      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8616      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8617      * is responsible for handling this call.
8618      * </p>
8619      *
8620      * @param info The instance to initialize.
8621      */
8622     @CallSuper
8623     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8624         if (mAccessibilityDelegate != null) {
8625             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8626         } else {
8627             onInitializeAccessibilityNodeInfoInternal(info);
8628         }
8629     }
8630 
8631     /**
8632      * Gets the location of this view in screen coordinates.
8633      *
8634      * @param outRect The output location
8635      * @hide
8636      */
8637     @UnsupportedAppUsage
8638     public void getBoundsOnScreen(Rect outRect) {
8639         getBoundsOnScreen(outRect, false);
8640     }
8641 
8642     /**
8643      * Gets the location of this view in screen coordinates.
8644      *
8645      * @param outRect The output location
8646      * @param clipToParent Whether to clip child bounds to the parent ones.
8647      * @hide
8648      */
8649     @UnsupportedAppUsage
8650     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
8651         if (mAttachInfo == null) {
8652             return;
8653         }
8654 
8655         RectF position = mAttachInfo.mTmpTransformRect;
8656         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8657         mapRectFromViewToScreenCoords(position, clipToParent);
8658         outRect.set(Math.round(position.left), Math.round(position.top),
8659                 Math.round(position.right), Math.round(position.bottom));
8660     }
8661 
8662     /**
8663      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8664      *
8665      * @param rect The rectangle to be mapped
8666      * @param clipToParent Whether to clip child bounds to the parent ones.
8667      * @hide
8668      */
8669     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8670         if (!hasIdentityMatrix()) {
8671             getMatrix().mapRect(rect);
8672         }
8673 
8674         rect.offset(mLeft, mTop);
8675 
8676         ViewParent parent = mParent;
8677         while (parent instanceof View) {
8678             View parentView = (View) parent;
8679 
8680             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
8681 
8682             if (clipToParent) {
8683                 rect.left = Math.max(rect.left, 0);
8684                 rect.top = Math.max(rect.top, 0);
8685                 rect.right = Math.min(rect.right, parentView.getWidth());
8686                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
8687             }
8688 
8689             if (!parentView.hasIdentityMatrix()) {
8690                 parentView.getMatrix().mapRect(rect);
8691             }
8692 
8693             rect.offset(parentView.mLeft, parentView.mTop);
8694 
8695             parent = parentView.mParent;
8696         }
8697 
8698         if (parent instanceof ViewRootImpl) {
8699             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
8700             rect.offset(0, -viewRootImpl.mCurScrollY);
8701         }
8702 
8703         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8704     }
8705 
8706     /**
8707      * Return the class name of this object to be used for accessibility purposes.
8708      * Subclasses should only override this if they are implementing something that
8709      * should be seen as a completely new class of view when used by accessibility,
8710      * unrelated to the class it is deriving from.  This is used to fill in
8711      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
8712      */
8713     public CharSequence getAccessibilityClassName() {
8714         return View.class.getName();
8715     }
8716 
8717     /**
8718      * Called when assist structure is being retrieved from a view as part of
8719      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
8720      * @param structure Fill in with structured view data.  The default implementation
8721      * fills in all data that can be inferred from the view itself.
8722      */
8723     public void onProvideStructure(ViewStructure structure) {
8724         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
8725     }
8726 
8727     /**
8728      * Populates a {@link ViewStructure} to fullfil an autofill request.
8729      *
8730      * <p>The structure should contain at least the following properties:
8731      * <ul>
8732      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
8733      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
8734      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
8735      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
8736      * </ul>
8737      *
8738      * <p>It's also recommended to set the following properties - the more properties the structure
8739      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
8740      * using the structure:
8741      *
8742      * <ul>
8743      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
8744      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
8745      *       view can only be filled with predefined values (typically used when the autofill type
8746      *       is {@link #AUTOFILL_TYPE_LIST}).
8747      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
8748      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
8749      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
8750      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
8751      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
8752      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
8753      *   <li>For views representing text fields, text properties such as the text itself
8754      *       ({@link ViewStructure#setText(CharSequence)}), text hints
8755      *       ({@link ViewStructure#setHint(CharSequence)}, input type
8756      *       ({@link ViewStructure#setInputType(int)}),
8757      *   <li>For views representing HTML nodes, its web domain
8758      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
8759      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
8760      * </ul>
8761      *
8762      * <p>The default implementation of this method already sets most of these properties based on
8763      * related {@link View} methods (for example, the autofill id is set using
8764      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
8765      * and views in the standard Android widgets library also override it to set their
8766      * relevant properties (for example, {@link android.widget.TextView} already sets the text
8767      * properties), so it's recommended to only override this method
8768      * (and call {@code super.onProvideAutofillStructure()}) when:
8769      *
8770      * <ul>
8771      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
8772      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
8773      *   <li>The view can only be autofilled with predefined options, so it can call
8774      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
8775      * </ul>
8776      *
8777      * <p><b>Note:</b> The {@code left} and {@code top} values set in
8778      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
8779      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
8780      *
8781      * <p>Views support the Autofill Framework mainly by:
8782      * <ul>
8783      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8784      *   <li>Notifying the Android System when the view value changed by calling
8785      *       {@link AutofillManager#notifyValueChanged(View)}.
8786      *   <li>Implementing the methods that autofill the view.
8787      * </ul>
8788      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
8789      * for the latter.
8790      *
8791      * @param structure fill in with structured view data for autofill purposes.
8792      * @param flags optional flags.
8793      *
8794      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8795      */
8796     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
8797         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
8798     }
8799 
8800     /**
8801      * Populates a {@link ViewStructure} for content capture.
8802      *
8803      * <p>This method is called after a view that is eligible for content capture
8804      * (for example, if it {@link #isImportantForContentCapture()}, an intelligence service is
8805      * enabled for the user, and the activity rendering the view is enabled for content capture)
8806      * is laid out and is visible. The populated structure is then passed to the service through
8807      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
8808      *
8809      * <p>The default implementation of this method sets the most relevant properties based on
8810      * related {@link View} methods, and views in the standard Android widgets library also
8811      * override it to set their relevant properties. Therefore, if overriding this method, it
8812      * is recommended to call {@code super.onProvideContentCaptureStructure()}.
8813      *
8814      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
8815      * the node representing this view and return right away, then asynchronously report (not
8816      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
8817      * changed by calling
8818      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
8819      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
8820      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
8821      * respectively. The structure for a child must be created using
8822      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
8823      * {@code autofillId} for a child can be obtained either through
8824      * {@code childStructure.getAutofillId()} or
8825      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
8826      *
8827      * <p>When the virtual view hierarchy represents a web page, you should also:
8828      *
8829      * <ul>
8830      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
8831      *   capture events should be generate for that URL.
8832      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
8833      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
8834      *   that subtree.
8835      * </ul>
8836      *
8837      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
8838      * <ul>
8839      *   <li>{@link ViewStructure#setChildCount(int)}
8840      *   <li>{@link ViewStructure#addChildCount(int)}
8841      *   <li>{@link ViewStructure#getChildCount()}
8842      *   <li>{@link ViewStructure#newChild(int)}
8843      *   <li>{@link ViewStructure#asyncNewChild(int)}
8844      *   <li>{@link ViewStructure#asyncCommit()}
8845      *   <li>{@link ViewStructure#setWebDomain(String)}
8846      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
8847      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
8848      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
8849      *   <li>{@link ViewStructure#setAlpha(float)}
8850      *   <li>{@link ViewStructure#setElevation(float)}
8851      *   <li>{@link ViewStructure#setTransformation(Matrix)}
8852      *
8853      * </ul>
8854      */
8855     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
8856         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
8857     }
8858 
8859     /** @hide */
8860     protected void onProvideStructure(@NonNull ViewStructure structure,
8861             @ViewStructureType int viewFor, int flags) {
8862         final int id = mID;
8863         if (id != NO_ID && !isViewIdGenerated(id)) {
8864             String pkg, type, entry;
8865             try {
8866                 final Resources res = getResources();
8867                 entry = res.getResourceEntryName(id);
8868                 type = res.getResourceTypeName(id);
8869                 pkg = res.getResourcePackageName(id);
8870             } catch (Resources.NotFoundException e) {
8871                 entry = type = pkg = null;
8872             }
8873             structure.setId(id, pkg, type, entry);
8874         } else {
8875             structure.setId(id, null, null, null);
8876         }
8877 
8878         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8879                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
8880             final @AutofillType int autofillType = getAutofillType();
8881             // Don't need to fill autofill info if view does not support it.
8882             // For example, only TextViews that are editable support autofill
8883             if (autofillType != AUTOFILL_TYPE_NONE) {
8884                 structure.setAutofillType(autofillType);
8885                 structure.setAutofillHints(getAutofillHints());
8886                 structure.setAutofillValue(getAutofillValue());
8887             }
8888             structure.setImportantForAutofill(getImportantForAutofill());
8889             structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
8890         }
8891 
8892         int ignoredParentLeft = 0;
8893         int ignoredParentTop = 0;
8894         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8895                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
8896             View parentGroup = null;
8897 
8898             ViewParent viewParent = getParent();
8899             if (viewParent instanceof View) {
8900                 parentGroup = (View) viewParent;
8901             }
8902 
8903             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
8904                 ignoredParentLeft += parentGroup.mLeft;
8905                 ignoredParentTop += parentGroup.mTop;
8906 
8907                 viewParent = parentGroup.getParent();
8908                 if (viewParent instanceof View) {
8909                     parentGroup = (View) viewParent;
8910                 } else {
8911                     break;
8912                 }
8913             }
8914         }
8915 
8916         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
8917                 mRight - mLeft, mBottom - mTop);
8918         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
8919             if (!hasIdentityMatrix()) {
8920                 structure.setTransformation(getMatrix());
8921             }
8922             structure.setElevation(getZ());
8923         }
8924         structure.setVisibility(getVisibility());
8925         structure.setEnabled(isEnabled());
8926         if (isClickable()) {
8927             structure.setClickable(true);
8928         }
8929         if (isFocusable()) {
8930             structure.setFocusable(true);
8931         }
8932         if (isFocused()) {
8933             structure.setFocused(true);
8934         }
8935         if (isAccessibilityFocused()) {
8936             structure.setAccessibilityFocused(true);
8937         }
8938         if (isSelected()) {
8939             structure.setSelected(true);
8940         }
8941         if (isActivated()) {
8942             structure.setActivated(true);
8943         }
8944         if (isLongClickable()) {
8945             structure.setLongClickable(true);
8946         }
8947         if (this instanceof Checkable) {
8948             structure.setCheckable(true);
8949             if (((Checkable)this).isChecked()) {
8950                 structure.setChecked(true);
8951             }
8952         }
8953         if (isOpaque()) {
8954             structure.setOpaque(true);
8955         }
8956         if (isContextClickable()) {
8957             structure.setContextClickable(true);
8958         }
8959         structure.setClassName(getAccessibilityClassName().toString());
8960         structure.setContentDescription(getContentDescription());
8961     }
8962 
8963     /**
8964      * Called when assist structure is being retrieved from a view as part of
8965      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
8966      * generate additional virtual structure under this view.  The default implementation
8967      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
8968      * view's virtual accessibility nodes, if any.  You can override this for a more
8969      * optimal implementation providing this data.
8970      */
8971     public void onProvideVirtualStructure(ViewStructure structure) {
8972         onProvideVirtualStructureCompat(structure, false);
8973     }
8974 
8975     /**
8976      * Fallback implementation to populate a ViewStructure from accessibility state.
8977      *
8978      * @param structure The structure to populate.
8979      * @param forAutofill Whether the structure is needed for autofill.
8980      */
8981     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
8982         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8983         if (provider != null) {
8984             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8985                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
8986             }
8987             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
8988             structure.setChildCount(1);
8989             final ViewStructure root = structure.newChild(0);
8990             populateVirtualStructure(root, provider, info, forAutofill);
8991             info.recycle();
8992         }
8993     }
8994 
8995     /**
8996      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
8997      * request.
8998      *
8999      * <p>This method should be used when the view manages a virtual structure under this view. For
9000      * example, a view that draws input fields using {@link #draw(Canvas)}.
9001      *
9002      * <p>When implementing this method, subclasses must follow the rules below:
9003      *
9004      * <ul>
9005      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
9006      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
9007      *       identifying the children in the virtual structure.
9008      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
9009      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
9010      *       autofill performance.
9011      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
9012      *       children.
9013      *   <li>Set the autofill properties of the child structure as defined by
9014      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
9015      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
9016      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
9017      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
9018      *       when the focused virtual child changed.
9019      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9020      *       whether a given virtual view is visible to the user in order to support triggering
9021      *       save when all views of interest go away.
9022      *   <li>Call
9023      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9024      *       when the value of a virtual child changed.
9025      *   <li>Call {@link
9026      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9027      *       when the visibility of a virtual child changed.
9028      *   <li>Call
9029      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9030      *       child is clicked.
9031      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9032      *       changed and the current context should be committed (for example, when the user tapped
9033      *       a {@code SUBMIT} button in an HTML page).
9034      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9035      *       changed and the current context should be canceled (for example, when the user tapped
9036      *       a {@code CANCEL} button in an HTML page).
9037      *   <li>Provide ways for users to manually request autofill by calling
9038      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9039      *   <li>The {@code left} and {@code top} values set in
9040      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9041      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9042      *       structure.
9043      * </ul>
9044      *
9045      * <p>Views with virtual children support the Autofill Framework mainly by:
9046      * <ul>
9047      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9048      *       autofilled.
9049      *   <li>Implementing the methods that autofill the virtual children.
9050      * </ul>
9051      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9052      * for the latter.
9053      *
9054      * @param structure fill in with virtual children data for autofill purposes.
9055      * @param flags optional flags.
9056      *
9057      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9058      */
9059     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9060         if (mContext.isAutofillCompatibilityEnabled()) {
9061             onProvideVirtualStructureCompat(structure, true);
9062         }
9063     }
9064 
9065     /**
9066      * Sets the listener to be {@link #performReceiveContent used} to handle insertion of
9067      * content into this view.
9068      *
9069      * <p>Depending on the type of view, this listener may be invoked for different scenarios. For
9070      * example, for an editable {@link android.widget.TextView}, this listener will be invoked for
9071      * the following scenarios:
9072      * <ol>
9073      *     <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
9074      *     insertion/selection menu)
9075      *     <li>Content insertion from the keyboard (from {@link InputConnection#commitContent})
9076      *     <li>Drag and drop (drop events from {@link #onDragEvent})
9077      *     <li>Autofill
9078      *     <li>Selection replacement via {@link Intent#ACTION_PROCESS_TEXT}
9079      * </ol>
9080      *
9081      * <p>When setting a listener, clients must also declare the accepted MIME types.
9082      * The listener will still be invoked even if the MIME type of the content is not one of the
9083      * declared MIME types (e.g. if the user pastes content whose type is not one of the declared
9084      * MIME types).
9085      * In that case, the listener may reject the content (defer to the default platform behavior)
9086      * or execute some other fallback logic (e.g. show an appropriate message to the user).
9087      * The declared MIME types serve as a hint to allow different features to optionally alter
9088      * their behavior. For example, a soft keyboard may optionally choose to hide its UI for
9089      * inserting GIFs for a particular input field if the MIME types set here for that field
9090      * don't include "image/gif" or "image/*".
9091      *
9092      * <p>Note: MIME type matching in the Android framework is case-sensitive, unlike formal RFC
9093      * MIME types. As a result, you should always write your MIME types with lowercase letters,
9094      * or use {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9095      * lowercase.
9096      *
9097      * @param mimeTypes The MIME types accepted by the given listener. These may use patterns
9098      *                  such as "image/*", but may not start with a wildcard. This argument must
9099      *                  not be null or empty if a non-null listener is passed in.
9100      * @param listener The listener to use. This can be null to reset to the default behavior.
9101      */
9102     public void setOnReceiveContentListener(
9103             @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
9104             @Nullable OnReceiveContentListener listener) {
9105         if (listener != null) {
9106             Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
9107                     "When the listener is set, MIME types must also be set");
9108         }
9109         if (mimeTypes != null) {
9110             Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
9111                     "A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
9112         }
9113         mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
9114         getListenerInfo().mOnReceiveContentListener = listener;
9115     }
9116 
9117     /**
9118      * Receives the given content. If no listener is set, invokes {@link #onReceiveContent}. If a
9119      * listener is {@link #setOnReceiveContentListener set}, invokes the listener instead; if the
9120      * listener returns a non-null result, invokes {@link #onReceiveContent} to handle it.
9121      *
9122      * @param payload The content to insert and related metadata.
9123      *
9124      * @return The portion of the passed-in content that was not accepted (may be all, some, or none
9125      * of the passed-in content).
9126      */
9127     @Nullable
performReceiveContent(@onNull ContentInfo payload)9128     public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
9129         final OnReceiveContentListener listener = (mListenerInfo == null) ? null
9130                 : getListenerInfo().mOnReceiveContentListener;
9131         if (listener != null) {
9132             final ContentInfo remaining = listener.onReceiveContent(this, payload);
9133             return (remaining == null) ? null : onReceiveContent(remaining);
9134         }
9135         return onReceiveContent(payload);
9136     }
9137 
9138     /**
9139      * Implements the default behavior for receiving content for this type of view. The default
9140      * view implementation is a no-op (returns the passed-in content without acting on it).
9141      *
9142      * <p>Widgets should override this method to define their default behavior for receiving
9143      * content. Apps should {@link #setOnReceiveContentListener set a listener} to provide
9144      * app-specific handling for receiving content.
9145      *
9146      * <p>See {@link #setOnReceiveContentListener} and {@link #performReceiveContent} for more info.
9147      *
9148      * @param payload The content to insert and related metadata.
9149      *
9150      * @return The portion of the passed-in content that was not handled (may be all, some, or none
9151      * of the passed-in content).
9152      */
9153     @Nullable
onReceiveContent(@onNull ContentInfo payload)9154     public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
9155         return payload;
9156     }
9157 
9158     /**
9159      * Returns the MIME types accepted by {@link #performReceiveContent} for this view, as
9160      * configured via {@link #setOnReceiveContentListener}. By default returns null.
9161      *
9162      * <p>Different features (e.g. pasting from the clipboard, inserting stickers from the soft
9163      * keyboard, etc) may optionally use this metadata to conditionally alter their behavior. For
9164      * example, a soft keyboard may choose to hide its UI for inserting GIFs for a particular
9165      * input field if the MIME types returned here for that field don't include "image/gif" or
9166      * "image/*".
9167      *
9168      * <p>Note: Comparisons of MIME types should be performed using utilities such as
9169      * {@link ClipDescription#compareMimeTypes} rather than simple string equality, in order to
9170      * correctly handle patterns such as "text/*", "image/*", etc. Note that MIME type matching
9171      * in the Android framework is case-sensitive, unlike formal RFC MIME types. As a result,
9172      * you should always write your MIME types with lowercase letters, or use
9173      * {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9174      * lowercase.
9175      *
9176      * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
9177      * include patterns such as "image/*").
9178      */
9179     @SuppressLint("NullableCollection")
9180     @Nullable
getReceiveContentMimeTypes()9181     public String[] getReceiveContentMimeTypes() {
9182         return mReceiveContentMimeTypes;
9183     }
9184 
9185     /**
9186      * Automatically fills the content of this view with the {@code value}.
9187      *
9188      * <p>Views support the Autofill Framework mainly by:
9189      * <ul>
9190      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9191      *   <li>Implementing the methods that autofill the view.
9192      * </ul>
9193      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
9194      * this method is responsible for latter.
9195      *
9196      * <p>This method does nothing by default, but when overridden it typically:
9197      * <ol>
9198      *   <li>Checks if the provided value matches the expected type (which is defined by
9199      *       {@link #getAutofillType()}).
9200      *   <li>Checks if the view is editable - if it isn't, it should return right away.
9201      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
9202      *   <li>Pass the actual value to the equivalent setter in the view.
9203      * </ol>
9204      *
9205      * <p>For example, a text-field view could implement the method this way:
9206      *
9207      * <pre class="prettyprint">
9208      * &#64;Override
9209      * public void autofill(AutofillValue value) {
9210      *   if (!value.isText() || !this.isEditable()) {
9211      *      return;
9212      *   }
9213      *   CharSequence text = value.getTextValue();
9214      *   if (text != null) {
9215      *     this.setText(text);
9216      *   }
9217      * }
9218      * </pre>
9219      *
9220      * <p>If the value is updated asynchronously, the next call to
9221      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
9222      * changed to the autofilled value. If not, the view will not be considered autofilled.
9223      *
9224      * <p><b>Note:</b> After this method is called, the value returned by
9225      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
9226      * view will not be highlighted as autofilled.
9227      *
9228      * @param value value to be autofilled.
9229      */
autofill(@uppressWarningsR) AutofillValue value)9230     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
9231     }
9232 
9233     /**
9234      * Automatically fills the content of the virtual children within this view.
9235      *
9236      * <p>Views with virtual children support the Autofill Framework mainly by:
9237      * <ul>
9238      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9239      *       autofilled.
9240      *   <li>Implementing the methods that autofill the virtual children.
9241      * </ul>
9242      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
9243      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
9244      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
9245      *
9246      * <p>If a child value is updated asynchronously, the next call to
9247      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
9248      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
9249      * considered autofilled.
9250      *
9251      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
9252      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
9253      * changes.
9254      *
9255      * @param values map of values to be autofilled, keyed by virtual child id.
9256      *
9257      * @attr ref android.R.styleable#Theme_autofilledHighlight
9258      */
autofill(@onNull @uppressWarningsR) SparseArray<AutofillValue> values)9259     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
9260         if (!mContext.isAutofillCompatibilityEnabled()) {
9261             return;
9262         }
9263         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9264         if (provider == null) {
9265             return;
9266         }
9267         final int valueCount = values.size();
9268         for (int i = 0; i < valueCount; i++) {
9269             final AutofillValue value = values.valueAt(i);
9270             if (value.isText()) {
9271                 final int virtualId = values.keyAt(i);
9272                 final CharSequence text = value.getTextValue();
9273                 final Bundle arguments = new Bundle();
9274                 arguments.putCharSequence(
9275                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
9276                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
9277             }
9278         }
9279     }
9280 
9281     /**
9282      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
9283      *
9284      * <p>The autofill id is created on demand, unless it is explicitly set by
9285      * {@link #setAutofillId(AutofillId)}.
9286      *
9287      * <p>See {@link #setAutofillId(AutofillId)} for more info.
9288      *
9289      * @return The View's autofill id.
9290      */
getAutofillId()9291     public final AutofillId getAutofillId() {
9292         if (mAutofillId == null) {
9293             // The autofill id needs to be unique, but its value doesn't matter,
9294             // so it's better to reuse the accessibility id to save space.
9295             mAutofillId = new AutofillId(getAutofillViewId());
9296         }
9297         return mAutofillId;
9298     }
9299 
9300     /**
9301      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
9302      *
9303      * <p>The autofill id is created on demand, and this method should only be called when a view is
9304      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
9305      * that method creates a snapshot of the view that is passed along to the autofill service.
9306      *
9307      * <p>This method is typically used when view subtrees are recycled to represent different
9308      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
9309      * out, and restored later when it's swapped back in. For example:
9310      *
9311      * <pre>
9312      * EditText reusableView = ...;
9313      * ViewGroup parentView = ...;
9314      * AutofillManager afm = ...;
9315      *
9316      * // Swap out the view and change its contents
9317      * AutofillId oldId = reusableView.getAutofillId();
9318      * CharSequence oldText = reusableView.getText();
9319      * parentView.removeView(reusableView);
9320      * AutofillId newId = afm.getNextAutofillId();
9321      * reusableView.setText("New I am");
9322      * reusableView.setAutofillId(newId);
9323      * parentView.addView(reusableView);
9324      *
9325      * // Later, swap the old content back in
9326      * parentView.removeView(reusableView);
9327      * reusableView.setAutofillId(oldId);
9328      * reusableView.setText(oldText);
9329      * parentView.addView(reusableView);
9330      * </pre>
9331      *
9332      * <p>NOTE: If this view is a descendant of an {@link android.widget.AdapterView}, the system
9333      * may reset its autofill id when this view is recycled. If the autofill ids need to be stable,
9334      * they should be set again in
9335      * {@link android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
9336      *
9337      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
9338      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
9339      * obtained through {@link #getAutofillId()}), or a new value obtained through
9340      * {@link AutofillManager#getNextAutofillId()}.
9341      *
9342      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
9343      * a window}.
9344      *
9345      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
9346      */
setAutofillId(@ullable AutofillId id)9347     public void setAutofillId(@Nullable AutofillId id) {
9348         // TODO(b/37566627): add unit / CTS test for all possible combinations below
9349         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9350             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
9351         }
9352         if (isAttachedToWindow()) {
9353             throw new IllegalStateException("Cannot set autofill id when view is attached");
9354         }
9355         if (id != null && !id.isNonVirtual()) {
9356             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
9357         }
9358         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
9359             // Ignore reset because it was never explicitly set before.
9360             return;
9361         }
9362         mAutofillId = id;
9363         if (id != null) {
9364             mAutofillViewId = id.getViewId();
9365             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9366         } else {
9367             mAutofillViewId = NO_ID;
9368             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9369         }
9370     }
9371 
9372     /**
9373      * Forces a reset of the autofill ids of the subtree rooted at this view. Like calling
9374      * {@link #setAutofillId(AutofillId) setAutofillId(null)} for each view, but works even if the
9375      * views are attached to a window.
9376      *
9377      * <p>This is useful if the views are being recycled, since an autofill id should uniquely
9378      * identify a particular piece of content.
9379      *
9380      * @hide
9381      */
resetSubtreeAutofillIds()9382     public void resetSubtreeAutofillIds() {
9383         if (mAutofillViewId == NO_ID) {
9384             return;
9385         }
9386         if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9387             Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9388         } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9389             Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9390         }
9391         mAutofillId = null;
9392         mAutofillViewId = NO_ID;
9393         mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9394     }
9395 
9396     /**
9397      * Describes the autofill type of this view, so an
9398      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
9399      * when autofilling the view.
9400      *
9401      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
9402      * support the Autofill Framework.
9403      *
9404      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
9405      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
9406      *
9407      * @see #onProvideAutofillStructure(ViewStructure, int)
9408      * @see #autofill(AutofillValue)
9409      */
getAutofillType()9410     public @AutofillType int getAutofillType() {
9411         return AUTOFILL_TYPE_NONE;
9412     }
9413 
9414     /**
9415      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
9416      * to autofill the view with the user's data.
9417      *
9418      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
9419      *
9420      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
9421      * {@code null} if no hints were set.
9422      *
9423      * @attr ref android.R.styleable#View_autofillHints
9424      */
9425     @ViewDebug.ExportedProperty()
9426     @InspectableProperty
getAutofillHints()9427     @Nullable public String[] getAutofillHints() {
9428         return mAutofillHints;
9429     }
9430 
9431     /**
9432      * @hide
9433      */
9434     @TestApi
isAutofilled()9435     public boolean isAutofilled() {
9436         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
9437     }
9438 
9439     /**
9440      * @hide
9441      */
hideAutofillHighlight()9442     public boolean hideAutofillHighlight() {
9443         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
9444     }
9445 
9446     /**
9447      * Gets the {@link View}'s current autofill value.
9448      *
9449      * <p>By default returns {@code null}, but subclasses should override it and return an
9450      * appropriate value to properly support the Autofill Framework.
9451      *
9452      * @see #onProvideAutofillStructure(ViewStructure, int)
9453      * @see #autofill(AutofillValue)
9454      */
9455     @Nullable
getAutofillValue()9456     public AutofillValue getAutofillValue() {
9457         return null;
9458     }
9459 
9460     /**
9461      * Gets the mode for determining whether this view is important for autofill.
9462      *
9463      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
9464      * info about this mode.
9465      *
9466      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
9467      * {@link #setImportantForAutofill(int)}.
9468      *
9469      * @attr ref android.R.styleable#View_importantForAutofill
9470      */
9471     @ViewDebug.ExportedProperty(mapping = {
9472             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
9473             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
9474             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
9475             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9476                 to = "yesExcludeDescendants"),
9477             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9478                 to = "noExcludeDescendants")})
9479     @InspectableProperty(enumMapping = {
9480             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
9481             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
9482             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
9483             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9484                     name = "yesExcludeDescendants"),
9485             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9486                     name = "noExcludeDescendants"),
9487     })
getImportantForAutofill()9488     public @AutofillImportance int getImportantForAutofill() {
9489         return (mPrivateFlags3
9490                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
9491     }
9492 
9493     /**
9494      * Sets the mode for determining whether this view is considered important for autofill.
9495      *
9496      * <p>The platform determines the importance for autofill automatically but you
9497      * can use this method to customize the behavior. For example:
9498      *
9499      * <ol>
9500      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
9501      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
9502      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
9503      *       view of an activity containing a spreadhseet editor), it should be
9504      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9505      *   <li>When the view content is relevant for autofill but its children aren't (for example,
9506      *       a credit card expiration date represented by a custom view that overrides the proper
9507      *       autofill methods and has 2 children representing the month and year), it should
9508      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
9509      * </ol>
9510      *
9511      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9512      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
9513      * children) will be always be considered not important; for example, when the user explicitly
9514      * makes an autofill request, all views are considered important. See
9515      * {@link #isImportantForAutofill()} for more details about how the View's importance for
9516      * autofill is used.
9517      *
9518      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
9519      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
9520      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9521      *
9522      * @attr ref android.R.styleable#View_importantForAutofill
9523      */
setImportantForAutofill(@utofillImportance int mode)9524     public void setImportantForAutofill(@AutofillImportance int mode) {
9525         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9526         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
9527                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9528     }
9529 
9530     /**
9531      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
9532      * associated with this view is considered important for autofill purposes.
9533      *
9534      * <p>Generally speaking, a view is important for autofill if:
9535      * <ol>
9536      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
9537      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
9538      *     determine how other views can be autofilled.
9539      * <ol>
9540      *
9541      * <p>For example, view containers should typically return {@code false} for performance reasons
9542      * (since the important info is provided by their children), but if its properties have relevant
9543      * information (for example, a resource id called {@code credentials}, it should return
9544      * {@code true}. On the other hand, views representing labels or editable fields should
9545      * typically return {@code true}, but in some cases they could return {@code false}
9546      * (for example, if they're part of a "Captcha" mechanism).
9547      *
9548      * <p>The value returned by this method depends on the value returned by
9549      * {@link #getImportantForAutofill()}:
9550      *
9551      * <ol>
9552      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
9553      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
9554      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9555      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
9556      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
9557      *       that can return {@code true} in some cases (like a container with a resource id),
9558      *       but {@code false} in most.
9559      *   <li>otherwise, it returns {@code false}.
9560      * </ol>
9561      *
9562      * <p>When a view is considered important for autofill:
9563      * <ul>
9564      *   <li>The view might automatically trigger an autofill request when focused on.
9565      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
9566      *       request.
9567      * </ul>
9568      *
9569      * <p>On the other hand, when a view is considered not important for autofill:
9570      * <ul>
9571      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
9572      *       request through {@link AutofillManager#requestAutofill(View)}.
9573      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
9574      *       autofill request, unless the request has the
9575      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9576      * </ul>
9577      *
9578      * @return whether the view is considered important for autofill.
9579      *
9580      * @see #setImportantForAutofill(int)
9581      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9582      * @see #IMPORTANT_FOR_AUTOFILL_YES
9583      * @see #IMPORTANT_FOR_AUTOFILL_NO
9584      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9585      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9586      * @see AutofillManager#requestAutofill(View)
9587      */
isImportantForAutofill()9588     public final boolean isImportantForAutofill() {
9589         // Check parent mode to ensure we're not hidden.
9590         ViewParent parent = mParent;
9591         while (parent instanceof View) {
9592             final int parentImportance = ((View) parent).getImportantForAutofill();
9593             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9594                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9595                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9596                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9597                             + "because parent " + parent + "'s importance is " + parentImportance);
9598                 }
9599                 return false;
9600             }
9601             parent = parent.getParent();
9602         }
9603 
9604         final int importance = getImportantForAutofill();
9605 
9606         // First, check the explicit states.
9607         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9608                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9609             return true;
9610         }
9611         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9612                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9613             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9614                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9615                         + "because its importance is " + importance);
9616             }
9617             return false;
9618         }
9619 
9620         // Then use some heuristics to handle AUTO.
9621         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9622             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9623                     + this);
9624             return false;
9625         }
9626 
9627         // Always include views that have an explicit resource id.
9628         final int id = mID;
9629         if (id != NO_ID && !isViewIdGenerated(id)) {
9630             final Resources res = getResources();
9631             String entry = null;
9632             String pkg = null;
9633             try {
9634                 entry = res.getResourceEntryName(id);
9635                 pkg = res.getResourcePackageName(id);
9636             } catch (Resources.NotFoundException e) {
9637                 // ignore
9638             }
9639             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9640                 return true;
9641             }
9642         }
9643 
9644         // If the app developer explicitly set hints for it, it's important.
9645         if (getAutofillHints() != null) {
9646             return true;
9647         }
9648 
9649         // Otherwise, assume it's not important...
9650         return false;
9651     }
9652 
9653     /**
9654      * Gets the mode for determining whether this view is important for content capture.
9655      *
9656      * <p>See {@link #setImportantForContentCapture(int)} and
9657      * {@link #isImportantForContentCapture()} for more info about this mode.
9658      *
9659      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
9660      * {@link #setImportantForContentCapture(int)}.
9661      *
9662      * @attr ref android.R.styleable#View_importantForContentCapture
9663      */
9664     @ViewDebug.ExportedProperty(mapping = {
9665             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
9666             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
9667             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
9668             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9669                 to = "yesExcludeDescendants"),
9670             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9671                 to = "noExcludeDescendants")})
9672     @InspectableProperty(enumMapping = {
9673             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
9674             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
9675             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
9676             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9677                     name = "yesExcludeDescendants"),
9678             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9679                     name = "noExcludeDescendants"),
9680     })
getImportantForContentCapture()9681     public @ContentCaptureImportance int getImportantForContentCapture() {
9682         // NOTE: the important for content capture values were the first flags added and are set in
9683         // the rightmost position, so we don't need to shift them
9684         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9685     }
9686 
9687     /**
9688      * Sets the mode for determining whether this view is considered important for content capture.
9689      *
9690      * <p>The platform determines the importance for autofill automatically but you
9691      * can use this method to customize the behavior. Typically, a view that provides text should
9692      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
9693      *
9694      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
9695      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
9696      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
9697      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
9698      *
9699      * @attr ref android.R.styleable#View_importantForContentCapture
9700      */
setImportantForContentCapture(@ontentCaptureImportance int mode)9701     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
9702         // Reset first
9703         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9704         // Then set again
9705         // NOTE: the important for content capture values were the first flags added and are set in
9706         // the rightmost position, so we don't need to shift them
9707         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
9708     }
9709 
9710     /**
9711      * Hints the Android System whether this view is considered important for content capture, based
9712      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
9713      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
9714      *
9715      * <p>See {@link ContentCaptureManager} for more info about content capture.
9716      *
9717      * @return whether the view is considered important for content capture.
9718      *
9719      * @see #setImportantForContentCapture(int)
9720      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
9721      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
9722      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
9723      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9724      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9725      */
isImportantForContentCapture()9726     public final boolean isImportantForContentCapture() {
9727         boolean isImportant;
9728         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
9729             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
9730             return isImportant;
9731         }
9732 
9733         isImportant = calculateIsImportantForContentCapture();
9734 
9735         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9736         if (isImportant) {
9737             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9738         }
9739         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
9740         return isImportant;
9741     }
9742 
9743     /**
9744      * Calculates whether the flag is important for content capture so it can be used by
9745      * {@link #isImportantForContentCapture()} while the tree is traversed.
9746      */
calculateIsImportantForContentCapture()9747     private boolean calculateIsImportantForContentCapture() {
9748         // Check parent mode to ensure we're important
9749         ViewParent parent = mParent;
9750         while (parent instanceof View) {
9751             final int parentImportance = ((View) parent).getImportantForContentCapture();
9752             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9753                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
9754                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9755                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
9756                             + "content capture because parent " + parent + "'s importance is "
9757                             + parentImportance);
9758                 }
9759                 return false;
9760             }
9761             parent = parent.getParent();
9762         }
9763 
9764         final int importance = getImportantForContentCapture();
9765 
9766         // First, check the explicit states.
9767         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9768                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
9769             return true;
9770         }
9771         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9772                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
9773             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9774                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
9775                         + "capture because its importance is " + importance);
9776             }
9777             return false;
9778         }
9779 
9780         // Then use some heuristics to handle AUTO.
9781         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
9782             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
9783                     + " on view " + this);
9784             return false;
9785         }
9786 
9787         // View group is important if at least one children also is
9788         if (this instanceof ViewGroup) {
9789             final ViewGroup group = (ViewGroup) this;
9790             for (int i = 0; i < group.getChildCount(); i++) {
9791                 final View child = group.getChildAt(i);
9792                 if (child.isImportantForContentCapture()) {
9793                     return true;
9794                 }
9795             }
9796         }
9797 
9798         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
9799         if (getAutofillHints() != null) {
9800             return true;
9801         }
9802 
9803         // Otherwise, assume it's not important...
9804         return false;
9805     }
9806 
9807     /**
9808      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
9809      * added, based on whether it's laid out and visible, and without knowing if the parent removed
9810      * it from the view hierarchy.
9811      *
9812      * <p>This method is called from many places (visibility changed, view laid out, view attached
9813      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
9814      * described below:
9815      *
9816      * <ol>
9817      *   <li>It should only be called when content capture is enabled for the view.
9818      *   <li>It must call viewAppeared() before viewDisappeared()
9819      *   <li>viewAppearead() can only be called when the view is visible and laidout
9820      *   <li>It should not call the same event twice.
9821      * </ol>
9822      */
notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared)9823     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
9824         AttachInfo ai = mAttachInfo;
9825         // Skip it while the view is being laid out for the first time
9826         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
9827 
9828         // First check if context has client, so it saves a service lookup when it doesn't
9829         if (mContext.getContentCaptureOptions() == null) return;
9830 
9831         if (appeared) {
9832             // The appeared event stops sending to AiAi.
9833             // 1. The view is hidden.
9834             // 2. The same event was sent.
9835             // 3. The view is not laid out, and it will be laid out in the future.
9836             //    Some recycled views cached its layout and a relayout is unnecessary. In this case,
9837             // system still needs to notify content capture the view appeared. When a view is
9838             // recycled, it will set the flag PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED.
9839             final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
9840                     && getVisibility() == VISIBLE
9841                     && !isLayoutRequested();
9842             if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
9843                     || !(isLaidOut() || isRecycledWithoutRelayout)) {
9844                 if (DEBUG_CONTENT_CAPTURE) {
9845                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
9846                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9847                             + ", visible=" + (getVisibility() == VISIBLE)
9848                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
9849                             + ", alreadyNotifiedDisappeared="
9850                             + getNotifiedContentCaptureDisappeared());
9851                 }
9852                 return;
9853             }
9854         } else {
9855             if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
9856                 if (DEBUG_CONTENT_CAPTURE) {
9857                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
9858                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9859                             + ", visible=" + (getVisibility() == VISIBLE)
9860                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
9861                             + ", alreadyNotifiedDisappeared="
9862                             + getNotifiedContentCaptureDisappeared());
9863                 }
9864                 return;
9865             }
9866         }
9867 
9868         ContentCaptureSession session = getContentCaptureSession();
9869         if (session == null) return;
9870 
9871         // ... and finally at the view level
9872         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
9873         if (!isImportantForContentCapture()) return;
9874 
9875         if (appeared) {
9876             setNotifiedContentCaptureAppeared();
9877 
9878             if (ai != null) {
9879                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9880             } else {
9881                 if (DEBUG_CONTENT_CAPTURE) {
9882                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
9883                 }
9884             }
9885         } else {
9886             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9887             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9888 
9889             if (ai != null) {
9890                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9891             } else {
9892                 if (DEBUG_CONTENT_CAPTURE) {
9893                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
9894                 }
9895             }
9896         }
9897     }
9898 
setNotifiedContentCaptureAppeared()9899     private void setNotifiedContentCaptureAppeared() {
9900         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9901         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9902     }
9903 
9904     /** @hide */
getNotifiedContentCaptureAppeared()9905     protected boolean getNotifiedContentCaptureAppeared() {
9906         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
9907     }
9908 
9909 
getNotifiedContentCaptureDisappeared()9910     private boolean getNotifiedContentCaptureDisappeared() {
9911         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
9912     }
9913 
9914     /**
9915      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
9916      *
9917      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
9918      * the content capture events associated with this view or its view hierarchy (if it's a
9919      * {@link ViewGroup}).
9920      *
9921      * <p>For example, if your activity is associated with a web domain, first you would need to
9922      * set the context for the main DOM:
9923      *
9924      * <pre>
9925      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
9926      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
9927      * </pre>
9928      *
9929      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
9930      *
9931      * <pre>
9932      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
9933      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
9934      *   iframeView.setContentCaptureSession(iframeSession);
9935      * </pre>
9936      *
9937      * @param contentCaptureSession a session created by
9938      * {@link ContentCaptureSession#createContentCaptureSession(
9939      *        android.view.contentcapture.ContentCaptureContext)}.
9940      */
setContentCaptureSession(@ullable ContentCaptureSession contentCaptureSession)9941     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
9942         mContentCaptureSession = contentCaptureSession;
9943     }
9944 
9945     /**
9946      * Gets the session used to notify content capture events.
9947      *
9948      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
9949      * inherited by ancestors, default session or {@code null} if content capture is disabled for
9950      * this view.
9951      */
9952     @Nullable
getContentCaptureSession()9953     public final ContentCaptureSession getContentCaptureSession() {
9954         if (mContentCaptureSessionCached) {
9955             return mContentCaptureSession;
9956         }
9957 
9958         mContentCaptureSession = getAndCacheContentCaptureSession();
9959         mContentCaptureSessionCached = true;
9960         return mContentCaptureSession;
9961     }
9962 
9963     @Nullable
getAndCacheContentCaptureSession()9964     private ContentCaptureSession getAndCacheContentCaptureSession() {
9965         // First try the session explicitly set by setContentCaptureSession()
9966         if (mContentCaptureSession != null) {
9967             return mContentCaptureSession;
9968         }
9969 
9970         // Then the session explicitly set in an ancestor
9971         ContentCaptureSession session = null;
9972         if (mParent instanceof View) {
9973             session = ((View) mParent).getContentCaptureSession();
9974         }
9975 
9976         // Finally, if no session was explicitly set, use the context's default session.
9977         if (session == null) {
9978             final ContentCaptureManager ccm = mContext
9979                     .getSystemService(ContentCaptureManager.class);
9980             return ccm == null ? null : ccm.getMainContentCaptureSession();
9981         }
9982         return session;
9983     }
9984 
9985     @Nullable
getAutofillManager()9986     private AutofillManager getAutofillManager() {
9987         return mContext.getSystemService(AutofillManager.class);
9988     }
9989 
isAutofillable()9990     private boolean isAutofillable() {
9991         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
9992 
9993         if (!isImportantForAutofill()) {
9994             // View is not important for "regular" autofill, so we must check if Augmented Autofill
9995             // is enabled for the activity
9996             final AutofillOptions options = mContext.getAutofillOptions();
9997             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
9998                 return false;
9999             }
10000             final AutofillManager afm = getAutofillManager();
10001             if (afm == null) return false;
10002             afm.notifyViewEnteredForAugmentedAutofill(this);
10003         }
10004 
10005         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
10006     }
10007 
10008     /** @hide */
canNotifyAutofillEnterExitEvent()10009     public boolean canNotifyAutofillEnterExitEvent() {
10010         return isAutofillable() && isAttachedToWindow();
10011     }
10012 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill)10013     private void populateVirtualStructure(ViewStructure structure,
10014             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
10015             boolean forAutofill) {
10016         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
10017                 null, null, info.getViewIdResourceName());
10018         Rect rect = structure.getTempRect();
10019         info.getBoundsInParent(rect);
10020         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
10021         structure.setVisibility(VISIBLE);
10022         structure.setEnabled(info.isEnabled());
10023         if (info.isClickable()) {
10024             structure.setClickable(true);
10025         }
10026         if (info.isFocusable()) {
10027             structure.setFocusable(true);
10028         }
10029         if (info.isFocused()) {
10030             structure.setFocused(true);
10031         }
10032         if (info.isAccessibilityFocused()) {
10033             structure.setAccessibilityFocused(true);
10034         }
10035         if (info.isSelected()) {
10036             structure.setSelected(true);
10037         }
10038         if (info.isLongClickable()) {
10039             structure.setLongClickable(true);
10040         }
10041         if (info.isCheckable()) {
10042             structure.setCheckable(true);
10043             if (info.isChecked()) {
10044                 structure.setChecked(true);
10045             }
10046         }
10047         if (info.isContextClickable()) {
10048             structure.setContextClickable(true);
10049         }
10050         if (forAutofill) {
10051             structure.setAutofillId(new AutofillId(getAutofillId(),
10052                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
10053         }
10054         CharSequence cname = info.getClassName();
10055         structure.setClassName(cname != null ? cname.toString() : null);
10056         structure.setContentDescription(info.getContentDescription());
10057         if (forAutofill) {
10058             final int maxTextLength = info.getMaxTextLength();
10059             if (maxTextLength != -1) {
10060                 structure.setMaxTextLength(maxTextLength);
10061             }
10062             structure.setHint(info.getHintText());
10063         }
10064         CharSequence text = info.getText();
10065         boolean hasText = text != null || info.getError() != null;
10066         if (hasText) {
10067             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
10068         }
10069         if (forAutofill) {
10070             if (info.isEditable()) {
10071                 structure.setDataIsSensitive(true);
10072                 if (hasText) {
10073                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
10074                     structure.setAutofillValue(AutofillValue.forText(text));
10075                 }
10076                 int inputType = info.getInputType();
10077                 if (inputType == 0 && info.isPassword()) {
10078                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
10079                 }
10080                 structure.setInputType(inputType);
10081             } else {
10082                 structure.setDataIsSensitive(false);
10083             }
10084         }
10085         final int NCHILDREN = info.getChildCount();
10086         if (NCHILDREN > 0) {
10087             structure.setChildCount(NCHILDREN);
10088             for (int i=0; i<NCHILDREN; i++) {
10089                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
10090                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
10091                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
10092                     continue;
10093                 }
10094                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
10095                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
10096                 if (cinfo != null) {
10097                     ViewStructure child = structure.newChild(i);
10098                     populateVirtualStructure(child, provider, cinfo, forAutofill);
10099                     cinfo.recycle();
10100                 }
10101             }
10102         }
10103     }
10104 
10105     /**
10106      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
10107      * implementation calls {@link #onProvideStructure} and
10108      * {@link #onProvideVirtualStructure}.
10109      */
dispatchProvideStructure(ViewStructure structure)10110     public void dispatchProvideStructure(ViewStructure structure) {
10111         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
10112     }
10113 
10114     /**
10115      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
10116      * when an Assist structure is being created as part of an autofill request.
10117      *
10118      * <p>The default implementation does the following:
10119      * <ul>
10120      *   <li>Sets the {@link AutofillId} in the structure.
10121      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
10122      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
10123      * </ul>
10124      *
10125      * <p>Typically, this method should only be overridden by subclasses that provide a view
10126      * hierarchy (such as {@link ViewGroup}) - other classes should override
10127      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
10128      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
10129      *
10130      * <p>When overridden, it must:
10131      *
10132      * <ul>
10133      *   <li>Either call
10134      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
10135      *       set the {@link AutofillId} in the structure (for example, by calling
10136      *       {@code structure.setAutofillId(getAutofillId())}).
10137      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
10138      *       set, all views in the structure should be considered important for autofill,
10139      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
10140      *       respect this flag to provide a better user experience - this flag is typically used
10141      *       when an user explicitly requested autofill. If the flag is not set,
10142      *       then only views marked as important for autofill should be included in the
10143      *       structure - skipping non-important views optimizes the overall autofill performance.
10144      * </ul>
10145      *
10146      * @param structure fill in with structured view data for autofill purposes.
10147      * @param flags optional flags.
10148      *
10149      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
10150      */
dispatchProvideAutofillStructure(@onNull ViewStructure structure, @AutofillFlags int flags)10151     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
10152             @AutofillFlags int flags) {
10153         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
10154     }
10155 
dispatchProvideStructure(@onNull ViewStructure structure, @ViewStructureType int viewFor, @AutofillFlags int flags)10156     private void dispatchProvideStructure(@NonNull ViewStructure structure,
10157             @ViewStructureType int viewFor, @AutofillFlags int flags) {
10158         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
10159             structure.setAutofillId(getAutofillId());
10160             onProvideAutofillStructure(structure, flags);
10161             onProvideAutofillVirtualStructure(structure, flags);
10162         } else if (!isAssistBlocked()) {
10163             onProvideStructure(structure);
10164             onProvideVirtualStructure(structure);
10165         } else {
10166             structure.setClassName(getAccessibilityClassName().toString());
10167             structure.setAssistBlocked(true);
10168         }
10169     }
10170 
10171     /**
10172      * Dispatches the initial content capture events for a view structure.
10173      *
10174      * @hide
10175      */
dispatchInitialProvideContentCaptureStructure()10176     public void dispatchInitialProvideContentCaptureStructure() {
10177         AttachInfo ai = mAttachInfo;
10178         if (ai == null) {
10179             Log.w(CONTENT_CAPTURE_LOG_TAG,
10180                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
10181             return;
10182         }
10183         ContentCaptureManager ccm = ai.mContentCaptureManager;
10184         if (ccm == null) {
10185             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
10186                     + "no ContentCaptureManager for " + this);
10187             return;
10188         }
10189 
10190         // We must set it before checkign if the view itself is important, because it might
10191         // initially not be (for example, if it's empty), although that might change later (for
10192         // example, if important views are added)
10193         ai.mReadyForContentCaptureUpdates = true;
10194 
10195         if (!isImportantForContentCapture()) {
10196             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10197                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10198                         "dispatchProvideContentCaptureStructure(): decorView is not important");
10199             }
10200             return;
10201         }
10202 
10203         ai.mContentCaptureManager = ccm;
10204 
10205         ContentCaptureSession session = getContentCaptureSession();
10206         if (session == null) {
10207             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10208                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10209                         "dispatchProvideContentCaptureStructure(): no session for " + this);
10210             }
10211             return;
10212         }
10213 
10214         session.internalNotifyViewTreeEvent(/* started= */ true);
10215         try {
10216             dispatchProvideContentCaptureStructure();
10217         } finally {
10218             session.internalNotifyViewTreeEvent(/* started= */ false);
10219         }
10220     }
10221 
10222     /** @hide */
dispatchProvideContentCaptureStructure()10223     void dispatchProvideContentCaptureStructure() {
10224         ContentCaptureSession session = getContentCaptureSession();
10225         if (session != null) {
10226             ViewStructure structure = session.newViewStructure(this);
10227             onProvideContentCaptureStructure(structure, /* flags= */ 0);
10228             setNotifiedContentCaptureAppeared();
10229             session.notifyViewAppeared(structure);
10230         }
10231     }
10232 
10233     /**
10234      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
10235      *
10236      * Note: Called from the default {@link AccessibilityDelegate}.
10237      *
10238      * @hide
10239      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)10240     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
10241         if (mAttachInfo == null) {
10242             return;
10243         }
10244 
10245         Rect bounds = mAttachInfo.mTmpInvalRect;
10246 
10247         getDrawingRect(bounds);
10248         info.setBoundsInParent(bounds);
10249 
10250         getBoundsOnScreen(bounds, true);
10251         info.setBoundsInScreen(bounds);
10252 
10253         ViewParent parent = getParentForAccessibility();
10254         if (parent instanceof View) {
10255             info.setParent((View) parent);
10256         }
10257 
10258         if (mID != View.NO_ID) {
10259             View rootView = getRootView();
10260             if (rootView == null) {
10261                 rootView = this;
10262             }
10263 
10264             View label = rootView.findLabelForView(this, mID);
10265             if (label != null) {
10266                 info.setLabeledBy(label);
10267             }
10268 
10269             if ((mAttachInfo.mAccessibilityFetchFlags
10270                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
10271                     && Resources.resourceHasPackage(mID)) {
10272                 try {
10273                     String viewId = getResources().getResourceName(mID);
10274                     info.setViewIdResourceName(viewId);
10275                 } catch (Resources.NotFoundException nfe) {
10276                     /* ignore */
10277                 }
10278             }
10279         }
10280 
10281         if (mLabelForId != View.NO_ID) {
10282             View rootView = getRootView();
10283             if (rootView == null) {
10284                 rootView = this;
10285             }
10286             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
10287             if (labeled != null) {
10288                 info.setLabelFor(labeled);
10289             }
10290         }
10291 
10292         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
10293             View rootView = getRootView();
10294             if (rootView == null) {
10295                 rootView = this;
10296             }
10297             View next = rootView.findViewInsideOutShouldExist(this,
10298                     mAccessibilityTraversalBeforeId);
10299             if (next != null && next.includeForAccessibility()) {
10300                 info.setTraversalBefore(next);
10301             }
10302         }
10303 
10304         if (mAccessibilityTraversalAfterId != View.NO_ID) {
10305             View rootView = getRootView();
10306             if (rootView == null) {
10307                 rootView = this;
10308             }
10309             View next = rootView.findViewInsideOutShouldExist(this,
10310                     mAccessibilityTraversalAfterId);
10311             if (next != null && next.includeForAccessibility()) {
10312                 info.setTraversalAfter(next);
10313             }
10314         }
10315 
10316         info.setVisibleToUser(isVisibleToUser());
10317 
10318         info.setImportantForAccessibility(isImportantForAccessibility());
10319         info.setPackageName(mContext.getPackageName());
10320         info.setClassName(getAccessibilityClassName());
10321         info.setStateDescription(getStateDescription());
10322         info.setContentDescription(getContentDescription());
10323 
10324         info.setEnabled(isEnabled());
10325         info.setClickable(isClickable());
10326         info.setFocusable(isFocusable());
10327         info.setScreenReaderFocusable(isScreenReaderFocusable());
10328         info.setFocused(isFocused());
10329         info.setAccessibilityFocused(isAccessibilityFocused());
10330         info.setSelected(isSelected());
10331         info.setLongClickable(isLongClickable());
10332         info.setContextClickable(isContextClickable());
10333         info.setLiveRegion(getAccessibilityLiveRegion());
10334         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
10335             info.setTooltipText(mTooltipInfo.mTooltipText);
10336             info.addAction((mTooltipInfo.mTooltipPopup == null)
10337                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
10338                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
10339         }
10340 
10341         // TODO: These make sense only if we are in an AdapterView but all
10342         // views can be selected. Maybe from accessibility perspective
10343         // we should report as selectable view in an AdapterView.
10344         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
10345         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
10346 
10347         if (isFocusable()) {
10348             if (isFocused()) {
10349                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
10350             } else {
10351                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
10352             }
10353         }
10354 
10355         if (!isAccessibilityFocused()) {
10356             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
10357         } else {
10358             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
10359         }
10360 
10361         if (isClickable() && isEnabled()) {
10362             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
10363         }
10364 
10365         if (isLongClickable() && isEnabled()) {
10366             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
10367         }
10368 
10369         if (isContextClickable() && isEnabled()) {
10370             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
10371         }
10372 
10373         CharSequence text = getIterableTextForAccessibility();
10374         if (text != null && text.length() > 0) {
10375             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
10376 
10377             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
10378             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
10379             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
10380             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
10381                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
10382                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
10383         }
10384 
10385         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
10386         populateAccessibilityNodeInfoDrawingOrderInParent(info);
10387         info.setPaneTitle(mAccessibilityPaneTitle);
10388         info.setHeading(isAccessibilityHeading());
10389 
10390         if (mTouchDelegate != null) {
10391             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
10392         }
10393 
10394         if (startedSystemDragForAccessibility()) {
10395             info.addAction(AccessibilityAction.ACTION_DRAG_CANCEL);
10396         }
10397 
10398         if (canAcceptAccessibilityDrop()) {
10399             info.addAction(AccessibilityAction.ACTION_DRAG_DROP);
10400         }
10401     }
10402 
10403 
10404     /**
10405      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
10406      * additional data.
10407      * <p>
10408      * This method only needs overloading if the node is marked as having extra data available.
10409      * </p>
10410      *
10411      * @param info The info to which to add the extra data. Never {@code null}.
10412      * @param extraDataKey A key specifying the type of extra data to add to the info. The
10413      *                     extra data should be added to the {@link Bundle} returned by
10414      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
10415      *                     {@code null}.
10416      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
10417      *                  {@code null} if the service provided no arguments.
10418      *
10419      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
10420      */
addExtraDataToAccessibilityNodeInfo( @onNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)10421     public void addExtraDataToAccessibilityNodeInfo(
10422             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
10423             @Nullable Bundle arguments) {
10424     }
10425 
10426     /**
10427      * Determine the order in which this view will be drawn relative to its siblings for a11y
10428      *
10429      * @param info The info whose drawing order should be populated
10430      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)10431     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
10432         /*
10433          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
10434          * drawing order may not be well-defined, and some Views with custom drawing order may
10435          * not be initialized sufficiently to respond properly getChildDrawingOrder.
10436          */
10437         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
10438             info.setDrawingOrder(0);
10439             return;
10440         }
10441         int drawingOrderInParent = 1;
10442         // Iterate up the hierarchy if parents are not important for a11y
10443         View viewAtDrawingLevel = this;
10444         final ViewParent parent = getParentForAccessibility();
10445         while (viewAtDrawingLevel != parent) {
10446             final ViewParent currentParent = viewAtDrawingLevel.getParent();
10447             if (!(currentParent instanceof ViewGroup)) {
10448                 // Should only happen for the Decor
10449                 drawingOrderInParent = 0;
10450                 break;
10451             } else {
10452                 final ViewGroup parentGroup = (ViewGroup) currentParent;
10453                 final int childCount = parentGroup.getChildCount();
10454                 if (childCount > 1) {
10455                     List<View> preorderedList = parentGroup.buildOrderedChildList();
10456                     if (preorderedList != null) {
10457                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
10458                         for (int i = 0; i < childDrawIndex; i++) {
10459                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
10460                         }
10461                         preorderedList.clear();
10462                     } else {
10463                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
10464                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
10465                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
10466                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
10467                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
10468                         if (childDrawIndex != 0) {
10469                             for (int i = 0; i < numChildrenToIterate; i++) {
10470                                 final int otherDrawIndex = (customOrder ?
10471                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
10472                                 if (otherDrawIndex < childDrawIndex) {
10473                                     drawingOrderInParent +=
10474                                             numViewsForAccessibility(parentGroup.getChildAt(i));
10475                                 }
10476                             }
10477                         }
10478                     }
10479                 }
10480             }
10481             viewAtDrawingLevel = (View) currentParent;
10482         }
10483         info.setDrawingOrder(drawingOrderInParent);
10484     }
10485 
numViewsForAccessibility(View view)10486     private static int numViewsForAccessibility(View view) {
10487         if (view != null) {
10488             if (view.includeForAccessibility()) {
10489                 return 1;
10490             } else if (view instanceof ViewGroup) {
10491                 return ((ViewGroup) view).getNumChildrenForAccessibility();
10492             }
10493         }
10494         return 0;
10495     }
10496 
findLabelForView(View view, int labeledId)10497     private View findLabelForView(View view, int labeledId) {
10498         if (mMatchLabelForPredicate == null) {
10499             mMatchLabelForPredicate = new MatchLabelForPredicate();
10500         }
10501         mMatchLabelForPredicate.mLabeledId = labeledId;
10502         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
10503     }
10504 
10505     /**
10506      * Computes whether this virtual autofill view is visible to the user.
10507      *
10508      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
10509      * view must override it.
10510      *
10511      * @return Whether the view is visible on the screen.
10512      */
isVisibleToUserForAutofill(int virtualId)10513     public boolean isVisibleToUserForAutofill(int virtualId) {
10514         if (mContext.isAutofillCompatibilityEnabled()) {
10515             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10516             if (provider != null) {
10517                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
10518                 if (node != null) {
10519                     return node.isVisibleToUser();
10520                 }
10521                 // if node is null, assume it's not visible anymore
10522             } else {
10523                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
10524             }
10525             return false;
10526         }
10527         return true;
10528     }
10529 
10530     /**
10531      * Computes whether this view is visible to the user. Such a view is
10532      * attached, visible, all its predecessors are visible, it is not clipped
10533      * entirely by its predecessors, and has an alpha greater than zero.
10534      *
10535      * @return Whether the view is visible on the screen.
10536      *
10537      * @hide
10538      */
10539     @UnsupportedAppUsage
isVisibleToUser()10540     public boolean isVisibleToUser() {
10541         return isVisibleToUser(null);
10542     }
10543 
10544     /**
10545      * Computes whether the given portion of this view is visible to the user.
10546      * Such a view is attached, visible, all its predecessors are visible,
10547      * has an alpha greater than zero, and the specified portion is not
10548      * clipped entirely by its predecessors.
10549      *
10550      * @param boundInView the portion of the view to test; coordinates should be relative; may be
10551      *                    <code>null</code>, and the entire view will be tested in this case.
10552      *                    When <code>true</code> is returned by the function, the actual visible
10553      *                    region will be stored in this parameter; that is, if boundInView is fully
10554      *                    contained within the view, no modification will be made, otherwise regions
10555      *                    outside of the visible area of the view will be clipped.
10556      *
10557      * @return Whether the specified portion of the view is visible on the screen.
10558      *
10559      * @hide
10560      */
10561     @UnsupportedAppUsage(trackingBug = 171933273)
isVisibleToUser(Rect boundInView)10562     protected boolean isVisibleToUser(Rect boundInView) {
10563         if (mAttachInfo != null) {
10564             // Attached to invisible window means this view is not visible.
10565             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
10566                 return false;
10567             }
10568             // An invisible predecessor or one with alpha zero means
10569             // that this view is not visible to the user.
10570             Object current = this;
10571             while (current instanceof View) {
10572                 View view = (View) current;
10573                 // We have attach info so this view is attached and there is no
10574                 // need to check whether we reach to ViewRootImpl on the way up.
10575                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
10576                         view.getVisibility() != VISIBLE) {
10577                     return false;
10578                 }
10579                 current = view.mParent;
10580             }
10581             // Check if the view is entirely covered by its predecessors.
10582             Rect visibleRect = mAttachInfo.mTmpInvalRect;
10583             Point offset = mAttachInfo.mPoint;
10584             if (!getGlobalVisibleRect(visibleRect, offset)) {
10585                 return false;
10586             }
10587             // Check if the visible portion intersects the rectangle of interest.
10588             if (boundInView != null) {
10589                 visibleRect.offset(-offset.x, -offset.y);
10590                 return boundInView.intersect(visibleRect);
10591             }
10592             return true;
10593         }
10594         return false;
10595     }
10596 
10597     /**
10598      * Returns the delegate for implementing accessibility support via
10599      * composition. For more details see {@link AccessibilityDelegate}.
10600      *
10601      * @return The delegate, or null if none set.
10602      */
getAccessibilityDelegate()10603     public AccessibilityDelegate getAccessibilityDelegate() {
10604         return mAccessibilityDelegate;
10605     }
10606 
10607     /**
10608      * Sets a delegate for implementing accessibility support via composition
10609      * (as opposed to inheritance). For more details, see
10610      * {@link AccessibilityDelegate}.
10611      * <p>
10612      * <strong>Note:</strong> On platform versions prior to
10613      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
10614      * views in the {@code android.widget.*} package are called <i>before</i>
10615      * host methods. This prevents certain properties such as class name from
10616      * being modified by overriding
10617      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
10618      * as any changes will be overwritten by the host class.
10619      * <p>
10620      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
10621      * methods are called <i>after</i> host methods, which all properties to be
10622      * modified without being overwritten by the host class.
10623      *
10624      * @param delegate the object to which accessibility method calls should be
10625      *                 delegated
10626      * @see AccessibilityDelegate
10627      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)10628     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
10629         mAccessibilityDelegate = delegate;
10630     }
10631 
10632     /**
10633      * Gets the provider for managing a virtual view hierarchy rooted at this View
10634      * and reported to {@link android.accessibilityservice.AccessibilityService}s
10635      * that explore the window content.
10636      * <p>
10637      * If this method returns an instance, this instance is responsible for managing
10638      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
10639      * View including the one representing the View itself. Similarly the returned
10640      * instance is responsible for performing accessibility actions on any virtual
10641      * view or the root view itself.
10642      * </p>
10643      * <p>
10644      * If an {@link AccessibilityDelegate} has been specified via calling
10645      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10646      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
10647      * is responsible for handling this call.
10648      * </p>
10649      *
10650      * @return The provider.
10651      *
10652      * @see AccessibilityNodeProvider
10653      */
getAccessibilityNodeProvider()10654     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
10655         if (mAccessibilityDelegate != null) {
10656             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
10657         } else {
10658             return null;
10659         }
10660     }
10661 
10662     /**
10663      * Gets the unique identifier of this view on the screen for accessibility purposes.
10664      *
10665      * @return The view accessibility id.
10666      *
10667      * @hide
10668      */
10669     @UnsupportedAppUsage
getAccessibilityViewId()10670     public int getAccessibilityViewId() {
10671         if (mAccessibilityViewId == NO_ID) {
10672             mAccessibilityViewId = sNextAccessibilityViewId++;
10673         }
10674         return mAccessibilityViewId;
10675     }
10676 
10677     /**
10678      * Gets the unique identifier of this view on the screen for autofill purposes.
10679      *
10680      * @return The view autofill id.
10681      *
10682      * @hide
10683      */
getAutofillViewId()10684     public int getAutofillViewId() {
10685         if (mAutofillViewId == NO_ID) {
10686             mAutofillViewId = mContext.getNextAutofillId();
10687         }
10688         return mAutofillViewId;
10689     }
10690 
10691     /**
10692      * Gets the unique identifier of the window in which this View resides.
10693      *
10694      * @return The window accessibility id.
10695      *
10696      * @hide
10697      */
getAccessibilityWindowId()10698     public int getAccessibilityWindowId() {
10699         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
10700                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
10701     }
10702 
10703     /**
10704      * Returns the {@link View}'s state description.
10705      * <p>
10706      * <strong>Note:</strong> Do not override this method, as it will have no
10707      * effect on the state description presented to accessibility services.
10708      * You must call {@link #setStateDescription(CharSequence)} to modify the
10709      * state description.
10710      *
10711      * @return the state description
10712      * @see #setStateDescription(CharSequence)
10713      */
10714     @ViewDebug.ExportedProperty(category = "accessibility")
getStateDescription()10715     public final @Nullable CharSequence getStateDescription() {
10716         return mStateDescription;
10717     }
10718 
10719     /**
10720      * Returns the {@link View}'s content description.
10721      * <p>
10722      * <strong>Note:</strong> Do not override this method, as it will have no
10723      * effect on the content description presented to accessibility services.
10724      * You must call {@link #setContentDescription(CharSequence)} to modify the
10725      * content description.
10726      *
10727      * @return the content description
10728      * @see #setContentDescription(CharSequence)
10729      * @attr ref android.R.styleable#View_contentDescription
10730      */
10731     @ViewDebug.ExportedProperty(category = "accessibility")
10732     @InspectableProperty
getContentDescription()10733     public CharSequence getContentDescription() {
10734         return mContentDescription;
10735     }
10736 
10737     /**
10738      * Sets the {@link View}'s state description.
10739      * <p>
10740      * A state description briefly describes the states of the view and is primarily used
10741      * for accessibility support to determine how the states of a view should be presented to
10742      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
10743      * it is used for customized state description (for example, "wifi, connected, three bars").
10744      * State description changes frequently while content description should change less often.
10745      * State description should be localized. For android widgets which have default state
10746      * descriptions, app developers can call this method to override the state descriptions.
10747      * Setting state description to null restores the default behavior.
10748      *
10749      * @param stateDescription The state description.
10750      * @see #getStateDescription()
10751      */
10752     @RemotableViewMethod
setStateDescription(@ullable CharSequence stateDescription)10753     public void setStateDescription(@Nullable CharSequence stateDescription) {
10754         if (mStateDescription == null) {
10755             if (stateDescription == null) {
10756                 return;
10757             }
10758         } else if (mStateDescription.equals(stateDescription)) {
10759             return;
10760         }
10761         mStateDescription = stateDescription;
10762         if (!TextUtils.isEmpty(stateDescription)
10763                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10764             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10765         }
10766         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10767             AccessibilityEvent event = AccessibilityEvent.obtain();
10768             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
10769             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
10770             sendAccessibilityEventUnchecked(event);
10771         }
10772     }
10773 
10774     /**
10775      * Sets the {@link View}'s content description.
10776      * <p>
10777      * A content description briefly describes the view and is primarily used
10778      * for accessibility support to determine how a view should be presented to
10779      * the user. In the case of a view with no textual representation, such as
10780      * {@link android.widget.ImageButton}, a useful content description
10781      * explains what the view does. For example, an image button with a phone
10782      * icon that is used to place a call may use "Call" as its content
10783      * description. An image of a floppy disk that is used to save a file may
10784      * use "Save".
10785      *
10786      * @param contentDescription The content description.
10787      * @see #getContentDescription()
10788      * @attr ref android.R.styleable#View_contentDescription
10789      */
10790     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)10791     public void setContentDescription(CharSequence contentDescription) {
10792         if (mContentDescription == null) {
10793             if (contentDescription == null) {
10794                 return;
10795             }
10796         } else if (mContentDescription.equals(contentDescription)) {
10797             return;
10798         }
10799         mContentDescription = contentDescription;
10800         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
10801         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10802             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10803             notifySubtreeAccessibilityStateChangedIfNeeded();
10804         } else {
10805             notifyViewAccessibilityStateChangedIfNeeded(
10806                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
10807         }
10808     }
10809 
10810     /**
10811      * Sets the id of a view before which this one is visited in accessibility traversal.
10812      * A screen-reader must visit the content of this view before the content of the one
10813      * it precedes. For example, if view B is set to be before view A, then a screen-reader
10814      * will traverse the entire content of B before traversing the entire content of A,
10815      * regardles of what traversal strategy it is using.
10816      * <p>
10817      * Views that do not have specified before/after relationships are traversed in order
10818      * determined by the screen-reader.
10819      * </p>
10820      * <p>
10821      * Setting that this view is before a view that is not important for accessibility
10822      * or if this view is not important for accessibility will have no effect as the
10823      * screen-reader is not aware of unimportant views.
10824      * </p>
10825      *
10826      * @param beforeId The id of a view this one precedes in accessibility traversal.
10827      *
10828      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
10829      *
10830      * @see #setImportantForAccessibility(int)
10831      */
10832     @RemotableViewMethod
setAccessibilityTraversalBefore(@dRes int beforeId)10833     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
10834         if (mAccessibilityTraversalBeforeId == beforeId) {
10835             return;
10836         }
10837         mAccessibilityTraversalBeforeId = beforeId;
10838         notifyViewAccessibilityStateChangedIfNeeded(
10839                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10840     }
10841 
10842     /**
10843      * Gets the id of a view before which this one is visited in accessibility traversal.
10844      *
10845      * @return The id of a view this one precedes in accessibility traversal if
10846      *         specified, otherwise {@link #NO_ID}.
10847      *
10848      * @see #setAccessibilityTraversalBefore(int)
10849      */
10850     @IdRes
10851     @InspectableProperty
getAccessibilityTraversalBefore()10852     public int getAccessibilityTraversalBefore() {
10853         return mAccessibilityTraversalBeforeId;
10854     }
10855 
10856     /**
10857      * Sets the id of a view after which this one is visited in accessibility traversal.
10858      * A screen-reader must visit the content of the other view before the content of this
10859      * one. For example, if view B is set to be after view A, then a screen-reader
10860      * will traverse the entire content of A before traversing the entire content of B,
10861      * regardles of what traversal strategy it is using.
10862      * <p>
10863      * Views that do not have specified before/after relationships are traversed in order
10864      * determined by the screen-reader.
10865      * </p>
10866      * <p>
10867      * Setting that this view is after a view that is not important for accessibility
10868      * or if this view is not important for accessibility will have no effect as the
10869      * screen-reader is not aware of unimportant views.
10870      * </p>
10871      *
10872      * @param afterId The id of a view this one succedees in accessibility traversal.
10873      *
10874      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
10875      *
10876      * @see #setImportantForAccessibility(int)
10877      */
10878     @RemotableViewMethod
setAccessibilityTraversalAfter(@dRes int afterId)10879     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
10880         if (mAccessibilityTraversalAfterId == afterId) {
10881             return;
10882         }
10883         mAccessibilityTraversalAfterId = afterId;
10884         notifyViewAccessibilityStateChangedIfNeeded(
10885                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10886     }
10887 
10888     /**
10889      * Gets the id of a view after which this one is visited in accessibility traversal.
10890      *
10891      * @return The id of a view this one succeedes in accessibility traversal if
10892      *         specified, otherwise {@link #NO_ID}.
10893      *
10894      * @see #setAccessibilityTraversalAfter(int)
10895      */
10896     @IdRes
10897     @InspectableProperty
getAccessibilityTraversalAfter()10898     public int getAccessibilityTraversalAfter() {
10899         return mAccessibilityTraversalAfterId;
10900     }
10901 
10902     /**
10903      * Gets the id of a view for which this view serves as a label for
10904      * accessibility purposes.
10905      *
10906      * @return The labeled view id.
10907      */
10908     @IdRes
10909     @ViewDebug.ExportedProperty(category = "accessibility")
10910     @InspectableProperty
getLabelFor()10911     public int getLabelFor() {
10912         return mLabelForId;
10913     }
10914 
10915     /**
10916      * Sets the id of a view for which this view serves as a label for
10917      * accessibility purposes.
10918      *
10919      * @param id The labeled view id.
10920      */
10921     @RemotableViewMethod
setLabelFor(@dRes int id)10922     public void setLabelFor(@IdRes int id) {
10923         if (mLabelForId == id) {
10924             return;
10925         }
10926         mLabelForId = id;
10927         if (mLabelForId != View.NO_ID
10928                 && mID == View.NO_ID) {
10929             mID = generateViewId();
10930         }
10931         notifyViewAccessibilityStateChangedIfNeeded(
10932                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10933     }
10934 
10935     /**
10936      * Invoked whenever this view loses focus, either by losing window focus or by losing
10937      * focus within its window. This method can be used to clear any state tied to the
10938      * focus. For instance, if a button is held pressed with the trackball and the window
10939      * loses focus, this method can be used to cancel the press.
10940      *
10941      * Subclasses of View overriding this method should always call super.onFocusLost().
10942      *
10943      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
10944      * @see #onWindowFocusChanged(boolean)
10945      *
10946      * @hide pending API council approval
10947      */
10948     @CallSuper
10949     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onFocusLost()10950     protected void onFocusLost() {
10951         resetPressedState();
10952     }
10953 
resetPressedState()10954     private void resetPressedState() {
10955         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10956             return;
10957         }
10958 
10959         if (isPressed()) {
10960             setPressed(false);
10961 
10962             if (!mHasPerformedLongPress) {
10963                 removeLongPressCallback();
10964             }
10965         }
10966     }
10967 
10968     /**
10969      * Returns true if this view has focus
10970      *
10971      * @return True if this view has focus, false otherwise.
10972      */
10973     @ViewDebug.ExportedProperty(category = "focus")
10974     @InspectableProperty(hasAttributeId = false)
isFocused()10975     public boolean isFocused() {
10976         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
10977     }
10978 
10979     /**
10980      * Find the view in the hierarchy rooted at this view that currently has
10981      * focus.
10982      *
10983      * @return The view that currently has focus, or null if no focused view can
10984      *         be found.
10985      */
findFocus()10986     public View findFocus() {
10987         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
10988     }
10989 
10990     /**
10991      * Indicates whether this view is one of the set of scrollable containers in
10992      * its window.
10993      *
10994      * @return whether this view is one of the set of scrollable containers in
10995      * its window
10996      *
10997      * @attr ref android.R.styleable#View_isScrollContainer
10998      */
10999     @InspectableProperty(name = "isScrollContainer")
isScrollContainer()11000     public boolean isScrollContainer() {
11001         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
11002     }
11003 
11004     /**
11005      * Change whether this view is one of the set of scrollable containers in
11006      * its window.  This will be used to determine whether the window can
11007      * resize or must pan when a soft input area is open -- scrollable
11008      * containers allow the window to use resize mode since the container
11009      * will appropriately shrink.
11010      *
11011      * @attr ref android.R.styleable#View_isScrollContainer
11012      */
setScrollContainer(boolean isScrollContainer)11013     public void setScrollContainer(boolean isScrollContainer) {
11014         if (isScrollContainer) {
11015             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
11016                 mAttachInfo.mScrollContainers.add(this);
11017                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
11018             }
11019             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
11020         } else {
11021             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
11022                 mAttachInfo.mScrollContainers.remove(this);
11023             }
11024             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
11025         }
11026     }
11027 
11028     /**
11029      * Returns the quality of the drawing cache.
11030      *
11031      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11032      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11033      *
11034      * @see #setDrawingCacheQuality(int)
11035      * @see #setDrawingCacheEnabled(boolean)
11036      * @see #isDrawingCacheEnabled()
11037      *
11038      * @attr ref android.R.styleable#View_drawingCacheQuality
11039      *
11040      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11041      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11042      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11043      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11044      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11045      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11046      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11047      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11048      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11049      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11050      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11051      * reports or unit testing the {@link PixelCopy} API is recommended.
11052      */
11053     @Deprecated
11054     @DrawingCacheQuality
11055     @InspectableProperty(enumMapping = {
11056             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
11057             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
11058             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
11059     })
getDrawingCacheQuality()11060     public int getDrawingCacheQuality() {
11061         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
11062     }
11063 
11064     /**
11065      * Set the drawing cache quality of this view. This value is used only when the
11066      * drawing cache is enabled
11067      *
11068      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11069      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11070      *
11071      * @see #getDrawingCacheQuality()
11072      * @see #setDrawingCacheEnabled(boolean)
11073      * @see #isDrawingCacheEnabled()
11074      *
11075      * @attr ref android.R.styleable#View_drawingCacheQuality
11076      *
11077      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11078      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11079      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11080      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11081      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11082      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11083      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11084      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11085      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11086      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11087      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11088      * reports or unit testing the {@link PixelCopy} API is recommended.
11089      */
11090     @Deprecated
setDrawingCacheQuality(@rawingCacheQuality int quality)11091     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
11092         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
11093     }
11094 
11095     /**
11096      * Returns whether the screen should remain on, corresponding to the current
11097      * value of {@link #KEEP_SCREEN_ON}.
11098      *
11099      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
11100      *
11101      * @see #setKeepScreenOn(boolean)
11102      *
11103      * @attr ref android.R.styleable#View_keepScreenOn
11104      */
11105     @InspectableProperty
getKeepScreenOn()11106     public boolean getKeepScreenOn() {
11107         return (mViewFlags & KEEP_SCREEN_ON) != 0;
11108     }
11109 
11110     /**
11111      * Controls whether the screen should remain on, modifying the
11112      * value of {@link #KEEP_SCREEN_ON}.
11113      *
11114      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
11115      *
11116      * @see #getKeepScreenOn()
11117      *
11118      * @attr ref android.R.styleable#View_keepScreenOn
11119      */
setKeepScreenOn(boolean keepScreenOn)11120     public void setKeepScreenOn(boolean keepScreenOn) {
11121         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
11122     }
11123 
11124     /**
11125      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11126      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11127      *
11128      * @attr ref android.R.styleable#View_nextFocusLeft
11129      */
11130     @IdRes
11131     @InspectableProperty(name = "nextFocusLeft")
getNextFocusLeftId()11132     public int getNextFocusLeftId() {
11133         return mNextFocusLeftId;
11134     }
11135 
11136     /**
11137      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11138      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
11139      * decide automatically.
11140      *
11141      * @attr ref android.R.styleable#View_nextFocusLeft
11142      */
setNextFocusLeftId(@dRes int nextFocusLeftId)11143     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
11144         mNextFocusLeftId = nextFocusLeftId;
11145     }
11146 
11147     /**
11148      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11149      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11150      *
11151      * @attr ref android.R.styleable#View_nextFocusRight
11152      */
11153     @IdRes
11154     @InspectableProperty(name = "nextFocusRight")
getNextFocusRightId()11155     public int getNextFocusRightId() {
11156         return mNextFocusRightId;
11157     }
11158 
11159     /**
11160      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11161      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
11162      * decide automatically.
11163      *
11164      * @attr ref android.R.styleable#View_nextFocusRight
11165      */
setNextFocusRightId(@dRes int nextFocusRightId)11166     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
11167         mNextFocusRightId = nextFocusRightId;
11168     }
11169 
11170     /**
11171      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11172      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11173      *
11174      * @attr ref android.R.styleable#View_nextFocusUp
11175      */
11176     @IdRes
11177     @InspectableProperty(name = "nextFocusUp")
getNextFocusUpId()11178     public int getNextFocusUpId() {
11179         return mNextFocusUpId;
11180     }
11181 
11182     /**
11183      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11184      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
11185      * decide automatically.
11186      *
11187      * @attr ref android.R.styleable#View_nextFocusUp
11188      */
setNextFocusUpId(@dRes int nextFocusUpId)11189     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
11190         mNextFocusUpId = nextFocusUpId;
11191     }
11192 
11193     /**
11194      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11195      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11196      *
11197      * @attr ref android.R.styleable#View_nextFocusDown
11198      */
11199     @IdRes
11200     @InspectableProperty(name = "nextFocusDown")
getNextFocusDownId()11201     public int getNextFocusDownId() {
11202         return mNextFocusDownId;
11203     }
11204 
11205     /**
11206      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11207      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
11208      * decide automatically.
11209      *
11210      * @attr ref android.R.styleable#View_nextFocusDown
11211      */
setNextFocusDownId(@dRes int nextFocusDownId)11212     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
11213         mNextFocusDownId = nextFocusDownId;
11214     }
11215 
11216     /**
11217      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11218      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11219      *
11220      * @attr ref android.R.styleable#View_nextFocusForward
11221      */
11222     @IdRes
11223     @InspectableProperty(name = "nextFocusForward")
getNextFocusForwardId()11224     public int getNextFocusForwardId() {
11225         return mNextFocusForwardId;
11226     }
11227 
11228     /**
11229      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11230      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
11231      * decide automatically.
11232      *
11233      * @attr ref android.R.styleable#View_nextFocusForward
11234      */
setNextFocusForwardId(@dRes int nextFocusForwardId)11235     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
11236         mNextFocusForwardId = nextFocusForwardId;
11237     }
11238 
11239     /**
11240      * Gets the id of the root of the next keyboard navigation cluster.
11241      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
11242      * decide automatically.
11243      *
11244      * @attr ref android.R.styleable#View_nextClusterForward
11245      */
11246     @IdRes
11247     @InspectableProperty(name = "nextClusterForward")
getNextClusterForwardId()11248     public int getNextClusterForwardId() {
11249         return mNextClusterForwardId;
11250     }
11251 
11252     /**
11253      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
11254      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
11255      * decide automatically.
11256      *
11257      * @attr ref android.R.styleable#View_nextClusterForward
11258      */
setNextClusterForwardId(@dRes int nextClusterForwardId)11259     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
11260         mNextClusterForwardId = nextClusterForwardId;
11261     }
11262 
11263     /**
11264      * Returns the visibility of this view and all of its ancestors
11265      *
11266      * @return True if this view and all of its ancestors are {@link #VISIBLE}
11267      */
isShown()11268     public boolean isShown() {
11269         View current = this;
11270         //noinspection ConstantConditions
11271         do {
11272             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
11273                 return false;
11274             }
11275             ViewParent parent = current.mParent;
11276             if (parent == null) {
11277                 return false; // We are not attached to the view root
11278             }
11279             if (!(parent instanceof View)) {
11280                 return true;
11281             }
11282             current = (View) parent;
11283         } while (current != null);
11284 
11285         return false;
11286     }
11287 
detached()11288     private boolean detached() {
11289         View current = this;
11290         //noinspection ConstantConditions
11291         do {
11292             if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
11293                 return true;
11294             }
11295             ViewParent parent = current.mParent;
11296             if (parent == null) {
11297                 return false;
11298             }
11299             if (!(parent instanceof View)) {
11300                 return false;
11301             }
11302             current = (View) parent;
11303         } while (current != null);
11304 
11305         return false;
11306     }
11307 
11308     /**
11309      * Called by the view hierarchy when the content insets for a window have
11310      * changed, to allow it to adjust its content to fit within those windows.
11311      * The content insets tell you the space that the status bar, input method,
11312      * and other system windows infringe on the application's window.
11313      *
11314      * <p>You do not normally need to deal with this function, since the default
11315      * window decoration given to applications takes care of applying it to the
11316      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
11317      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
11318      * and your content can be placed under those system elements.  You can then
11319      * use this method within your view hierarchy if you have parts of your UI
11320      * which you would like to ensure are not being covered.
11321      *
11322      * <p>The default implementation of this method simply applies the content
11323      * insets to the view's padding, consuming that content (modifying the
11324      * insets to be 0), and returning true.  This behavior is off by default, but can
11325      * be enabled through {@link #setFitsSystemWindows(boolean)}.
11326      *
11327      * <p>This function's traversal down the hierarchy is depth-first.  The same content
11328      * insets object is propagated down the hierarchy, so any changes made to it will
11329      * be seen by all following views (including potentially ones above in
11330      * the hierarchy since this is a depth-first traversal).  The first view
11331      * that returns true will abort the entire traversal.
11332      *
11333      * <p>The default implementation works well for a situation where it is
11334      * used with a container that covers the entire window, allowing it to
11335      * apply the appropriate insets to its content on all edges.  If you need
11336      * a more complicated layout (such as two different views fitting system
11337      * windows, one on the top of the window, and one on the bottom),
11338      * you can override the method and handle the insets however you would like.
11339      * Note that the insets provided by the framework are always relative to the
11340      * far edges of the window, not accounting for the location of the called view
11341      * within that window.  (In fact when this method is called you do not yet know
11342      * where the layout will place the view, as it is done before layout happens.)
11343      *
11344      * <p>Note: unlike many View methods, there is no dispatch phase to this
11345      * call.  If you are overriding it in a ViewGroup and want to allow the
11346      * call to continue to your children, you must be sure to call the super
11347      * implementation.
11348      *
11349      * <p>Here is a sample layout that makes use of fitting system windows
11350      * to have controls for a video view placed inside of the window decorations
11351      * that it hides and shows.  This can be used with code like the second
11352      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
11353      *
11354      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
11355      *
11356      * @param insets Current content insets of the window.  Prior to
11357      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
11358      * the insets or else you and Android will be unhappy.
11359      *
11360      * @return {@code true} if this view applied the insets and it should not
11361      * continue propagating further down the hierarchy, {@code false} otherwise.
11362      * @see #getFitsSystemWindows()
11363      * @see #setFitsSystemWindows(boolean)
11364      * @see #setSystemUiVisibility(int)
11365      *
11366      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
11367      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
11368      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
11369      * to implement handling their own insets.
11370      */
11371     @Deprecated
fitSystemWindows(Rect insets)11372     protected boolean fitSystemWindows(Rect insets) {
11373         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
11374             if (insets == null) {
11375                 // Null insets by definition have already been consumed.
11376                 // This call cannot apply insets since there are none to apply,
11377                 // so return false.
11378                 return false;
11379             }
11380             // If we're not in the process of dispatching the newer apply insets call,
11381             // that means we're not in the compatibility path. Dispatch into the newer
11382             // apply insets path and take things from there.
11383             try {
11384                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
11385                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
11386             } finally {
11387                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
11388             }
11389         } else {
11390             // We're being called from the newer apply insets path.
11391             // Perform the standard fallback behavior.
11392             return fitSystemWindowsInt(insets);
11393         }
11394     }
11395 
fitSystemWindowsInt(Rect insets)11396     private boolean fitSystemWindowsInt(Rect insets) {
11397         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
11398             Rect localInsets = sThreadLocal.get();
11399             boolean res = computeFitSystemWindows(insets, localInsets);
11400             applyInsets(localInsets);
11401             return res;
11402         }
11403         return false;
11404     }
11405 
applyInsets(Rect insets)11406     private void applyInsets(Rect insets) {
11407         mUserPaddingStart = UNDEFINED_PADDING;
11408         mUserPaddingEnd = UNDEFINED_PADDING;
11409         mUserPaddingLeftInitial = insets.left;
11410         mUserPaddingRightInitial = insets.right;
11411         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
11412     }
11413 
11414     /**
11415      * Called when the view should apply {@link WindowInsets} according to its internal policy.
11416      *
11417      * <p>This method should be overridden by views that wish to apply a policy different from or
11418      * in addition to the default behavior. Clients that wish to force a view subtree
11419      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
11420      *
11421      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
11422      * it will be called during dispatch instead of this method. The listener may optionally
11423      * call this method from its own implementation if it wishes to apply the view's default
11424      * insets policy in addition to its own.</p>
11425      *
11426      * <p>Implementations of this method should either return the insets parameter unchanged
11427      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
11428      * that this view applied itself. This allows new inset types added in future platform
11429      * versions to pass through existing implementations unchanged without being erroneously
11430      * consumed.</p>
11431      *
11432      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
11433      * property is set then the view will consume the system window insets and apply them
11434      * as padding for the view.</p>
11435      *
11436      * @param insets Insets to apply
11437      * @return The supplied insets with any applied insets consumed
11438      */
onApplyWindowInsets(WindowInsets insets)11439     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
11440         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11441                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
11442             return onApplyFrameworkOptionalFitSystemWindows(insets);
11443         }
11444         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
11445             // We weren't called from within a direct call to fitSystemWindows,
11446             // call into it as a fallback in case we're in a class that overrides it
11447             // and has logic to perform.
11448             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
11449                 return insets.consumeSystemWindowInsets();
11450             }
11451         } else {
11452             // We were called from within a direct call to fitSystemWindows.
11453             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
11454                 return insets.consumeSystemWindowInsets();
11455             }
11456         }
11457         return insets;
11458     }
11459 
onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets)11460     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
11461         Rect localInsets = sThreadLocal.get();
11462         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
11463         applyInsets(localInsets);
11464         return result;
11465     }
11466 
11467     /**
11468      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
11469      * window insets to this view. The listener's
11470      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
11471      * method will be called instead of the view's
11472      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
11473      *
11474      * @param listener Listener to set
11475      *
11476      * @see #onApplyWindowInsets(WindowInsets)
11477      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)11478     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
11479         getListenerInfo().mOnApplyWindowInsetsListener = listener;
11480     }
11481 
11482     /**
11483      * Request to apply the given window insets to this view or another view in its subtree.
11484      *
11485      * <p>This method should be called by clients wishing to apply insets corresponding to areas
11486      * obscured by window decorations or overlays. This can include the status and navigation bars,
11487      * action bars, input methods and more. New inset categories may be added in the future.
11488      * The method returns the insets provided minus any that were applied by this view or its
11489      * children.</p>
11490      *
11491      * <p>Clients wishing to provide custom behavior should override the
11492      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
11493      * {@link OnApplyWindowInsetsListener} via the
11494      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
11495      * method.</p>
11496      *
11497      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
11498      * </p>
11499      *
11500      * @param insets Insets to apply
11501      * @return The provided insets minus the insets that were consumed
11502      */
dispatchApplyWindowInsets(WindowInsets insets)11503     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
11504         try {
11505             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
11506             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
11507                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
11508             } else {
11509                 return onApplyWindowInsets(insets);
11510             }
11511         } finally {
11512             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
11513         }
11514     }
11515 
11516     /**
11517      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
11518      * cause insets.
11519      * <p>
11520      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
11521      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
11522      * this view.
11523      * </p>
11524      * @param callback The callback to set.
11525      */
setWindowInsetsAnimationCallback( @ullable WindowInsetsAnimation.Callback callback)11526     public void setWindowInsetsAnimationCallback(
11527             @Nullable WindowInsetsAnimation.Callback callback) {
11528         getListenerInfo().mWindowInsetsAnimationCallback = callback;
11529     }
11530 
11531     /**
11532      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
11533      *         or view tree of the sub-hierarchy {@code false} otherwise.
11534      * @hide
11535      */
hasWindowInsetsAnimationCallback()11536     public boolean hasWindowInsetsAnimationCallback() {
11537         return getListenerInfo().mWindowInsetsAnimationCallback != null;
11538     }
11539 
11540     /**
11541      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
11542      * when Window Insets animation is being prepared.
11543      * @param animation current animation
11544      *
11545      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
11546      */
dispatchWindowInsetsAnimationPrepare( @onNull WindowInsetsAnimation animation)11547     public void dispatchWindowInsetsAnimationPrepare(
11548             @NonNull WindowInsetsAnimation animation) {
11549         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11550             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
11551         }
11552     }
11553 
11554     /**
11555      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
11556      * when Window Insets animation is started.
11557      * @param animation current animation
11558      * @param bounds the upper and lower {@link Bounds} that provides range of
11559      *  {@link WindowInsetsAnimation}.
11560      * @return the upper and lower {@link Bounds}.
11561      */
11562     @NonNull
dispatchWindowInsetsAnimationStart( @onNull WindowInsetsAnimation animation, @NonNull Bounds bounds)11563     public Bounds dispatchWindowInsetsAnimationStart(
11564             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
11565         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11566             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
11567         }
11568         return bounds;
11569     }
11570 
11571     /**
11572      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
11573      * when Window Insets animation makes progress.
11574      * @param insets The current {@link WindowInsets}.
11575      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
11576      * @return current {@link WindowInsets}.
11577      */
11578     @NonNull
dispatchWindowInsetsAnimationProgress(@onNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations)11579     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
11580             @NonNull List<WindowInsetsAnimation> runningAnimations) {
11581         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11582             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
11583                     runningAnimations);
11584         } else {
11585             return insets;
11586         }
11587     }
11588 
11589     /**
11590      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
11591      * when Window Insets animation ends.
11592      * @param animation The current ongoing {@link WindowInsetsAnimation}.
11593      */
dispatchWindowInsetsAnimationEnd(@onNull WindowInsetsAnimation animation)11594     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
11595         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11596             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
11597         }
11598     }
11599 
11600     /**
11601      * Sets a list of areas within this view's post-layout coordinate space where the system
11602      * should not intercept touch or other pointing device gestures. <em>This method should
11603      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
11604      *
11605      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
11606      * input in order to function correctly in the presence of global system gestures that may
11607      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
11608      * to provide system-level navigation functionality, a view such as a navigation drawer
11609      * container can mark the left (or starting) edge of itself as requiring gesture capture
11610      * priority using this API. The system may then choose to relax its own gesture recognition
11611      * to allow the app to consume the user's gesture. It is not necessary for an app to register
11612      * exclusion rects for broadly spanning regions such as the entirety of a
11613      * <code>ScrollView</code> or for simple press and release click targets such as
11614      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
11615      * a precision touch gesture in a small area in either the X or Y dimension, such as
11616      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
11617      *
11618      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
11619      * exclusions it takes into account. The limit does not apply while the navigation
11620      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
11621      * {@link android.inputmethodservice.InputMethodService input method} and
11622      * {@link Intent#CATEGORY_HOME home activity}.
11623      * </p>
11624      *
11625      * @param rects A list of precision gesture regions that this view needs to function correctly
11626      */
setSystemGestureExclusionRects(@onNull List<Rect> rects)11627     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
11628         if (rects.isEmpty() && mListenerInfo == null) return;
11629 
11630         final ListenerInfo info = getListenerInfo();
11631         if (info.mSystemGestureExclusionRects != null) {
11632             info.mSystemGestureExclusionRects.clear();
11633             info.mSystemGestureExclusionRects.addAll(rects);
11634         } else {
11635             info.mSystemGestureExclusionRects = new ArrayList<>(rects);
11636         }
11637         if (rects.isEmpty()) {
11638             if (info.mPositionUpdateListener != null) {
11639                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
11640             }
11641         } else {
11642             if (info.mPositionUpdateListener == null) {
11643                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
11644                     @Override
11645                     public void positionChanged(long n, int l, int t, int r, int b) {
11646                         postUpdateSystemGestureExclusionRects();
11647                     }
11648 
11649                     @Override
11650                     public void positionLost(long frameNumber) {
11651                         postUpdateSystemGestureExclusionRects();
11652                     }
11653                 };
11654                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
11655             }
11656         }
11657         postUpdateSystemGestureExclusionRects();
11658     }
11659 
11660     /**
11661      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
11662      */
postUpdateSystemGestureExclusionRects()11663     void postUpdateSystemGestureExclusionRects() {
11664         // Potentially racey from a background thread. It's ok if it's not perfect.
11665         final Handler h = getHandler();
11666         if (h != null) {
11667             h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects);
11668         }
11669     }
11670 
updateSystemGestureExclusionRects()11671     void updateSystemGestureExclusionRects() {
11672         final AttachInfo ai = mAttachInfo;
11673         if (ai != null) {
11674             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
11675         }
11676     }
11677 
11678     /**
11679      * Retrieve the list of areas within this view's post-layout coordinate space where the system
11680      * should not intercept touch or other pointing device gestures.
11681      *
11682      * <p>Do not modify the returned list.</p>
11683      *
11684      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
11685      */
11686     @NonNull
getSystemGestureExclusionRects()11687     public List<Rect> getSystemGestureExclusionRects() {
11688         final ListenerInfo info = mListenerInfo;
11689         if (info != null) {
11690             final List<Rect> list = info.mSystemGestureExclusionRects;
11691             if (list != null) {
11692                 return list;
11693             }
11694         }
11695         return Collections.emptyList();
11696     }
11697 
11698     /**
11699      * Compute the view's coordinate within the surface.
11700      *
11701      * <p>Computes the coordinates of this view in its surface. The argument
11702      * must be an array of two integers. After the method returns, the array
11703      * contains the x and y location in that order.</p>
11704      *
11705      * @param location an array of two integers in which to hold the coordinates
11706      */
getLocationInSurface(@onNull @ize2) int[] location)11707     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
11708         getLocationInWindow(location);
11709         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
11710             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
11711             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
11712         }
11713     }
11714 
11715     /**
11716      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
11717      * only available if the view is attached.
11718      *
11719      * @return WindowInsets from the top of the view hierarchy or null if View is detached
11720      */
getRootWindowInsets()11721     public WindowInsets getRootWindowInsets() {
11722         if (mAttachInfo != null) {
11723             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
11724         }
11725         return null;
11726     }
11727 
11728     /**
11729      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
11730      *
11731      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
11732      *         a window nor a view tree with a decor.
11733      * @see Window#getInsetsController()
11734      */
getWindowInsetsController()11735     public @Nullable WindowInsetsController getWindowInsetsController() {
11736         if (mAttachInfo != null) {
11737             return mAttachInfo.mViewRootImpl.getInsetsController();
11738         }
11739         ViewParent parent = getParent();
11740         if (parent instanceof View) {
11741             return ((View) parent).getWindowInsetsController();
11742         } else if (parent instanceof ViewRootImpl) {
11743             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
11744             return ((ViewRootImpl) parent).getInsetsController();
11745         }
11746         return null;
11747     }
11748 
11749     /**
11750      * @hide Compute the insets that should be consumed by this view and the ones
11751      * that should propagate to those under it.
11752      *
11753      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
11754      *
11755      * @param inoutInsets the insets given to this view
11756      * @param outLocalInsets the insets that should be applied to this view
11757      * @deprecated use {@link #computeSystemWindowInsets}
11758      * @return
11759      */
11760     @Deprecated
11761     @UnsupportedAppUsage
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)11762     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
11763         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
11764                 outLocalInsets);
11765         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
11766         return innerInsets.isSystemWindowInsetsConsumed();
11767     }
11768 
11769     /**
11770      * Compute insets that should be consumed by this view and the ones that should propagate
11771      * to those under it.
11772      *
11773      * @param in Insets currently being processed by this View, likely received as a parameter
11774      *           to {@link #onApplyWindowInsets(WindowInsets)}.
11775      * @param outLocalInsets A Rect that will receive the insets that should be consumed
11776      *                       by this view
11777      * @return Insets that should be passed along to views under this one
11778      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)11779     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
11780         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11781                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
11782         if (isOptionalFitSystemWindows && mAttachInfo != null) {
11783             OnContentApplyWindowInsetsListener listener =
11784                     mAttachInfo.mContentOnApplyWindowInsetsListener;
11785             if (listener == null) {
11786                 // The application wants to take care of fitting system window for
11787                 // the content.
11788                 outLocalInsets.setEmpty();
11789                 return in;
11790             }
11791             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
11792             outLocalInsets.set(result.first.toRect());
11793             return result.second;
11794         } else {
11795             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
11796             return in.consumeSystemWindowInsets().inset(outLocalInsets);
11797         }
11798     }
11799 
11800     /**
11801      * Sets whether or not this view should account for system screen decorations
11802      * such as the status bar and inset its content; that is, controlling whether
11803      * the default implementation of {@link #fitSystemWindows(Rect)} will be
11804      * executed.  See that method for more details.
11805      *
11806      * <p>Note that if you are providing your own implementation of
11807      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
11808      * flag to true -- your implementation will be overriding the default
11809      * implementation that checks this flag.
11810      *
11811      * @param fitSystemWindows If true, then the default implementation of
11812      * {@link #fitSystemWindows(Rect)} will be executed.
11813      *
11814      * @attr ref android.R.styleable#View_fitsSystemWindows
11815      * @see #getFitsSystemWindows()
11816      * @see #fitSystemWindows(Rect)
11817      * @see #setSystemUiVisibility(int)
11818      */
setFitsSystemWindows(boolean fitSystemWindows)11819     public void setFitsSystemWindows(boolean fitSystemWindows) {
11820         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
11821     }
11822 
11823     /**
11824      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
11825      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
11826      * will be executed.
11827      *
11828      * @return {@code true} if the default implementation of
11829      * {@link #fitSystemWindows(Rect)} will be executed.
11830      *
11831      * @attr ref android.R.styleable#View_fitsSystemWindows
11832      * @see #setFitsSystemWindows(boolean)
11833      * @see #fitSystemWindows(Rect)
11834      * @see #setSystemUiVisibility(int)
11835      */
11836     @ViewDebug.ExportedProperty
11837     @InspectableProperty
getFitsSystemWindows()11838     public boolean getFitsSystemWindows() {
11839         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
11840     }
11841 
11842     /** @hide */
11843     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
fitsSystemWindows()11844     public boolean fitsSystemWindows() {
11845         return getFitsSystemWindows();
11846     }
11847 
11848     /**
11849      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
11850      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
11851      */
11852     @Deprecated
requestFitSystemWindows()11853     public void requestFitSystemWindows() {
11854         if (mParent != null) {
11855             mParent.requestFitSystemWindows();
11856         }
11857     }
11858 
11859     /**
11860      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
11861      */
requestApplyInsets()11862     public void requestApplyInsets() {
11863         requestFitSystemWindows();
11864     }
11865 
11866     /**
11867      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
11868      * @hide
11869      */
11870     @UnsupportedAppUsage
makeOptionalFitsSystemWindows()11871     public void makeOptionalFitsSystemWindows() {
11872         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
11873     }
11874 
11875     /**
11876      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
11877      * @hide
11878      */
makeFrameworkOptionalFitsSystemWindows()11879     public void makeFrameworkOptionalFitsSystemWindows() {
11880         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
11881     }
11882 
11883     /**
11884      * @hide
11885      */
isFrameworkOptionalFitsSystemWindows()11886     public boolean isFrameworkOptionalFitsSystemWindows() {
11887         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
11888     }
11889 
11890     /**
11891      * Returns the visibility status for this view.
11892      *
11893      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11894      * @attr ref android.R.styleable#View_visibility
11895      */
11896     @ViewDebug.ExportedProperty(mapping = {
11897         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
11898         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
11899         @ViewDebug.IntToString(from = GONE,      to = "GONE")
11900     })
11901     @InspectableProperty(enumMapping = {
11902             @EnumEntry(value = VISIBLE, name = "visible"),
11903             @EnumEntry(value = INVISIBLE, name = "invisible"),
11904             @EnumEntry(value = GONE, name = "gone")
11905     })
11906     @Visibility
getVisibility()11907     public int getVisibility() {
11908         return mViewFlags & VISIBILITY_MASK;
11909     }
11910 
11911     /**
11912      * Set the visibility state of this view.
11913      *
11914      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11915      * @attr ref android.R.styleable#View_visibility
11916      */
11917     @RemotableViewMethod
setVisibility(@isibility int visibility)11918     public void setVisibility(@Visibility int visibility) {
11919         setFlags(visibility, VISIBILITY_MASK);
11920     }
11921 
11922     /**
11923      * Returns the enabled status for this view. The interpretation of the
11924      * enabled state varies by subclass.
11925      *
11926      * @return True if this view is enabled, false otherwise.
11927      */
11928     @ViewDebug.ExportedProperty
11929     @InspectableProperty
isEnabled()11930     public boolean isEnabled() {
11931         return (mViewFlags & ENABLED_MASK) == ENABLED;
11932     }
11933 
11934     /**
11935      * Set the enabled state of this view. The interpretation of the enabled
11936      * state varies by subclass.
11937      *
11938      * @param enabled True if this view is enabled, false otherwise.
11939      */
11940     @RemotableViewMethod
setEnabled(boolean enabled)11941     public void setEnabled(boolean enabled) {
11942         if (enabled == isEnabled()) return;
11943 
11944         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
11945 
11946         /*
11947          * The View most likely has to change its appearance, so refresh
11948          * the drawable state.
11949          */
11950         refreshDrawableState();
11951 
11952         // Invalidate too, since the default behavior for views is to be
11953         // be drawn at 50% alpha rather than to change the drawable.
11954         invalidate(true);
11955 
11956         if (!enabled) {
11957             cancelPendingInputEvents();
11958         }
11959     }
11960 
11961     /**
11962      * Set whether this view can receive the focus.
11963      * <p>
11964      * Setting this to false will also ensure that this view is not focusable
11965      * in touch mode.
11966      *
11967      * @param focusable If true, this view can receive the focus.
11968      *
11969      * @see #setFocusableInTouchMode(boolean)
11970      * @see #setFocusable(int)
11971      * @attr ref android.R.styleable#View_focusable
11972      */
11973     @RemotableViewMethod
setFocusable(boolean focusable)11974     public void setFocusable(boolean focusable) {
11975         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
11976     }
11977 
11978     /**
11979      * Sets whether this view can receive focus.
11980      * <p>
11981      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
11982      * automatically based on the view's interactivity. This is the default.
11983      * <p>
11984      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
11985      * in touch mode.
11986      *
11987      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
11988      *                  or {@link #FOCUSABLE_AUTO}.
11989      * @see #setFocusableInTouchMode(boolean)
11990      * @attr ref android.R.styleable#View_focusable
11991      */
11992     @RemotableViewMethod
setFocusable(@ocusable int focusable)11993     public void setFocusable(@Focusable int focusable) {
11994         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
11995             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
11996         }
11997         setFlags(focusable, FOCUSABLE_MASK);
11998     }
11999 
12000     /**
12001      * Set whether this view can receive focus while in touch mode.
12002      *
12003      * Setting this to true will also ensure that this view is focusable.
12004      *
12005      * @param focusableInTouchMode If true, this view can receive the focus while
12006      *   in touch mode.
12007      *
12008      * @see #setFocusable(boolean)
12009      * @attr ref android.R.styleable#View_focusableInTouchMode
12010      */
12011     @RemotableViewMethod
setFocusableInTouchMode(boolean focusableInTouchMode)12012     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
12013         // Focusable in touch mode should always be set before the focusable flag
12014         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
12015         // which, in touch mode, will not successfully request focus on this view
12016         // because the focusable in touch mode flag is not set
12017         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
12018 
12019         // Clear FOCUSABLE_AUTO if set.
12020         if (focusableInTouchMode) {
12021             // Clears FOCUSABLE_AUTO if set.
12022             setFlags(FOCUSABLE, FOCUSABLE_MASK);
12023         }
12024     }
12025 
12026     /**
12027      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
12028      * to autofill the view with the user's data.
12029      *
12030      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
12031      * For example, if the application accepts either an username or email address to identify
12032      * an user.
12033      *
12034      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
12035      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
12036      * constants such as:
12037      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
12038      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
12039      * {@link #AUTOFILL_HINT_NAME},
12040      * {@link #AUTOFILL_HINT_PHONE},
12041      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
12042      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
12043      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
12044      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
12045      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
12046      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
12047      *
12048      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
12049      * @attr ref android.R.styleable#View_autofillHints
12050      */
setAutofillHints(@ullable String... autofillHints)12051     public void setAutofillHints(@Nullable String... autofillHints) {
12052         if (autofillHints == null || autofillHints.length == 0) {
12053             mAutofillHints = null;
12054         } else {
12055             mAutofillHints = autofillHints;
12056         }
12057     }
12058 
12059     /**
12060      * @hide
12061      */
12062     @TestApi
setAutofilled(boolean isAutofilled, boolean hideHighlight)12063     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
12064         boolean wasChanged = isAutofilled != isAutofilled();
12065 
12066         if (wasChanged) {
12067             if (isAutofilled) {
12068                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
12069             } else {
12070                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
12071             }
12072 
12073             if (hideHighlight) {
12074                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
12075             } else {
12076                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
12077             }
12078 
12079             invalidate();
12080         }
12081     }
12082 
12083     /**
12084      * Set whether this view should have sound effects enabled for events such as
12085      * clicking and touching.
12086      *
12087      * <p>You may wish to disable sound effects for a view if you already play sounds,
12088      * for instance, a dial key that plays dtmf tones.
12089      *
12090      * @param soundEffectsEnabled whether sound effects are enabled for this view.
12091      * @see #isSoundEffectsEnabled()
12092      * @see #playSoundEffect(int)
12093      * @attr ref android.R.styleable#View_soundEffectsEnabled
12094      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)12095     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
12096         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
12097     }
12098 
12099     /**
12100      * @return whether this view should have sound effects enabled for events such as
12101      *     clicking and touching.
12102      *
12103      * @see #setSoundEffectsEnabled(boolean)
12104      * @see #playSoundEffect(int)
12105      * @attr ref android.R.styleable#View_soundEffectsEnabled
12106      */
12107     @ViewDebug.ExportedProperty
12108     @InspectableProperty
isSoundEffectsEnabled()12109     public boolean isSoundEffectsEnabled() {
12110         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
12111     }
12112 
12113     /**
12114      * Set whether this view should have haptic feedback for events such as
12115      * long presses.
12116      *
12117      * <p>You may wish to disable haptic feedback if your view already controls
12118      * its own haptic feedback.
12119      *
12120      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
12121      * @see #isHapticFeedbackEnabled()
12122      * @see #performHapticFeedback(int)
12123      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
12124      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)12125     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
12126         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
12127     }
12128 
12129     /**
12130      * @return whether this view should have haptic feedback enabled for events
12131      * long presses.
12132      *
12133      * @see #setHapticFeedbackEnabled(boolean)
12134      * @see #performHapticFeedback(int)
12135      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
12136      */
12137     @ViewDebug.ExportedProperty
12138     @InspectableProperty
isHapticFeedbackEnabled()12139     public boolean isHapticFeedbackEnabled() {
12140         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
12141     }
12142 
12143     /**
12144      * Returns the layout direction for this view.
12145      *
12146      * @return One of {@link #LAYOUT_DIRECTION_LTR},
12147      *   {@link #LAYOUT_DIRECTION_RTL},
12148      *   {@link #LAYOUT_DIRECTION_INHERIT} or
12149      *   {@link #LAYOUT_DIRECTION_LOCALE}.
12150      *
12151      * @attr ref android.R.styleable#View_layoutDirection
12152      *
12153      * @hide
12154      */
12155     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12156         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
12157         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
12158         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
12159         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
12160     })
12161     @InspectableProperty(hasAttributeId = false, enumMapping = {
12162             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12163             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
12164             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
12165             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
12166     })
12167     @LayoutDir
getRawLayoutDirection()12168     public int getRawLayoutDirection() {
12169         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
12170     }
12171 
12172     /**
12173      * Set the layout direction for this view. This will propagate a reset of layout direction
12174      * resolution to the view's children and resolve layout direction for this view.
12175      *
12176      * @param layoutDirection the layout direction to set. Should be one of:
12177      *
12178      * {@link #LAYOUT_DIRECTION_LTR},
12179      * {@link #LAYOUT_DIRECTION_RTL},
12180      * {@link #LAYOUT_DIRECTION_INHERIT},
12181      * {@link #LAYOUT_DIRECTION_LOCALE}.
12182      *
12183      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
12184      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
12185      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
12186      *
12187      * @attr ref android.R.styleable#View_layoutDirection
12188      */
12189     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)12190     public void setLayoutDirection(@LayoutDir int layoutDirection) {
12191         if (getRawLayoutDirection() != layoutDirection) {
12192             // Reset the current layout direction and the resolved one
12193             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
12194             resetRtlProperties();
12195             // Set the new layout direction (filtered)
12196             mPrivateFlags2 |=
12197                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
12198             // We need to resolve all RTL properties as they all depend on layout direction
12199             resolveRtlPropertiesIfNeeded();
12200             requestLayout();
12201             invalidate(true);
12202         }
12203     }
12204 
12205     /**
12206      * Returns the resolved layout direction for this view.
12207      *
12208      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
12209      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
12210      *
12211      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
12212      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
12213      *
12214      * @attr ref android.R.styleable#View_layoutDirection
12215      */
12216     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12217         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
12218         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
12219     })
12220     @InspectableProperty(enumMapping = {
12221             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12222             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
12223     })
12224     @ResolvedLayoutDir
getLayoutDirection()12225     public int getLayoutDirection() {
12226         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12227         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
12228             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12229             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
12230         }
12231         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
12232                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
12233     }
12234 
12235     /**
12236      * Indicates whether or not this view's layout is right-to-left. This is resolved from
12237      * layout attribute and/or the inherited value from the parent
12238      *
12239      * @return true if the layout is right-to-left.
12240      *
12241      * @hide
12242      */
12243     @ViewDebug.ExportedProperty(category = "layout")
12244     @UnsupportedAppUsage
isLayoutRtl()12245     public boolean isLayoutRtl() {
12246         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
12247     }
12248 
12249     /**
12250      * Indicates whether the view is currently tracking transient state that the
12251      * app should not need to concern itself with saving and restoring, but that
12252      * the framework should take special note to preserve when possible.
12253      *
12254      * <p>A view with transient state cannot be trivially rebound from an external
12255      * data source, such as an adapter binding item views in a list. This may be
12256      * because the view is performing an animation, tracking user selection
12257      * of content, or similar.</p>
12258      *
12259      * @return true if the view has transient state
12260      */
12261     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()12262     public boolean hasTransientState() {
12263         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
12264     }
12265 
12266     /**
12267      * Set whether this view is currently tracking transient state that the
12268      * framework should attempt to preserve when possible. This flag is reference counted,
12269      * so every call to setHasTransientState(true) should be paired with a later call
12270      * to setHasTransientState(false).
12271      *
12272      * <p>A view with transient state cannot be trivially rebound from an external
12273      * data source, such as an adapter binding item views in a list. This may be
12274      * because the view is performing an animation, tracking user selection
12275      * of content, or similar.</p>
12276      *
12277      * @param hasTransientState true if this view has transient state
12278      */
setHasTransientState(boolean hasTransientState)12279     public void setHasTransientState(boolean hasTransientState) {
12280         final boolean oldHasTransientState = hasTransientState();
12281         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
12282                 mTransientStateCount - 1;
12283         if (mTransientStateCount < 0) {
12284             mTransientStateCount = 0;
12285             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
12286                     "unmatched pair of setHasTransientState calls");
12287         } else if ((hasTransientState && mTransientStateCount == 1) ||
12288                 (!hasTransientState && mTransientStateCount == 0)) {
12289             // update flag if we've just incremented up from 0 or decremented down to 0
12290             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
12291                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
12292             final boolean newHasTransientState = hasTransientState();
12293             if (mParent != null && newHasTransientState != oldHasTransientState) {
12294                 try {
12295                     mParent.childHasTransientStateChanged(this, newHasTransientState);
12296                 } catch (AbstractMethodError e) {
12297                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12298                             " does not fully implement ViewParent", e);
12299                 }
12300             }
12301         }
12302     }
12303 
12304     /**
12305      * Set the view is tracking translation transient state. This flag is used to check if the view
12306      * need to call setHasTransientState(false) to reset transient state that set when starting
12307      * translation.
12308      *
12309      * @param hasTranslationTransientState true if this view has translation transient state
12310      * @hide
12311      */
setHasTranslationTransientState(boolean hasTranslationTransientState)12312     public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
12313         if (hasTranslationTransientState) {
12314             mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12315         } else {
12316             mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12317         }
12318     }
12319 
12320     /**
12321      * @hide
12322      */
hasTranslationTransientState()12323     public boolean hasTranslationTransientState() {
12324         return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
12325                 == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12326     }
12327 
12328     /**
12329      * Returns true if this view is currently attached to a window.
12330      */
isAttachedToWindow()12331     public boolean isAttachedToWindow() {
12332         return mAttachInfo != null;
12333     }
12334 
12335     /**
12336      * Returns true if this view has been through at least one layout since it
12337      * was last attached to or detached from a window.
12338      */
isLaidOut()12339     public boolean isLaidOut() {
12340         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
12341     }
12342 
12343     /**
12344      * @return {@code true} if laid-out and not about to do another layout.
12345      */
isLayoutValid()12346     boolean isLayoutValid() {
12347         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
12348     }
12349 
12350     /**
12351      * If this view doesn't do any drawing on its own, set this flag to
12352      * allow further optimizations. By default, this flag is not set on
12353      * View, but could be set on some View subclasses such as ViewGroup.
12354      *
12355      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
12356      * you should clear this flag.
12357      *
12358      * @param willNotDraw whether or not this View draw on its own
12359      */
setWillNotDraw(boolean willNotDraw)12360     public void setWillNotDraw(boolean willNotDraw) {
12361         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
12362     }
12363 
12364     /**
12365      * Returns whether or not this View draws on its own.
12366      *
12367      * @return true if this view has nothing to draw, false otherwise
12368      */
12369     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()12370     public boolean willNotDraw() {
12371         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
12372     }
12373 
12374     /**
12375      * When a View's drawing cache is enabled, drawing is redirected to an
12376      * offscreen bitmap. Some views, like an ImageView, must be able to
12377      * bypass this mechanism if they already draw a single bitmap, to avoid
12378      * unnecessary usage of the memory.
12379      *
12380      * @param willNotCacheDrawing true if this view does not cache its
12381      *        drawing, false otherwise
12382      *
12383      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12384      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12385      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12386      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12387      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12388      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12389      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12390      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12391      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12392      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12393      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12394      * reports or unit testing the {@link PixelCopy} API is recommended.
12395      */
12396     @Deprecated
setWillNotCacheDrawing(boolean willNotCacheDrawing)12397     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
12398         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
12399     }
12400 
12401     /**
12402      * Returns whether or not this View can cache its drawing or not.
12403      *
12404      * @return true if this view does not cache its drawing, false otherwise
12405      *
12406      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12407      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12408      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12409      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12410      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12411      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12412      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12413      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12414      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12415      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12416      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12417      * reports or unit testing the {@link PixelCopy} API is recommended.
12418      */
12419     @ViewDebug.ExportedProperty(category = "drawing")
12420     @Deprecated
willNotCacheDrawing()12421     public boolean willNotCacheDrawing() {
12422         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
12423     }
12424 
12425     /**
12426      * Indicates whether this view reacts to click events or not.
12427      *
12428      * @return true if the view is clickable, false otherwise
12429      *
12430      * @see #setClickable(boolean)
12431      * @attr ref android.R.styleable#View_clickable
12432      */
12433     @ViewDebug.ExportedProperty
12434     @InspectableProperty
isClickable()12435     public boolean isClickable() {
12436         return (mViewFlags & CLICKABLE) == CLICKABLE;
12437     }
12438 
12439     /**
12440      * Enables or disables click events for this view. When a view
12441      * is clickable it will change its state to "pressed" on every click.
12442      * Subclasses should set the view clickable to visually react to
12443      * user's clicks.
12444      *
12445      * @param clickable true to make the view clickable, false otherwise
12446      *
12447      * @see #isClickable()
12448      * @attr ref android.R.styleable#View_clickable
12449      */
setClickable(boolean clickable)12450     public void setClickable(boolean clickable) {
12451         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
12452     }
12453 
12454     /**
12455      * Enables or disables click events for this view when disabled.
12456      *
12457      * @param clickableWhenDisabled true to make the view clickable, false otherwise
12458      *
12459      * @attr ref android.R.styleable#View_allowClickWhenDisabled
12460      */
setAllowClickWhenDisabled(boolean clickableWhenDisabled)12461     public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
12462         if (clickableWhenDisabled) {
12463             mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
12464         } else {
12465             mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
12466         }
12467     }
12468 
12469     /**
12470      * Indicates whether this view reacts to long click events or not.
12471      *
12472      * @return true if the view is long clickable, false otherwise
12473      *
12474      * @see #setLongClickable(boolean)
12475      * @attr ref android.R.styleable#View_longClickable
12476      */
12477     @InspectableProperty
isLongClickable()12478     public boolean isLongClickable() {
12479         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12480     }
12481 
12482     /**
12483      * Enables or disables long click events for this view. When a view is long
12484      * clickable it reacts to the user holding down the button for a longer
12485      * duration than a tap. This event can either launch the listener or a
12486      * context menu.
12487      *
12488      * @param longClickable true to make the view long clickable, false otherwise
12489      * @see #isLongClickable()
12490      * @attr ref android.R.styleable#View_longClickable
12491      */
setLongClickable(boolean longClickable)12492     public void setLongClickable(boolean longClickable) {
12493         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
12494     }
12495 
12496     /**
12497      * Indicates whether this view reacts to context clicks or not.
12498      *
12499      * @return true if the view is context clickable, false otherwise
12500      * @see #setContextClickable(boolean)
12501      * @attr ref android.R.styleable#View_contextClickable
12502      */
12503     @InspectableProperty
isContextClickable()12504     public boolean isContextClickable() {
12505         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12506     }
12507 
12508     /**
12509      * Enables or disables context clicking for this view. This event can launch the listener.
12510      *
12511      * @param contextClickable true to make the view react to a context click, false otherwise
12512      * @see #isContextClickable()
12513      * @attr ref android.R.styleable#View_contextClickable
12514      */
setContextClickable(boolean contextClickable)12515     public void setContextClickable(boolean contextClickable) {
12516         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
12517     }
12518 
12519     /**
12520      * Sets the pressed state for this view and provides a touch coordinate for
12521      * animation hinting.
12522      *
12523      * @param pressed Pass true to set the View's internal state to "pressed",
12524      *            or false to reverts the View's internal state from a
12525      *            previously set "pressed" state.
12526      * @param x The x coordinate of the touch that caused the press
12527      * @param y The y coordinate of the touch that caused the press
12528      */
setPressed(boolean pressed, float x, float y)12529     private void setPressed(boolean pressed, float x, float y) {
12530         if (pressed) {
12531             drawableHotspotChanged(x, y);
12532         }
12533 
12534         setPressed(pressed);
12535     }
12536 
12537     /**
12538      * Sets the pressed state for this view.
12539      *
12540      * @see #isClickable()
12541      * @see #setClickable(boolean)
12542      *
12543      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
12544      *        the View's internal state from a previously set "pressed" state.
12545      */
setPressed(boolean pressed)12546     public void setPressed(boolean pressed) {
12547         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
12548 
12549         if (pressed) {
12550             mPrivateFlags |= PFLAG_PRESSED;
12551         } else {
12552             mPrivateFlags &= ~PFLAG_PRESSED;
12553         }
12554 
12555         if (needsRefresh) {
12556             refreshDrawableState();
12557         }
12558         dispatchSetPressed(pressed);
12559     }
12560 
12561     /**
12562      * Dispatch setPressed to all of this View's children.
12563      *
12564      * @see #setPressed(boolean)
12565      *
12566      * @param pressed The new pressed state
12567      */
dispatchSetPressed(boolean pressed)12568     protected void dispatchSetPressed(boolean pressed) {
12569     }
12570 
12571     /**
12572      * Indicates whether the view is currently in pressed state. Unless
12573      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
12574      * the pressed state.
12575      *
12576      * @see #setPressed(boolean)
12577      * @see #isClickable()
12578      * @see #setClickable(boolean)
12579      *
12580      * @return true if the view is currently pressed, false otherwise
12581      */
12582     @ViewDebug.ExportedProperty
12583     @InspectableProperty(hasAttributeId = false)
isPressed()12584     public boolean isPressed() {
12585         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
12586     }
12587 
12588     /**
12589      * @hide
12590      * Indicates whether this view will participate in data collection through
12591      * {@link ViewStructure}.  If true, it will not provide any data
12592      * for itself or its children.  If false, the normal data collection will be allowed.
12593      *
12594      * @return Returns false if assist data collection is not blocked, else true.
12595      *
12596      * @see #setAssistBlocked(boolean)
12597      * @attr ref android.R.styleable#View_assistBlocked
12598      */
isAssistBlocked()12599     public boolean isAssistBlocked() {
12600         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
12601     }
12602 
12603     /**
12604      * @hide
12605      * Controls whether assist data collection from this view and its children is enabled
12606      * (that is, whether {@link #onProvideStructure} and
12607      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
12608      * allowing normal assist collection.  Setting this to false will disable assist collection.
12609      *
12610      * @param enabled Set to true to <em>disable</em> assist data collection, or false
12611      * (the default) to allow it.
12612      *
12613      * @see #isAssistBlocked()
12614      * @see #onProvideStructure
12615      * @see #onProvideVirtualStructure
12616      * @attr ref android.R.styleable#View_assistBlocked
12617      */
12618     @UnsupportedAppUsage
setAssistBlocked(boolean enabled)12619     public void setAssistBlocked(boolean enabled) {
12620         if (enabled) {
12621             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
12622         } else {
12623             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
12624         }
12625     }
12626 
12627     /**
12628      * Indicates whether this view will save its state (that is,
12629      * whether its {@link #onSaveInstanceState} method will be called).
12630      *
12631      * @return Returns true if the view state saving is enabled, else false.
12632      *
12633      * @see #setSaveEnabled(boolean)
12634      * @attr ref android.R.styleable#View_saveEnabled
12635      */
12636     @InspectableProperty
isSaveEnabled()12637     public boolean isSaveEnabled() {
12638         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
12639     }
12640 
12641     /**
12642      * Controls whether the saving of this view's state is
12643      * enabled (that is, whether its {@link #onSaveInstanceState} method
12644      * will be called).  Note that even if freezing is enabled, the
12645      * view still must have an id assigned to it (via {@link #setId(int)})
12646      * for its state to be saved.  This flag can only disable the
12647      * saving of this view; any child views may still have their state saved.
12648      *
12649      * @param enabled Set to false to <em>disable</em> state saving, or true
12650      * (the default) to allow it.
12651      *
12652      * @see #isSaveEnabled()
12653      * @see #setId(int)
12654      * @see #onSaveInstanceState()
12655      * @attr ref android.R.styleable#View_saveEnabled
12656      */
setSaveEnabled(boolean enabled)12657     public void setSaveEnabled(boolean enabled) {
12658         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
12659     }
12660 
12661     /**
12662      * Gets whether the framework should discard touches when the view's
12663      * window is obscured by another visible window.
12664      * Refer to the {@link View} security documentation for more details.
12665      *
12666      * @return True if touch filtering is enabled.
12667      *
12668      * @see #setFilterTouchesWhenObscured(boolean)
12669      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12670      */
12671     @ViewDebug.ExportedProperty
12672     @InspectableProperty
getFilterTouchesWhenObscured()12673     public boolean getFilterTouchesWhenObscured() {
12674         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
12675     }
12676 
12677     /**
12678      * Sets whether the framework should discard touches when the view's
12679      * window is obscured by another visible window.
12680      * Refer to the {@link View} security documentation for more details.
12681      *
12682      * @param enabled True if touch filtering should be enabled.
12683      *
12684      * @see #getFilterTouchesWhenObscured
12685      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12686      */
setFilterTouchesWhenObscured(boolean enabled)12687     public void setFilterTouchesWhenObscured(boolean enabled) {
12688         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
12689                 FILTER_TOUCHES_WHEN_OBSCURED);
12690     }
12691 
12692     /**
12693      * Indicates whether the entire hierarchy under this view will save its
12694      * state when a state saving traversal occurs from its parent.  The default
12695      * is true; if false, these views will not be saved unless
12696      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12697      *
12698      * @return Returns true if the view state saving from parent is enabled, else false.
12699      *
12700      * @see #setSaveFromParentEnabled(boolean)
12701      */
isSaveFromParentEnabled()12702     public boolean isSaveFromParentEnabled() {
12703         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
12704     }
12705 
12706     /**
12707      * Controls whether the entire hierarchy under this view will save its
12708      * state when a state saving traversal occurs from its parent.  The default
12709      * is true; if false, these views will not be saved unless
12710      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12711      *
12712      * @param enabled Set to false to <em>disable</em> state saving, or true
12713      * (the default) to allow it.
12714      *
12715      * @see #isSaveFromParentEnabled()
12716      * @see #setId(int)
12717      * @see #onSaveInstanceState()
12718      */
setSaveFromParentEnabled(boolean enabled)12719     public void setSaveFromParentEnabled(boolean enabled) {
12720         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
12721     }
12722 
12723 
12724     /**
12725      * Returns whether this View is currently able to take focus.
12726      *
12727      * @return True if this view can take focus, or false otherwise.
12728      */
12729     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()12730     public final boolean isFocusable() {
12731         return FOCUSABLE == (mViewFlags & FOCUSABLE);
12732     }
12733 
12734     /**
12735      * Returns the focusable setting for this view.
12736      *
12737      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
12738      * @attr ref android.R.styleable#View_focusable
12739      */
12740     @ViewDebug.ExportedProperty(mapping = {
12741             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
12742             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
12743             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
12744             }, category = "focus")
12745     @InspectableProperty(enumMapping = {
12746             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
12747             @EnumEntry(value = FOCUSABLE, name = "true"),
12748             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
12749     })
12750     @Focusable
getFocusable()12751     public int getFocusable() {
12752         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
12753     }
12754 
12755     /**
12756      * When a view is focusable, it may not want to take focus when in touch mode.
12757      * For example, a button would like focus when the user is navigating via a D-pad
12758      * so that the user can click on it, but once the user starts touching the screen,
12759      * the button shouldn't take focus
12760      * @return Whether the view is focusable in touch mode.
12761      * @attr ref android.R.styleable#View_focusableInTouchMode
12762      */
12763     @ViewDebug.ExportedProperty(category = "focus")
12764     @InspectableProperty
isFocusableInTouchMode()12765     public final boolean isFocusableInTouchMode() {
12766         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
12767     }
12768 
12769     /**
12770      * Returns whether the view should be treated as a focusable unit by screen reader
12771      * accessibility tools.
12772      * @see #setScreenReaderFocusable(boolean)
12773      *
12774      * @return Whether the view should be treated as a focusable unit by screen reader.
12775      *
12776      * @attr ref android.R.styleable#View_screenReaderFocusable
12777      */
12778     @InspectableProperty
isScreenReaderFocusable()12779     public boolean isScreenReaderFocusable() {
12780         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
12781     }
12782 
12783     /**
12784      * Sets whether this View should be a focusable element for screen readers
12785      * and include non-focusable Views from its subtree when providing feedback.
12786      * <p>
12787      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
12788      * but does not impact input focus behavior.
12789      *
12790      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
12791      *                              accessibility tools.
12792      *
12793      * @attr ref android.R.styleable#View_screenReaderFocusable
12794      */
setScreenReaderFocusable(boolean screenReaderFocusable)12795     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
12796         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
12797     }
12798 
12799     /**
12800      * Gets whether this view is a heading for accessibility purposes.
12801      *
12802      * @return {@code true} if the view is a heading, {@code false} otherwise.
12803      *
12804      * @attr ref android.R.styleable#View_accessibilityHeading
12805      */
12806     @InspectableProperty
isAccessibilityHeading()12807     public boolean isAccessibilityHeading() {
12808         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
12809     }
12810 
12811     /**
12812      * Set if view is a heading for a section of content for accessibility purposes.
12813      *
12814      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
12815      *
12816      * @attr ref android.R.styleable#View_accessibilityHeading
12817      */
setAccessibilityHeading(boolean isHeading)12818     public void setAccessibilityHeading(boolean isHeading) {
12819         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
12820     }
12821 
updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue)12822     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
12823         int pflags3 = mPrivateFlags3;
12824         if (newValue) {
12825             pflags3 |= mask;
12826         } else {
12827             pflags3 &= ~mask;
12828         }
12829 
12830         if (pflags3 != mPrivateFlags3) {
12831             mPrivateFlags3 = pflags3;
12832             notifyViewAccessibilityStateChangedIfNeeded(
12833                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12834         }
12835     }
12836 
12837     /**
12838      * Find the nearest view in the specified direction that can take focus.
12839      * This does not actually give focus to that view.
12840      *
12841      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12842      *
12843      * @return The nearest focusable in the specified direction, or null if none
12844      *         can be found.
12845      */
focusSearch(@ocusRealDirection int direction)12846     public View focusSearch(@FocusRealDirection int direction) {
12847         if (mParent != null) {
12848             return mParent.focusSearch(this, direction);
12849         } else {
12850             return null;
12851         }
12852     }
12853 
12854     /**
12855      * Returns whether this View is a root of a keyboard navigation cluster.
12856      *
12857      * @return True if this view is a root of a cluster, or false otherwise.
12858      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12859      */
12860     @ViewDebug.ExportedProperty(category = "focus")
12861     @InspectableProperty
isKeyboardNavigationCluster()12862     public final boolean isKeyboardNavigationCluster() {
12863         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
12864     }
12865 
12866     /**
12867      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
12868      * will be ignored.
12869      *
12870      * @return the keyboard navigation cluster that this view is in (can be this view)
12871      *         or {@code null} if not in one
12872      */
findKeyboardNavigationCluster()12873     View findKeyboardNavigationCluster() {
12874         if (mParent instanceof View) {
12875             View cluster = ((View) mParent).findKeyboardNavigationCluster();
12876             if (cluster != null) {
12877                 return cluster;
12878             } else if (isKeyboardNavigationCluster()) {
12879                 return this;
12880             }
12881         }
12882         return null;
12883     }
12884 
12885     /**
12886      * Set whether this view is a root of a keyboard navigation cluster.
12887      *
12888      * @param isCluster If true, this view is a root of a cluster.
12889      *
12890      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12891      */
setKeyboardNavigationCluster(boolean isCluster)12892     public void setKeyboardNavigationCluster(boolean isCluster) {
12893         if (isCluster) {
12894             mPrivateFlags3 |= PFLAG3_CLUSTER;
12895         } else {
12896             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
12897         }
12898     }
12899 
12900     /**
12901      * Sets this View as the one which receives focus the next time cluster navigation jumps
12902      * to the cluster containing this View. This does NOT change focus even if the cluster
12903      * containing this view is current.
12904      *
12905      * @hide
12906      */
12907     @TestApi
setFocusedInCluster()12908     public final void setFocusedInCluster() {
12909         setFocusedInCluster(findKeyboardNavigationCluster());
12910     }
12911 
setFocusedInCluster(View cluster)12912     private void setFocusedInCluster(View cluster) {
12913         if (this instanceof ViewGroup) {
12914             ((ViewGroup) this).mFocusedInCluster = null;
12915         }
12916         if (cluster == this) {
12917             return;
12918         }
12919         ViewParent parent = mParent;
12920         View child = this;
12921         while (parent instanceof ViewGroup) {
12922             ((ViewGroup) parent).mFocusedInCluster = child;
12923             if (parent == cluster) {
12924                 break;
12925             }
12926             child = (View) parent;
12927             parent = parent.getParent();
12928         }
12929     }
12930 
updateFocusedInCluster(View oldFocus, @FocusDirection int direction)12931     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
12932         if (oldFocus != null) {
12933             View oldCluster = oldFocus.findKeyboardNavigationCluster();
12934             View cluster = findKeyboardNavigationCluster();
12935             if (oldCluster != cluster) {
12936                 // Going from one cluster to another, so save last-focused.
12937                 // This covers cluster jumps because they are always FOCUS_DOWN
12938                 oldFocus.setFocusedInCluster(oldCluster);
12939                 if (!(oldFocus.mParent instanceof ViewGroup)) {
12940                     return;
12941                 }
12942                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
12943                     // This is a result of ordered navigation so consider navigation through
12944                     // the previous cluster "complete" and clear its last-focused memory.
12945                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12946                 } else if (oldFocus instanceof ViewGroup
12947                         && ((ViewGroup) oldFocus).getDescendantFocusability()
12948                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
12949                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
12950                     // This means oldFocus is not focusable since it obviously has a focusable
12951                     // child (this). Don't restore focus to it in the future.
12952                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12953                 }
12954             }
12955         }
12956     }
12957 
12958     /**
12959      * Returns whether this View should receive focus when the focus is restored for the view
12960      * hierarchy containing this view.
12961      * <p>
12962      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12963      * window or serves as a target of cluster navigation.
12964      *
12965      * @see #restoreDefaultFocus()
12966      *
12967      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
12968      * @attr ref android.R.styleable#View_focusedByDefault
12969      */
12970     @ViewDebug.ExportedProperty(category = "focus")
12971     @InspectableProperty
isFocusedByDefault()12972     public final boolean isFocusedByDefault() {
12973         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
12974     }
12975 
12976     /**
12977      * Sets whether this View should receive focus when the focus is restored for the view
12978      * hierarchy containing this view.
12979      * <p>
12980      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12981      * window or serves as a target of cluster navigation.
12982      *
12983      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
12984      *                           {@code false} otherwise.
12985      *
12986      * @see #restoreDefaultFocus()
12987      *
12988      * @attr ref android.R.styleable#View_focusedByDefault
12989      */
12990     @RemotableViewMethod
setFocusedByDefault(boolean isFocusedByDefault)12991     public void setFocusedByDefault(boolean isFocusedByDefault) {
12992         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
12993             return;
12994         }
12995 
12996         if (isFocusedByDefault) {
12997             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
12998         } else {
12999             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
13000         }
13001 
13002         if (mParent instanceof ViewGroup) {
13003             if (isFocusedByDefault) {
13004                 ((ViewGroup) mParent).setDefaultFocus(this);
13005             } else {
13006                 ((ViewGroup) mParent).clearDefaultFocus(this);
13007             }
13008         }
13009     }
13010 
13011     /**
13012      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
13013      *
13014      * @return {@code true} if this view has default focus, {@code false} otherwise
13015      */
hasDefaultFocus()13016     boolean hasDefaultFocus() {
13017         return isFocusedByDefault();
13018     }
13019 
13020     /**
13021      * Find the nearest keyboard navigation cluster in the specified direction.
13022      * This does not actually give focus to that cluster.
13023      *
13024      * @param currentCluster The starting point of the search. Null means the current cluster is not
13025      *                       found yet
13026      * @param direction Direction to look
13027      *
13028      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
13029      *         can be found
13030      */
keyboardNavigationClusterSearch(View currentCluster, @FocusDirection int direction)13031     public View keyboardNavigationClusterSearch(View currentCluster,
13032             @FocusDirection int direction) {
13033         if (isKeyboardNavigationCluster()) {
13034             currentCluster = this;
13035         }
13036         if (isRootNamespace()) {
13037             // Root namespace means we should consider ourselves the top of the
13038             // tree for group searching; otherwise we could be group searching
13039             // into other tabs.  see LocalActivityManager and TabHost for more info.
13040             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
13041                     this, currentCluster, direction);
13042         } else if (mParent != null) {
13043             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
13044         }
13045         return null;
13046     }
13047 
13048     /**
13049      * This method is the last chance for the focused view and its ancestors to
13050      * respond to an arrow key. This is called when the focused view did not
13051      * consume the key internally, nor could the view system find a new view in
13052      * the requested direction to give focus to.
13053      *
13054      * @param focused The currently focused view.
13055      * @param direction The direction focus wants to move. One of FOCUS_UP,
13056      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
13057      * @return True if the this view consumed this unhandled move.
13058      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)13059     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
13060         return false;
13061     }
13062 
13063     /**
13064      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
13065      * have {@link android.R.attr#state_focused} defined in its background.
13066      *
13067      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
13068      *                                      highlight, {@code false} otherwise.
13069      *
13070      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
13071      */
setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled)13072     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
13073         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
13074     }
13075 
13076     /**
13077 
13078     /**
13079      * Returns whether this View should use a default focus highlight when it gets focused but
13080      * doesn't have {@link android.R.attr#state_focused} defined in its background.
13081      *
13082      * @return True if this View should use a default focus highlight.
13083      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
13084      */
13085     @ViewDebug.ExportedProperty(category = "focus")
13086     @InspectableProperty
getDefaultFocusHighlightEnabled()13087     public final boolean getDefaultFocusHighlightEnabled() {
13088         return mDefaultFocusHighlightEnabled;
13089     }
13090 
13091     /**
13092      * If a user manually specified the next view id for a particular direction,
13093      * use the root to look up the view.
13094      * @param root The root view of the hierarchy containing this view.
13095      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
13096      * or FOCUS_BACKWARD.
13097      * @return The user specified next view, or null if there is none.
13098      */
findUserSetNextFocus(View root, @FocusDirection int direction)13099     View findUserSetNextFocus(View root, @FocusDirection int direction) {
13100         switch (direction) {
13101             case FOCUS_LEFT:
13102                 if (mNextFocusLeftId == View.NO_ID) return null;
13103                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
13104             case FOCUS_RIGHT:
13105                 if (mNextFocusRightId == View.NO_ID) return null;
13106                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
13107             case FOCUS_UP:
13108                 if (mNextFocusUpId == View.NO_ID) return null;
13109                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
13110             case FOCUS_DOWN:
13111                 if (mNextFocusDownId == View.NO_ID) return null;
13112                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
13113             case FOCUS_FORWARD:
13114                 if (mNextFocusForwardId == View.NO_ID) return null;
13115                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
13116             case FOCUS_BACKWARD: {
13117                 if (mID == View.NO_ID) return null;
13118                 final View rootView = root;
13119                 final View startView = this;
13120                 // Since we have forward links but no backward links, we need to find the view that
13121                 // forward links to this view. We can't just find the view with the specified ID
13122                 // because view IDs need not be unique throughout the tree.
13123                 return root.findViewByPredicateInsideOut(startView,
13124                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
13125                             == startView);
13126             }
13127         }
13128         return null;
13129     }
13130 
13131     /**
13132      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
13133      * use the root to look up the view.
13134      *
13135      * @param root the root view of the hierarchy containing this view
13136      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
13137      * @return the user-specified next cluster, or {@code null} if there is none
13138      */
findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction)13139     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
13140         switch (direction) {
13141             case FOCUS_FORWARD:
13142                 if (mNextClusterForwardId == View.NO_ID) return null;
13143                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
13144             case FOCUS_BACKWARD: {
13145                 if (mID == View.NO_ID) return null;
13146                 final int id = mID;
13147                 return root.findViewByPredicateInsideOut(this,
13148                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
13149             }
13150         }
13151         return null;
13152     }
13153 
findViewInsideOutShouldExist(View root, int id)13154     private View findViewInsideOutShouldExist(View root, int id) {
13155         return findViewInsideOutShouldExist(root, this, id);
13156     }
13157 
findViewInsideOutShouldExist(View root, View start, int id)13158     private View findViewInsideOutShouldExist(View root, View start, int id) {
13159         if (mMatchIdPredicate == null) {
13160             mMatchIdPredicate = new MatchIdPredicate();
13161         }
13162         mMatchIdPredicate.mId = id;
13163         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
13164         if (result == null) {
13165             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
13166         }
13167         return result;
13168     }
13169 
13170     /**
13171      * Find and return all focusable views that are descendants of this view,
13172      * possibly including this view if it is focusable itself.
13173      *
13174      * @param direction The direction of the focus
13175      * @return A list of focusable views
13176      */
getFocusables(@ocusDirection int direction)13177     public ArrayList<View> getFocusables(@FocusDirection int direction) {
13178         ArrayList<View> result = new ArrayList<View>(24);
13179         addFocusables(result, direction);
13180         return result;
13181     }
13182 
13183     /**
13184      * Add any focusable views that are descendants of this view (possibly
13185      * including this view if it is focusable itself) to views.  If we are in touch mode,
13186      * only add views that are also focusable in touch mode.
13187      *
13188      * @param views Focusable views found so far
13189      * @param direction The direction of the focus
13190      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)13191     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
13192         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
13193     }
13194 
13195     /**
13196      * Adds any focusable views that are descendants of this view (possibly
13197      * including this view if it is focusable itself) to views. This method
13198      * adds all focusable views regardless if we are in touch mode or
13199      * only views focusable in touch mode if we are in touch mode or
13200      * only views that can take accessibility focus if accessibility is enabled
13201      * depending on the focusable mode parameter.
13202      *
13203      * @param views Focusable views found so far or null if all we are interested is
13204      *        the number of focusables.
13205      * @param direction The direction of the focus.
13206      * @param focusableMode The type of focusables to be added.
13207      *
13208      * @see #FOCUSABLES_ALL
13209      * @see #FOCUSABLES_TOUCH_MODE
13210      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)13211     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
13212             @FocusableMode int focusableMode) {
13213         if (views == null) {
13214             return;
13215         }
13216         if (!canTakeFocus()) {
13217             return;
13218         }
13219         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
13220                 && !isFocusableInTouchMode()) {
13221             return;
13222         }
13223         views.add(this);
13224     }
13225 
13226     /**
13227      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
13228      * including this view if it is a cluster root itself) to views.
13229      *
13230      * @param views Keyboard navigation cluster roots found so far
13231      * @param direction Direction to look
13232      */
addKeyboardNavigationClusters( @onNull Collection<View> views, int direction)13233     public void addKeyboardNavigationClusters(
13234             @NonNull Collection<View> views,
13235             int direction) {
13236         if (!isKeyboardNavigationCluster()) {
13237             return;
13238         }
13239         if (!hasFocusable()) {
13240             return;
13241         }
13242         views.add(this);
13243     }
13244 
13245     /**
13246      * Finds the Views that contain given text. The containment is case insensitive.
13247      * The search is performed by either the text that the View renders or the content
13248      * description that describes the view for accessibility purposes and the view does
13249      * not render or both. Clients can specify how the search is to be performed via
13250      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
13251      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
13252      *
13253      * @param outViews The output list of matching Views.
13254      * @param searched The text to match against.
13255      *
13256      * @see #FIND_VIEWS_WITH_TEXT
13257      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
13258      * @see #setContentDescription(CharSequence)
13259      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)13260     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
13261             @FindViewFlags int flags) {
13262         if (getAccessibilityNodeProvider() != null) {
13263             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
13264                 outViews.add(this);
13265             }
13266         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
13267                 && (searched != null && searched.length() > 0)
13268                 && (mContentDescription != null && mContentDescription.length() > 0)) {
13269             String searchedLowerCase = searched.toString().toLowerCase();
13270             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
13271             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
13272                 outViews.add(this);
13273             }
13274         }
13275     }
13276 
13277     /**
13278      * Find and return all touchable views that are descendants of this view,
13279      * possibly including this view if it is touchable itself.
13280      *
13281      * @return A list of touchable views
13282      */
getTouchables()13283     public ArrayList<View> getTouchables() {
13284         ArrayList<View> result = new ArrayList<View>();
13285         addTouchables(result);
13286         return result;
13287     }
13288 
13289     /**
13290      * Add any touchable views that are descendants of this view (possibly
13291      * including this view if it is touchable itself) to views.
13292      *
13293      * @param views Touchable views found so far
13294      */
addTouchables(ArrayList<View> views)13295     public void addTouchables(ArrayList<View> views) {
13296         final int viewFlags = mViewFlags;
13297 
13298         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
13299                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
13300                 && (viewFlags & ENABLED_MASK) == ENABLED) {
13301             views.add(this);
13302         }
13303     }
13304 
13305     /**
13306      * Returns whether this View is accessibility focused.
13307      *
13308      * @return True if this View is accessibility focused.
13309      */
13310     @InspectableProperty(hasAttributeId = false)
isAccessibilityFocused()13311     public boolean isAccessibilityFocused() {
13312         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
13313     }
13314 
13315     /**
13316      * Call this to try to give accessibility focus to this view.
13317      *
13318      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
13319      * returns false or the view is no visible or the view already has accessibility
13320      * focus.
13321      *
13322      * See also {@link #focusSearch(int)}, which is what you call to say that you
13323      * have focus, and you want your parent to look for the next one.
13324      *
13325      * @return Whether this view actually took accessibility focus.
13326      *
13327      * @hide
13328      */
13329     @UnsupportedAppUsage
requestAccessibilityFocus()13330     public boolean requestAccessibilityFocus() {
13331         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
13332         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
13333             return false;
13334         }
13335         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
13336             return false;
13337         }
13338         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
13339             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
13340             ViewRootImpl viewRootImpl = getViewRootImpl();
13341             if (viewRootImpl != null) {
13342                 viewRootImpl.setAccessibilityFocus(this, null);
13343             }
13344             invalidate();
13345             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
13346             return true;
13347         }
13348         return false;
13349     }
13350 
13351     /**
13352      * Call this to try to clear accessibility focus of this view.
13353      *
13354      * See also {@link #focusSearch(int)}, which is what you call to say that you
13355      * have focus, and you want your parent to look for the next one.
13356      *
13357      * @hide
13358      */
13359     @UnsupportedAppUsage
clearAccessibilityFocus()13360     public void clearAccessibilityFocus() {
13361         clearAccessibilityFocusNoCallbacks(0);
13362 
13363         // Clear the global reference of accessibility focus if this view or
13364         // any of its descendants had accessibility focus. This will NOT send
13365         // an event or update internal state if focus is cleared from a
13366         // descendant view, which may leave views in inconsistent states.
13367         final ViewRootImpl viewRootImpl = getViewRootImpl();
13368         if (viewRootImpl != null) {
13369             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
13370             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13371                 viewRootImpl.setAccessibilityFocus(null, null);
13372             }
13373         }
13374     }
13375 
sendAccessibilityHoverEvent(int eventType)13376     private void sendAccessibilityHoverEvent(int eventType) {
13377         // Since we are not delivering to a client accessibility events from not
13378         // important views (unless the clinet request that) we need to fire the
13379         // event from the deepest view exposed to the client. As a consequence if
13380         // the user crosses a not exposed view the client will see enter and exit
13381         // of the exposed predecessor followed by and enter and exit of that same
13382         // predecessor when entering and exiting the not exposed descendant. This
13383         // is fine since the client has a clear idea which view is hovered at the
13384         // price of a couple more events being sent. This is a simple and
13385         // working solution.
13386         View source = this;
13387         while (true) {
13388             if (source.includeForAccessibility()) {
13389                 source.sendAccessibilityEvent(eventType);
13390                 return;
13391             }
13392             ViewParent parent = source.getParent();
13393             if (parent instanceof View) {
13394                 source = (View) parent;
13395             } else {
13396                 return;
13397             }
13398         }
13399     }
13400 
13401     /**
13402      * Clears accessibility focus without calling any callback methods
13403      * normally invoked in {@link #clearAccessibilityFocus()}. This method
13404      * is used separately from that one for clearing accessibility focus when
13405      * giving this focus to another view.
13406      *
13407      * @param action The action, if any, that led to focus being cleared. Set to
13408      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
13409      * the window.
13410      */
clearAccessibilityFocusNoCallbacks(int action)13411     void clearAccessibilityFocusNoCallbacks(int action) {
13412         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
13413             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
13414             invalidate();
13415             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13416                 AccessibilityEvent event = AccessibilityEvent.obtain(
13417                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
13418                 event.setAction(action);
13419                 if (mAccessibilityDelegate != null) {
13420                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
13421                 } else {
13422                     sendAccessibilityEventUnchecked(event);
13423                 }
13424             }
13425         }
13426     }
13427 
13428     /**
13429      * Call this to try to give focus to a specific view or to one of its
13430      * descendants.
13431      *
13432      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13433      * false), or if it can't be focused due to other conditions (not focusable in touch mode
13434      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
13435      * enabled, or has no size).
13436      *
13437      * See also {@link #focusSearch(int)}, which is what you call to say that you
13438      * have focus, and you want your parent to look for the next one.
13439      *
13440      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
13441      * {@link #FOCUS_DOWN} and <code>null</code>.
13442      *
13443      * @return Whether this view or one of its descendants actually took focus.
13444      */
requestFocus()13445     public final boolean requestFocus() {
13446         return requestFocus(View.FOCUS_DOWN);
13447     }
13448 
13449     /**
13450      * This will request focus for whichever View was last focused within this
13451      * cluster before a focus-jump out of it.
13452      *
13453      * @hide
13454      */
13455     @TestApi
restoreFocusInCluster(@ocusRealDirection int direction)13456     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
13457         // Prioritize focusableByDefault over algorithmic focus selection.
13458         if (restoreDefaultFocus()) {
13459             return true;
13460         }
13461         return requestFocus(direction);
13462     }
13463 
13464     /**
13465      * This will request focus for whichever View not in a cluster was last focused before a
13466      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
13467      * the "first" focusable view it finds.
13468      *
13469      * @hide
13470      */
13471     @TestApi
restoreFocusNotInCluster()13472     public boolean restoreFocusNotInCluster() {
13473         return requestFocus(View.FOCUS_DOWN);
13474     }
13475 
13476     /**
13477      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
13478      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
13479      *
13480      * @return Whether this view or one of its descendants actually took focus
13481      */
restoreDefaultFocus()13482     public boolean restoreDefaultFocus() {
13483         return requestFocus(View.FOCUS_DOWN);
13484     }
13485 
13486     /**
13487      * Call this to try to give focus to a specific view or to one of its
13488      * descendants and give it a hint about what direction focus is heading.
13489      *
13490      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13491      * false), or if it is focusable and it is not focusable in touch mode
13492      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13493      *
13494      * See also {@link #focusSearch(int)}, which is what you call to say that you
13495      * have focus, and you want your parent to look for the next one.
13496      *
13497      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
13498      * <code>null</code> set for the previously focused rectangle.
13499      *
13500      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13501      * @return Whether this view or one of its descendants actually took focus.
13502      */
requestFocus(int direction)13503     public final boolean requestFocus(int direction) {
13504         return requestFocus(direction, null);
13505     }
13506 
13507     /**
13508      * Call this to try to give focus to a specific view or to one of its descendants
13509      * and give it hints about the direction and a specific rectangle that the focus
13510      * is coming from.  The rectangle can help give larger views a finer grained hint
13511      * about where focus is coming from, and therefore, where to show selection, or
13512      * forward focus change internally.
13513      *
13514      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13515      * false), or if it is focusable and it is not focusable in touch mode
13516      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13517      *
13518      * A View will not take focus if it is not visible.
13519      *
13520      * A View will not take focus if one of its parents has
13521      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
13522      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
13523      *
13524      * See also {@link #focusSearch(int)}, which is what you call to say that you
13525      * have focus, and you want your parent to look for the next one.
13526      *
13527      * You may wish to override this method if your custom {@link View} has an internal
13528      * {@link View} that it wishes to forward the request to.
13529      *
13530      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13531      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
13532      *        to give a finer grained hint about where focus is coming from.  May be null
13533      *        if there is no hint.
13534      * @return Whether this view or one of its descendants actually took focus.
13535      */
requestFocus(int direction, Rect previouslyFocusedRect)13536     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
13537         return requestFocusNoSearch(direction, previouslyFocusedRect);
13538     }
13539 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)13540     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
13541         // need to be focusable
13542         if (!canTakeFocus()) {
13543             return false;
13544         }
13545 
13546         // need to be focusable in touch mode if in touch mode
13547         if (isInTouchMode() &&
13548             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
13549                return false;
13550         }
13551 
13552         // need to not have any parents blocking us
13553         if (hasAncestorThatBlocksDescendantFocus()) {
13554             return false;
13555         }
13556 
13557         if (!isLayoutValid()) {
13558             mPrivateFlags |= PFLAG_WANTS_FOCUS;
13559         } else {
13560             clearParentsWantFocus();
13561         }
13562 
13563         handleFocusGainInternal(direction, previouslyFocusedRect);
13564         return true;
13565     }
13566 
clearParentsWantFocus()13567     void clearParentsWantFocus() {
13568         if (mParent instanceof View) {
13569             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
13570             ((View) mParent).clearParentsWantFocus();
13571         }
13572     }
13573 
13574     /**
13575      * Call this to try to give focus to a specific view or to one of its descendants. This is a
13576      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
13577      * touch mode to request focus when they are touched.
13578      *
13579      * @return Whether this view or one of its descendants actually took focus.
13580      *
13581      * @see #isInTouchMode()
13582      *
13583      */
requestFocusFromTouch()13584     public final boolean requestFocusFromTouch() {
13585         // Leave touch mode if we need to
13586         if (isInTouchMode()) {
13587             ViewRootImpl viewRoot = getViewRootImpl();
13588             if (viewRoot != null) {
13589                 viewRoot.ensureTouchMode(false);
13590             }
13591         }
13592         return requestFocus(View.FOCUS_DOWN);
13593     }
13594 
13595     /**
13596      * @return Whether any ancestor of this view blocks descendant focus.
13597      */
hasAncestorThatBlocksDescendantFocus()13598     private boolean hasAncestorThatBlocksDescendantFocus() {
13599         final boolean focusableInTouchMode = isFocusableInTouchMode();
13600         ViewParent ancestor = mParent;
13601         while (ancestor instanceof ViewGroup) {
13602             final ViewGroup vgAncestor = (ViewGroup) ancestor;
13603             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
13604                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
13605                 return true;
13606             } else {
13607                 ancestor = vgAncestor.getParent();
13608             }
13609         }
13610         return false;
13611     }
13612 
13613     /**
13614      * Gets the mode for determining whether this View is important for accessibility.
13615      * A view is important for accessibility if it fires accessibility events and if it
13616      * is reported to accessibility services that query the screen.
13617      *
13618      * @return The mode for determining whether a view is important for accessibility, one
13619      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
13620      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
13621      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
13622      *
13623      * @attr ref android.R.styleable#View_importantForAccessibility
13624      *
13625      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13626      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13627      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13628      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13629      */
13630     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
13631             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
13632             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
13633             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
13634             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13635                     to = "noHideDescendants")
13636         })
13637     @InspectableProperty(enumMapping = {
13638             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
13639             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
13640             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
13641             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13642                     name = "noHideDescendants"),
13643     })
getImportantForAccessibility()13644     public int getImportantForAccessibility() {
13645         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
13646                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
13647     }
13648 
13649     /**
13650      * Sets the live region mode for this view. This indicates to accessibility
13651      * services whether they should automatically notify the user about changes
13652      * to the view's content description or text, or to the content descriptions
13653      * or text of the view's children (where applicable).
13654      * <p>
13655      * For example, in a login screen with a TextView that displays an "incorrect
13656      * password" notification, that view should be marked as a live region with
13657      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13658      * <p>
13659      * To disable change notifications for this view, use
13660      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
13661      * mode for most views.
13662      * <p>
13663      * To indicate that the user should be notified of changes, use
13664      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13665      * <p>
13666      * If the view's changes should interrupt ongoing speech and notify the user
13667      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
13668      *
13669      * @param mode The live region mode for this view, one of:
13670      *        <ul>
13671      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
13672      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
13673      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
13674      *        </ul>
13675      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13676      */
setAccessibilityLiveRegion(int mode)13677     public void setAccessibilityLiveRegion(int mode) {
13678         if (mode != getAccessibilityLiveRegion()) {
13679             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13680             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
13681                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13682             notifyViewAccessibilityStateChangedIfNeeded(
13683                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13684         }
13685     }
13686 
13687     /**
13688      * Gets the live region mode for this View.
13689      *
13690      * @return The live region mode for the view.
13691      *
13692      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13693      *
13694      * @see #setAccessibilityLiveRegion(int)
13695      */
13696     @InspectableProperty(enumMapping = {
13697             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
13698             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
13699             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
13700     })
getAccessibilityLiveRegion()13701     public int getAccessibilityLiveRegion() {
13702         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
13703                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
13704     }
13705 
13706     /**
13707      * Sets how to determine whether this view is important for accessibility
13708      * which is if it fires accessibility events and if it is reported to
13709      * accessibility services that query the screen.
13710      *
13711      * @param mode How to determine whether this view is important for accessibility.
13712      *
13713      * @attr ref android.R.styleable#View_importantForAccessibility
13714      *
13715      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13716      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13717      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13718      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13719      */
setImportantForAccessibility(int mode)13720     public void setImportantForAccessibility(int mode) {
13721         final int oldMode = getImportantForAccessibility();
13722         if (mode != oldMode) {
13723             final boolean hideDescendants =
13724                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
13725 
13726             // If this node or its descendants are no longer important, try to
13727             // clear accessibility focus.
13728             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
13729                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
13730                 if (focusHost != null) {
13731                     focusHost.clearAccessibilityFocus();
13732                 }
13733             }
13734 
13735             // If we're moving between AUTO and another state, we might not need
13736             // to send a subtree changed notification. We'll store the computed
13737             // importance, since we'll need to check it later to make sure.
13738             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
13739                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
13740             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
13741             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13742             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
13743                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13744             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
13745                 notifySubtreeAccessibilityStateChangedIfNeeded();
13746             } else {
13747                 notifyViewAccessibilityStateChangedIfNeeded(
13748                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13749             }
13750         }
13751     }
13752 
13753     /**
13754      * Returns the view within this view's hierarchy that is hosting
13755      * accessibility focus.
13756      *
13757      * @param searchDescendants whether to search for focus in descendant views
13758      * @return the view hosting accessibility focus, or {@code null}
13759      */
findAccessibilityFocusHost(boolean searchDescendants)13760     private View findAccessibilityFocusHost(boolean searchDescendants) {
13761         if (isAccessibilityFocusedViewOrHost()) {
13762             return this;
13763         }
13764 
13765         if (searchDescendants) {
13766             final ViewRootImpl viewRoot = getViewRootImpl();
13767             if (viewRoot != null) {
13768                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
13769                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13770                     return focusHost;
13771                 }
13772             }
13773         }
13774 
13775         return null;
13776     }
13777 
13778     /**
13779      * Computes whether this view should be exposed for accessibility. In
13780      * general, views that are interactive or provide information are exposed
13781      * while views that serve only as containers are hidden.
13782      * <p>
13783      * If an ancestor of this view has importance
13784      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
13785      * returns <code>false</code>.
13786      * <p>
13787      * Otherwise, the value is computed according to the view's
13788      * {@link #getImportantForAccessibility()} value:
13789      * <ol>
13790      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
13791      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
13792      * </code>
13793      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
13794      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
13795      * view satisfies any of the following:
13796      * <ul>
13797      * <li>Is actionable, e.g. {@link #isClickable()},
13798      * {@link #isLongClickable()}, or {@link #isFocusable()}
13799      * <li>Has an {@link AccessibilityDelegate}
13800      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
13801      * {@link OnKeyListener}, etc.
13802      * <li>Is an accessibility live region, e.g.
13803      * {@link #getAccessibilityLiveRegion()} is not
13804      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
13805      * </ul>
13806      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
13807      * </ol>
13808      *
13809      * @return Whether the view is exposed for accessibility.
13810      * @see #setImportantForAccessibility(int)
13811      * @see #getImportantForAccessibility()
13812      */
isImportantForAccessibility()13813     public boolean isImportantForAccessibility() {
13814         final int mode = getImportantForAccessibility();
13815         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
13816                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13817             return false;
13818         }
13819 
13820         // Check parent mode to ensure we're not hidden.
13821         ViewParent parent = mParent;
13822         while (parent instanceof View) {
13823             if (((View) parent).getImportantForAccessibility()
13824                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13825                 return false;
13826             }
13827             parent = parent.getParent();
13828         }
13829 
13830         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
13831                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
13832                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
13833                 || isAccessibilityPane();
13834     }
13835 
13836     /**
13837      * Gets the parent for accessibility purposes. Note that the parent for
13838      * accessibility is not necessary the immediate parent. It is the first
13839      * predecessor that is important for accessibility.
13840      *
13841      * @return The parent for accessibility purposes.
13842      */
getParentForAccessibility()13843     public ViewParent getParentForAccessibility() {
13844         if (mParent instanceof View) {
13845             View parentView = (View) mParent;
13846             if (parentView.includeForAccessibility()) {
13847                 return mParent;
13848             } else {
13849                 return mParent.getParentForAccessibility();
13850             }
13851         }
13852         return null;
13853     }
13854 
13855     /** @hide */
getSelfOrParentImportantForA11y()13856     View getSelfOrParentImportantForA11y() {
13857         if (isImportantForAccessibility()) return this;
13858         ViewParent parent = getParentForAccessibility();
13859         if (parent instanceof View) return (View) parent;
13860         return null;
13861     }
13862 
13863     /**
13864      * Adds the children of this View relevant for accessibility to the given list
13865      * as output. Since some Views are not important for accessibility the added
13866      * child views are not necessarily direct children of this view, rather they are
13867      * the first level of descendants important for accessibility.
13868      *
13869      * @param outChildren The output list that will receive children for accessibility.
13870      */
addChildrenForAccessibility(ArrayList<View> outChildren)13871     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
13872 
13873     }
13874 
13875     /**
13876      * Whether to regard this view for accessibility. A view is regarded for
13877      * accessibility if it is important for accessibility or the querying
13878      * accessibility service has explicitly requested that view not
13879      * important for accessibility are regarded.
13880      *
13881      * @return Whether to regard the view for accessibility.
13882      *
13883      * @hide
13884      */
13885     @UnsupportedAppUsage
includeForAccessibility()13886     public boolean includeForAccessibility() {
13887         if (mAttachInfo != null) {
13888             return (mAttachInfo.mAccessibilityFetchFlags
13889                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
13890                     || isImportantForAccessibility();
13891         }
13892         return false;
13893     }
13894 
13895     /**
13896      * Returns whether the View is considered actionable from
13897      * accessibility perspective. Such view are important for
13898      * accessibility.
13899      *
13900      * @return True if the view is actionable for accessibility.
13901      *
13902      * @hide
13903      */
isActionableForAccessibility()13904     public boolean isActionableForAccessibility() {
13905         return (isClickable() || isLongClickable() || isFocusable());
13906     }
13907 
13908     /**
13909      * Returns whether the View has registered callbacks which makes it
13910      * important for accessibility.
13911      *
13912      * @return True if the view is actionable for accessibility.
13913      */
hasListenersForAccessibility()13914     private boolean hasListenersForAccessibility() {
13915         ListenerInfo info = getListenerInfo();
13916         return mTouchDelegate != null || info.mOnKeyListener != null
13917                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
13918                 || info.mOnHoverListener != null || info.mOnDragListener != null;
13919     }
13920 
13921     /**
13922      * Notifies that the accessibility state of this view changed. The change
13923      * is local to this view and does not represent structural changes such
13924      * as children and parent. For example, the view became focusable. The
13925      * notification is at at most once every
13926      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13927      * to avoid unnecessary load to the system. Also once a view has a pending
13928      * notification this method is a NOP until the notification has been sent.
13929      *
13930      * @hide
13931      */
13932     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyViewAccessibilityStateChangedIfNeeded(int changeType)13933     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
13934         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13935             return;
13936         }
13937 
13938         // Changes to views with a pane title count as window state changes, as the pane title
13939         // marks them as significant parts of the UI.
13940         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
13941                 && isAccessibilityPane()) {
13942             // If the pane isn't visible, content changed events are sufficient unless we're
13943             // reporting that the view just disappeared
13944             if ((getVisibility() == VISIBLE)
13945                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
13946                 final AccessibilityEvent event = AccessibilityEvent.obtain();
13947                 onInitializeAccessibilityEvent(event);
13948                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
13949                 event.setContentChangeTypes(changeType);
13950                 event.setSource(this);
13951                 onPopulateAccessibilityEvent(event);
13952                 if (mParent != null) {
13953                     try {
13954                         mParent.requestSendAccessibilityEvent(this, event);
13955                     } catch (AbstractMethodError e) {
13956                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
13957                                 + " does not fully implement ViewParent", e);
13958                     }
13959                 }
13960                 return;
13961             }
13962         }
13963 
13964         // If this is a live region, we should send a subtree change event
13965         // from this view immediately. Otherwise, we can let it propagate up.
13966         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
13967             final AccessibilityEvent event = AccessibilityEvent.obtain();
13968             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
13969             event.setContentChangeTypes(changeType);
13970             sendAccessibilityEventUnchecked(event);
13971         } else if (mParent != null) {
13972             try {
13973                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
13974             } catch (AbstractMethodError e) {
13975                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13976                         " does not fully implement ViewParent", e);
13977             }
13978         }
13979     }
13980 
13981     /**
13982      * Notifies that the accessibility state of this view changed. The change
13983      * is *not* local to this view and does represent structural changes such
13984      * as children and parent. For example, the view size changed. The
13985      * notification is at at most once every
13986      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13987      * to avoid unnecessary load to the system. Also once a view has a pending
13988      * notification this method is a NOP until the notification has been sent.
13989      *
13990      * @hide
13991      */
13992     @UnsupportedAppUsage
notifySubtreeAccessibilityStateChangedIfNeeded()13993     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
13994         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13995             return;
13996         }
13997 
13998         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
13999             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
14000             if (mParent != null) {
14001                 try {
14002                     mParent.notifySubtreeAccessibilityStateChanged(
14003                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
14004                 } catch (AbstractMethodError e) {
14005                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14006                             " does not fully implement ViewParent", e);
14007                 }
14008             }
14009         }
14010     }
14011 
notifySubtreeAccessibilityStateChangedByParentIfNeeded()14012     private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
14013         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
14014             return;
14015         }
14016 
14017         final View sendA11yEventView = (View) getParentForAccessibility();
14018         if (sendA11yEventView != null && sendA11yEventView.isShown()) {
14019             sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
14020         }
14021     }
14022 
14023     /**
14024      * Changes the visibility of this View without triggering any other changes. This should only
14025      * be used by animation frameworks, such as {@link android.transition.Transition}, where
14026      * visibility changes should not adjust focus or trigger a new layout. Application developers
14027      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
14028      *
14029      * <p>Only call this method when a temporary visibility must be applied during an
14030      * animation and the original visibility value is guaranteed to be reset after the
14031      * animation completes. Use {@link #setVisibility} in all other cases.</p>
14032      *
14033      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
14034      * @see #setVisibility(int)
14035      */
setTransitionVisibility(@isibility int visibility)14036     public void setTransitionVisibility(@Visibility int visibility) {
14037         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
14038     }
14039 
14040     /**
14041      * Reset the flag indicating the accessibility state of the subtree rooted
14042      * at this view changed.
14043      */
resetSubtreeAccessibilityStateChanged()14044     void resetSubtreeAccessibilityStateChanged() {
14045         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
14046     }
14047 
14048     /**
14049      * Report an accessibility action to this view's parents for delegated processing.
14050      *
14051      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
14052      * call this method to delegate an accessibility action to a supporting parent. If the parent
14053      * returns true from its
14054      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
14055      * method this method will return true to signify that the action was consumed.</p>
14056      *
14057      * <p>This method is useful for implementing nested scrolling child views. If
14058      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
14059      * a custom view implementation may invoke this method to allow a parent to consume the
14060      * scroll first. If this method returns true the custom view should skip its own scrolling
14061      * behavior.</p>
14062      *
14063      * @param action Accessibility action to delegate
14064      * @param arguments Optional action arguments
14065      * @return true if the action was consumed by a parent
14066      */
dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)14067     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
14068         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
14069             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
14070                 return true;
14071             }
14072         }
14073         return false;
14074     }
14075 
14076     /**
14077      * Performs the specified accessibility action on the view. For
14078      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
14079      * <p>
14080      * If an {@link AccessibilityDelegate} has been specified via calling
14081      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
14082      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
14083      * is responsible for handling this call.
14084      * </p>
14085      *
14086      * <p>The default implementation will delegate
14087      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
14088      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
14089      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
14090      *
14091      * @param action The action to perform.
14092      * @param arguments Optional action arguments.
14093      * @return Whether the action was performed.
14094      */
performAccessibilityAction(int action, Bundle arguments)14095     public boolean performAccessibilityAction(int action, Bundle arguments) {
14096       if (mAccessibilityDelegate != null) {
14097           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
14098       } else {
14099           return performAccessibilityActionInternal(action, arguments);
14100       }
14101     }
14102 
14103    /**
14104     * @see #performAccessibilityAction(int, Bundle)
14105     *
14106     * Note: Called from the default {@link AccessibilityDelegate}.
14107     *
14108     * @hide
14109     */
14110     @UnsupportedAppUsage
performAccessibilityActionInternal(int action, Bundle arguments)14111     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
14112         if (isNestedScrollingEnabled()
14113                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
14114                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
14115                 || action == R.id.accessibilityActionScrollUp
14116                 || action == R.id.accessibilityActionScrollLeft
14117                 || action == R.id.accessibilityActionScrollDown
14118                 || action == R.id.accessibilityActionScrollRight)) {
14119             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
14120                 return true;
14121             }
14122         }
14123 
14124         switch (action) {
14125             case AccessibilityNodeInfo.ACTION_CLICK: {
14126                 if (isClickable()) {
14127                     performClickInternal();
14128                     return true;
14129                 }
14130             } break;
14131             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
14132                 if (isLongClickable()) {
14133                     performLongClick();
14134                     return true;
14135                 }
14136             } break;
14137             case AccessibilityNodeInfo.ACTION_FOCUS: {
14138                 if (!hasFocus()) {
14139                     // Get out of touch mode since accessibility
14140                     // wants to move focus around.
14141                     getViewRootImpl().ensureTouchMode(false);
14142                     return requestFocus();
14143                 }
14144             } break;
14145             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
14146                 if (hasFocus()) {
14147                     clearFocus();
14148                     return !isFocused();
14149                 }
14150             } break;
14151             case AccessibilityNodeInfo.ACTION_SELECT: {
14152                 if (!isSelected()) {
14153                     setSelected(true);
14154                     return isSelected();
14155                 }
14156             } break;
14157             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
14158                 if (isSelected()) {
14159                     setSelected(false);
14160                     return !isSelected();
14161                 }
14162             } break;
14163             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
14164                 if (!isAccessibilityFocused()) {
14165                     return requestAccessibilityFocus();
14166                 }
14167             } break;
14168             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
14169                 if (isAccessibilityFocused()) {
14170                     clearAccessibilityFocus();
14171                     return true;
14172                 }
14173             } break;
14174             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
14175                 if (arguments != null) {
14176                     final int granularity = arguments.getInt(
14177                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
14178                     final boolean extendSelection = arguments.getBoolean(
14179                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
14180                     return traverseAtGranularity(granularity, true, extendSelection);
14181                 }
14182             } break;
14183             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
14184                 if (arguments != null) {
14185                     final int granularity = arguments.getInt(
14186                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
14187                     final boolean extendSelection = arguments.getBoolean(
14188                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
14189                     return traverseAtGranularity(granularity, false, extendSelection);
14190                 }
14191             } break;
14192             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
14193                 CharSequence text = getIterableTextForAccessibility();
14194                 if (text == null) {
14195                     return false;
14196                 }
14197                 final int start = (arguments != null) ? arguments.getInt(
14198                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
14199                 final int end = (arguments != null) ? arguments.getInt(
14200                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
14201                 // Only cursor position can be specified (selection length == 0)
14202                 if ((getAccessibilitySelectionStart() != start
14203                         || getAccessibilitySelectionEnd() != end)
14204                         && (start == end)) {
14205                     setAccessibilitySelection(start, end);
14206                     notifyViewAccessibilityStateChangedIfNeeded(
14207                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14208                     return true;
14209                 }
14210             } break;
14211             case R.id.accessibilityActionShowOnScreen: {
14212                 if (mAttachInfo != null) {
14213                     final Rect r = mAttachInfo.mTmpInvalRect;
14214                     getDrawingRect(r);
14215                     return requestRectangleOnScreen(r, true);
14216                 }
14217             } break;
14218             case R.id.accessibilityActionContextClick: {
14219                 if (isContextClickable()) {
14220                     performContextClick();
14221                     return true;
14222                 }
14223             } break;
14224             case R.id.accessibilityActionShowTooltip: {
14225                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
14226                     // Tooltip already showing
14227                     return false;
14228                 }
14229                 return showLongClickTooltip(0, 0);
14230             }
14231             case R.id.accessibilityActionHideTooltip: {
14232                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
14233                     // No tooltip showing
14234                     return false;
14235                 }
14236                 hideTooltip();
14237                 return true;
14238             }
14239         }
14240 
14241         if (action == R.id.accessibilityActionDragDrop) {
14242             if (!canAcceptAccessibilityDrop()) {
14243                 return false;
14244             }
14245             try {
14246                 if (mAttachInfo != null && mAttachInfo.mSession != null) {
14247                     final int[] location = new int[2];
14248                     getLocationInWindow(location);
14249                     final int centerX = location[0] + getWidth() / 2;
14250                     final int centerY = location[1] + getHeight() / 2;
14251                     return mAttachInfo.mSession.dropForAccessibility(mAttachInfo.mWindow,
14252                             centerX, centerY);
14253                 }
14254             } catch (RemoteException e) {
14255                 Log.e(VIEW_LOG_TAG, "Unable to drop for accessibility", e);
14256             }
14257             return false;
14258         } else if (action == R.id.accessibilityActionDragCancel) {
14259             if (!startedSystemDragForAccessibility()) {
14260                 return false;
14261             }
14262             if (mAttachInfo != null && mAttachInfo.mDragToken != null) {
14263                 cancelDragAndDrop();
14264                 return true;
14265             }
14266             return false;
14267         }
14268         return false;
14269     }
14270 
canAcceptAccessibilityDrop()14271     private boolean canAcceptAccessibilityDrop() {
14272         if (!canAcceptDrag()) {
14273             return false;
14274         }
14275         ListenerInfo li = mListenerInfo;
14276         return (li != null) && (li.mOnDragListener != null || li.mOnReceiveContentListener != null);
14277     }
14278 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)14279     private boolean traverseAtGranularity(int granularity, boolean forward,
14280             boolean extendSelection) {
14281         CharSequence text = getIterableTextForAccessibility();
14282         if (text == null || text.length() == 0) {
14283             return false;
14284         }
14285         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
14286         if (iterator == null) {
14287             return false;
14288         }
14289         int current = getAccessibilitySelectionEnd();
14290         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14291             current = forward ? 0 : text.length();
14292         }
14293         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
14294         if (range == null) {
14295             return false;
14296         }
14297         final int segmentStart = range[0];
14298         final int segmentEnd = range[1];
14299         int selectionStart;
14300         int selectionEnd;
14301         if (extendSelection && isAccessibilitySelectionExtendable()) {
14302             selectionStart = getAccessibilitySelectionStart();
14303             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14304                 selectionStart = forward ? segmentStart : segmentEnd;
14305             }
14306             selectionEnd = forward ? segmentEnd : segmentStart;
14307         } else {
14308             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
14309         }
14310         setAccessibilitySelection(selectionStart, selectionEnd);
14311         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
14312                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
14313         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
14314         return true;
14315     }
14316 
14317     /**
14318      * Gets the text reported for accessibility purposes.
14319      *
14320      * @return The accessibility text.
14321      *
14322      * @hide
14323      */
14324     @UnsupportedAppUsage
getIterableTextForAccessibility()14325     public CharSequence getIterableTextForAccessibility() {
14326         return getContentDescription();
14327     }
14328 
14329     /**
14330      * Gets whether accessibility selection can be extended.
14331      *
14332      * @return If selection is extensible.
14333      *
14334      * @hide
14335      */
isAccessibilitySelectionExtendable()14336     public boolean isAccessibilitySelectionExtendable() {
14337         return false;
14338     }
14339 
14340     /**
14341      * @hide
14342      */
getAccessibilitySelectionStart()14343     public int getAccessibilitySelectionStart() {
14344         return mAccessibilityCursorPosition;
14345     }
14346 
14347     /**
14348      * @hide
14349      */
getAccessibilitySelectionEnd()14350     public int getAccessibilitySelectionEnd() {
14351         return getAccessibilitySelectionStart();
14352     }
14353 
14354     /**
14355      * @hide
14356      */
setAccessibilitySelection(int start, int end)14357     public void setAccessibilitySelection(int start, int end) {
14358         if (start ==  end && end == mAccessibilityCursorPosition) {
14359             return;
14360         }
14361         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
14362             mAccessibilityCursorPosition = start;
14363         } else {
14364             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
14365         }
14366         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
14367     }
14368 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)14369     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
14370             int fromIndex, int toIndex) {
14371         if (mParent == null) {
14372             return;
14373         }
14374         AccessibilityEvent event = AccessibilityEvent.obtain(
14375                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
14376         onInitializeAccessibilityEvent(event);
14377         onPopulateAccessibilityEvent(event);
14378         event.setFromIndex(fromIndex);
14379         event.setToIndex(toIndex);
14380         event.setAction(action);
14381         event.setMovementGranularity(granularity);
14382         mParent.requestSendAccessibilityEvent(this, event);
14383     }
14384 
14385     /**
14386      * @hide
14387      */
14388     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getIteratorForGranularity(int granularity)14389     public TextSegmentIterator getIteratorForGranularity(int granularity) {
14390         switch (granularity) {
14391             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
14392                 CharSequence text = getIterableTextForAccessibility();
14393                 if (text != null && text.length() > 0) {
14394                     CharacterTextSegmentIterator iterator =
14395                         CharacterTextSegmentIterator.getInstance(
14396                                 mContext.getResources().getConfiguration().locale);
14397                     iterator.initialize(text.toString());
14398                     return iterator;
14399                 }
14400             } break;
14401             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
14402                 CharSequence text = getIterableTextForAccessibility();
14403                 if (text != null && text.length() > 0) {
14404                     WordTextSegmentIterator iterator =
14405                         WordTextSegmentIterator.getInstance(
14406                                 mContext.getResources().getConfiguration().locale);
14407                     iterator.initialize(text.toString());
14408                     return iterator;
14409                 }
14410             } break;
14411             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
14412                 CharSequence text = getIterableTextForAccessibility();
14413                 if (text != null && text.length() > 0) {
14414                     ParagraphTextSegmentIterator iterator =
14415                         ParagraphTextSegmentIterator.getInstance();
14416                     iterator.initialize(text.toString());
14417                     return iterator;
14418                 }
14419             } break;
14420         }
14421         return null;
14422     }
14423 
14424     /**
14425      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
14426      * and {@link #onFinishTemporaryDetach()}.
14427      *
14428      * <p>This method always returns {@code true} when called directly or indirectly from
14429      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
14430      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
14431      * <ul>
14432      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
14433      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
14434      * </ul>
14435      * </p>
14436      *
14437      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
14438      * and {@link #onFinishTemporaryDetach()}.
14439      */
isTemporarilyDetached()14440     public final boolean isTemporarilyDetached() {
14441         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
14442     }
14443 
14444     /**
14445      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
14446      * a container View.
14447      */
14448     @CallSuper
dispatchStartTemporaryDetach()14449     public void dispatchStartTemporaryDetach() {
14450         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
14451         notifyEnterOrExitForAutoFillIfNeeded(false);
14452         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
14453         onStartTemporaryDetach();
14454     }
14455 
14456     /**
14457      * This is called when a container is going to temporarily detach a child, with
14458      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
14459      * It will either be followed by {@link #onFinishTemporaryDetach()} or
14460      * {@link #onDetachedFromWindow()} when the container is done.
14461      */
onStartTemporaryDetach()14462     public void onStartTemporaryDetach() {
14463         removeUnsetPressCallback();
14464         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
14465     }
14466 
14467     /**
14468      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
14469      * a container View.
14470      */
14471     @CallSuper
dispatchFinishTemporaryDetach()14472     public void dispatchFinishTemporaryDetach() {
14473         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
14474         onFinishTemporaryDetach();
14475         if (hasWindowFocus() && hasFocus()) {
14476             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14477         }
14478         notifyEnterOrExitForAutoFillIfNeeded(true);
14479         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
14480     }
14481 
14482     /**
14483      * Called after {@link #onStartTemporaryDetach} when the container is done
14484      * changing the view.
14485      */
onFinishTemporaryDetach()14486     public void onFinishTemporaryDetach() {
14487     }
14488 
14489     /**
14490      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
14491      * for this view's window.  Returns null if the view is not currently attached
14492      * to the window.  Normally you will not need to use this directly, but
14493      * just use the standard high-level event callbacks like
14494      * {@link #onKeyDown(int, KeyEvent)}.
14495      */
getKeyDispatcherState()14496     public KeyEvent.DispatcherState getKeyDispatcherState() {
14497         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
14498     }
14499 
14500     /**
14501      * Dispatch a key event before it is processed by any input method
14502      * associated with the view hierarchy.  This can be used to intercept
14503      * key events in special situations before the IME consumes them; a
14504      * typical example would be handling the BACK key to update the application's
14505      * UI instead of allowing the IME to see it and close itself.
14506      *
14507      * @param event The key event to be dispatched.
14508      * @return True if the event was handled, false otherwise.
14509      */
dispatchKeyEventPreIme(KeyEvent event)14510     public boolean dispatchKeyEventPreIme(KeyEvent event) {
14511         return onKeyPreIme(event.getKeyCode(), event);
14512     }
14513 
14514     /**
14515      * Dispatch a key event to the next view on the focus path. This path runs
14516      * from the top of the view tree down to the currently focused view. If this
14517      * view has focus, it will dispatch to itself. Otherwise it will dispatch
14518      * the next node down the focus path. This method also fires any key
14519      * listeners.
14520      *
14521      * @param event The key event to be dispatched.
14522      * @return True if the event was handled, false otherwise.
14523      */
dispatchKeyEvent(KeyEvent event)14524     public boolean dispatchKeyEvent(KeyEvent event) {
14525         if (mInputEventConsistencyVerifier != null) {
14526             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
14527         }
14528 
14529         // Give any attached key listener a first crack at the event.
14530         //noinspection SimplifiableIfStatement
14531         ListenerInfo li = mListenerInfo;
14532         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
14533                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
14534             return true;
14535         }
14536 
14537         if (event.dispatch(this, mAttachInfo != null
14538                 ? mAttachInfo.mKeyDispatchState : null, this)) {
14539             return true;
14540         }
14541 
14542         if (mInputEventConsistencyVerifier != null) {
14543             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14544         }
14545         return false;
14546     }
14547 
14548     /**
14549      * Dispatches a key shortcut event.
14550      *
14551      * @param event The key event to be dispatched.
14552      * @return True if the event was handled by the view, false otherwise.
14553      */
dispatchKeyShortcutEvent(KeyEvent event)14554     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
14555         return onKeyShortcut(event.getKeyCode(), event);
14556     }
14557 
14558     /**
14559      * Pass the touch screen motion event down to the target view, or this
14560      * view if it is the target.
14561      *
14562      * @param event The motion event to be dispatched.
14563      * @return True if the event was handled by the view, false otherwise.
14564      */
dispatchTouchEvent(MotionEvent event)14565     public boolean dispatchTouchEvent(MotionEvent event) {
14566         // If the event should be handled by accessibility focus first.
14567         if (event.isTargetAccessibilityFocus()) {
14568             // We don't have focus or no virtual descendant has it, do not handle the event.
14569             if (!isAccessibilityFocusedViewOrHost()) {
14570                 return false;
14571             }
14572             // We have focus and got the event, then use normal event dispatch.
14573             event.setTargetAccessibilityFocus(false);
14574         }
14575         boolean result = false;
14576 
14577         if (mInputEventConsistencyVerifier != null) {
14578             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
14579         }
14580 
14581         final int actionMasked = event.getActionMasked();
14582         if (actionMasked == MotionEvent.ACTION_DOWN) {
14583             // Defensive cleanup for new gesture
14584             stopNestedScroll();
14585         }
14586 
14587         if (onFilterTouchEventForSecurity(event)) {
14588             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
14589                 result = true;
14590             }
14591             //noinspection SimplifiableIfStatement
14592             ListenerInfo li = mListenerInfo;
14593             if (li != null && li.mOnTouchListener != null
14594                     && (mViewFlags & ENABLED_MASK) == ENABLED
14595                     && li.mOnTouchListener.onTouch(this, event)) {
14596                 result = true;
14597             }
14598 
14599             if (!result && onTouchEvent(event)) {
14600                 result = true;
14601             }
14602         }
14603 
14604         if (!result && mInputEventConsistencyVerifier != null) {
14605             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14606         }
14607 
14608         // Clean up after nested scrolls if this is the end of a gesture;
14609         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
14610         // of the gesture.
14611         if (actionMasked == MotionEvent.ACTION_UP ||
14612                 actionMasked == MotionEvent.ACTION_CANCEL ||
14613                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
14614             stopNestedScroll();
14615         }
14616 
14617         return result;
14618     }
14619 
isAccessibilityFocusedViewOrHost()14620     boolean isAccessibilityFocusedViewOrHost() {
14621         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
14622                 .getAccessibilityFocusedHost() == this);
14623     }
14624 
14625     /**
14626      * Returns whether this view can receive pointer events.
14627      *
14628      * @return {@code true} if this view can receive pointer events.
14629      * @hide
14630      */
canReceivePointerEvents()14631     protected boolean canReceivePointerEvents() {
14632         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
14633     }
14634 
14635     /**
14636      * Filter the touch event to apply security policies.
14637      *
14638      * @param event The motion event to be filtered.
14639      * @return True if the event should be dispatched, false if the event should be dropped.
14640      *
14641      * @see #getFilterTouchesWhenObscured
14642      */
onFilterTouchEventForSecurity(MotionEvent event)14643     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
14644         //noinspection RedundantIfStatement
14645         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
14646                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
14647             // Window is obscured, drop this touch.
14648             return false;
14649         }
14650         return true;
14651     }
14652 
14653     /**
14654      * Pass a trackball motion event down to the focused view.
14655      *
14656      * @param event The motion event to be dispatched.
14657      * @return True if the event was handled by the view, false otherwise.
14658      */
dispatchTrackballEvent(MotionEvent event)14659     public boolean dispatchTrackballEvent(MotionEvent event) {
14660         if (mInputEventConsistencyVerifier != null) {
14661             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
14662         }
14663 
14664         return onTrackballEvent(event);
14665     }
14666 
14667     /**
14668      * Pass a captured pointer event down to the focused view.
14669      *
14670      * @param event The motion event to be dispatched.
14671      * @return True if the event was handled by the view, false otherwise.
14672      */
dispatchCapturedPointerEvent(MotionEvent event)14673     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
14674         if (!hasPointerCapture()) {
14675             return false;
14676         }
14677         //noinspection SimplifiableIfStatement
14678         ListenerInfo li = mListenerInfo;
14679         if (li != null && li.mOnCapturedPointerListener != null
14680                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
14681             return true;
14682         }
14683         return onCapturedPointerEvent(event);
14684     }
14685 
14686     /**
14687      * Dispatch a generic motion event.
14688      * <p>
14689      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
14690      * are delivered to the view under the pointer.  All other generic motion events are
14691      * delivered to the focused view.  Hover events are handled specially and are delivered
14692      * to {@link #onHoverEvent(MotionEvent)}.
14693      * </p>
14694      *
14695      * @param event The motion event to be dispatched.
14696      * @return True if the event was handled by the view, false otherwise.
14697      */
dispatchGenericMotionEvent(MotionEvent event)14698     public boolean dispatchGenericMotionEvent(MotionEvent event) {
14699         if (mInputEventConsistencyVerifier != null) {
14700             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
14701         }
14702 
14703         final int source = event.getSource();
14704         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
14705             final int action = event.getAction();
14706             if (action == MotionEvent.ACTION_HOVER_ENTER
14707                     || action == MotionEvent.ACTION_HOVER_MOVE
14708                     || action == MotionEvent.ACTION_HOVER_EXIT) {
14709                 if (dispatchHoverEvent(event)) {
14710                     return true;
14711                 }
14712             } else if (dispatchGenericPointerEvent(event)) {
14713                 return true;
14714             }
14715         } else if (dispatchGenericFocusedEvent(event)) {
14716             return true;
14717         }
14718 
14719         if (dispatchGenericMotionEventInternal(event)) {
14720             return true;
14721         }
14722 
14723         if (mInputEventConsistencyVerifier != null) {
14724             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14725         }
14726         return false;
14727     }
14728 
dispatchGenericMotionEventInternal(MotionEvent event)14729     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
14730         //noinspection SimplifiableIfStatement
14731         ListenerInfo li = mListenerInfo;
14732         if (li != null && li.mOnGenericMotionListener != null
14733                 && (mViewFlags & ENABLED_MASK) == ENABLED
14734                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
14735             return true;
14736         }
14737 
14738         if (onGenericMotionEvent(event)) {
14739             return true;
14740         }
14741 
14742         final int actionButton = event.getActionButton();
14743         switch (event.getActionMasked()) {
14744             case MotionEvent.ACTION_BUTTON_PRESS:
14745                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
14746                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14747                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14748                     if (performContextClick(event.getX(), event.getY())) {
14749                         mInContextButtonPress = true;
14750                         setPressed(true, event.getX(), event.getY());
14751                         removeTapCallback();
14752                         removeLongPressCallback();
14753                         return true;
14754                     }
14755                 }
14756                 break;
14757 
14758             case MotionEvent.ACTION_BUTTON_RELEASE:
14759                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14760                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14761                     mInContextButtonPress = false;
14762                     mIgnoreNextUpEvent = true;
14763                 }
14764                 break;
14765         }
14766 
14767         if (mInputEventConsistencyVerifier != null) {
14768             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14769         }
14770         return false;
14771     }
14772 
14773     /**
14774      * Dispatch a hover event.
14775      * <p>
14776      * Do not call this method directly.
14777      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14778      * </p>
14779      *
14780      * @param event The motion event to be dispatched.
14781      * @return True if the event was handled by the view, false otherwise.
14782      */
dispatchHoverEvent(MotionEvent event)14783     protected boolean dispatchHoverEvent(MotionEvent event) {
14784         ListenerInfo li = mListenerInfo;
14785         //noinspection SimplifiableIfStatement
14786         if (li != null && li.mOnHoverListener != null
14787                 && (mViewFlags & ENABLED_MASK) == ENABLED
14788                 && li.mOnHoverListener.onHover(this, event)) {
14789             return true;
14790         }
14791 
14792         return onHoverEvent(event);
14793     }
14794 
14795     /**
14796      * Returns true if the view has a child to which it has recently sent
14797      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
14798      * it does not have a hovered child, then it must be the innermost hovered view.
14799      * @hide
14800      */
hasHoveredChild()14801     protected boolean hasHoveredChild() {
14802         return false;
14803     }
14804 
14805     /**
14806      * Returns true if the given point, in local coordinates, is inside the hovered child.
14807      *
14808      * @hide
14809      */
pointInHoveredChild(MotionEvent event)14810     protected boolean pointInHoveredChild(MotionEvent event) {
14811         return false;
14812     }
14813 
14814     /**
14815      * Dispatch a generic motion event to the view under the first pointer.
14816      * <p>
14817      * Do not call this method directly.
14818      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14819      * </p>
14820      *
14821      * @param event The motion event to be dispatched.
14822      * @return True if the event was handled by the view, false otherwise.
14823      */
dispatchGenericPointerEvent(MotionEvent event)14824     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
14825         return false;
14826     }
14827 
14828     /**
14829      * Dispatch a generic motion event to the currently focused view.
14830      * <p>
14831      * Do not call this method directly.
14832      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14833      * </p>
14834      *
14835      * @param event The motion event to be dispatched.
14836      * @return True if the event was handled by the view, false otherwise.
14837      */
dispatchGenericFocusedEvent(MotionEvent event)14838     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
14839         return false;
14840     }
14841 
14842     /**
14843      * Dispatch a pointer event.
14844      * <p>
14845      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
14846      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
14847      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
14848      * and should not be expected to handle other pointing device features.
14849      * </p>
14850      *
14851      * @param event The motion event to be dispatched.
14852      * @return True if the event was handled by the view, false otherwise.
14853      * @hide
14854      */
14855     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchPointerEvent(MotionEvent event)14856     public final boolean dispatchPointerEvent(MotionEvent event) {
14857         if (event.isTouchEvent()) {
14858             return dispatchTouchEvent(event);
14859         } else {
14860             return dispatchGenericMotionEvent(event);
14861         }
14862     }
14863 
14864     /**
14865      * Called when the window containing this view gains or loses window focus.
14866      * ViewGroups should override to route to their children.
14867      *
14868      * @param hasFocus True if the window containing this view now has focus,
14869      *        false otherwise.
14870      */
dispatchWindowFocusChanged(boolean hasFocus)14871     public void dispatchWindowFocusChanged(boolean hasFocus) {
14872         onWindowFocusChanged(hasFocus);
14873     }
14874 
14875     /**
14876      * Called when the window containing this view gains or loses focus.  Note
14877      * that this is separate from view focus: to receive key events, both
14878      * your view and its window must have focus.  If a window is displayed
14879      * on top of yours that takes input focus, then your own window will lose
14880      * focus but the view focus will remain unchanged.
14881      *
14882      * @param hasWindowFocus True if the window containing this view now has
14883      *        focus, false otherwise.
14884      */
onWindowFocusChanged(boolean hasWindowFocus)14885     public void onWindowFocusChanged(boolean hasWindowFocus) {
14886         if (!hasWindowFocus) {
14887             if (isPressed()) {
14888                 setPressed(false);
14889             }
14890             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14891             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14892                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
14893             }
14894             removeLongPressCallback();
14895             removeTapCallback();
14896             onFocusLost();
14897         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14898             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14899         }
14900 
14901         refreshDrawableState();
14902     }
14903 
14904     /**
14905      * Returns true if this view is in a window that currently has window focus.
14906      * Note that this is not the same as the view itself having focus.
14907      *
14908      * @return True if this view is in a window that currently has window focus.
14909      */
hasWindowFocus()14910     public boolean hasWindowFocus() {
14911         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
14912     }
14913 
14914     /**
14915      * @return {@code true} if this view is in a window that currently has IME focusable state.
14916      * @hide
14917      */
hasImeFocus()14918     public boolean hasImeFocus() {
14919         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
14920     }
14921 
14922     /**
14923      * Dispatch a view visibility change down the view hierarchy.
14924      * ViewGroups should override to route to their children.
14925      * @param changedView The view whose visibility changed. Could be 'this' or
14926      * an ancestor view.
14927      * @param visibility The new visibility of changedView: {@link #VISIBLE},
14928      * {@link #INVISIBLE} or {@link #GONE}.
14929      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)14930     protected void dispatchVisibilityChanged(@NonNull View changedView,
14931             @Visibility int visibility) {
14932         onVisibilityChanged(changedView, visibility);
14933     }
14934 
14935     /**
14936      * Called when the visibility of the view or an ancestor of the view has
14937      * changed.
14938      *
14939      * @param changedView The view whose visibility changed. May be
14940      *                    {@code this} or an ancestor view.
14941      * @param visibility The new visibility, one of {@link #VISIBLE},
14942      *                   {@link #INVISIBLE} or {@link #GONE}.
14943      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)14944     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
14945     }
14946 
14947     /**
14948      * Dispatch a hint about whether this view is displayed. For instance, when
14949      * a View moves out of the screen, it might receives a display hint indicating
14950      * the view is not displayed. Applications should not <em>rely</em> on this hint
14951      * as there is no guarantee that they will receive one.
14952      *
14953      * @param hint A hint about whether or not this view is displayed:
14954      * {@link #VISIBLE} or {@link #INVISIBLE}.
14955      */
dispatchDisplayHint(@isibility int hint)14956     public void dispatchDisplayHint(@Visibility int hint) {
14957         onDisplayHint(hint);
14958     }
14959 
14960     /**
14961      * Gives this view a hint about whether is displayed or not. For instance, when
14962      * a View moves out of the screen, it might receives a display hint indicating
14963      * the view is not displayed. Applications should not <em>rely</em> on this hint
14964      * as there is no guarantee that they will receive one.
14965      *
14966      * @param hint A hint about whether or not this view is displayed:
14967      * {@link #VISIBLE} or {@link #INVISIBLE}.
14968      */
onDisplayHint(@isibility int hint)14969     protected void onDisplayHint(@Visibility int hint) {
14970     }
14971 
14972     /**
14973      * Dispatch a window visibility change down the view hierarchy.
14974      * ViewGroups should override to route to their children.
14975      *
14976      * @param visibility The new visibility of the window.
14977      *
14978      * @see #onWindowVisibilityChanged(int)
14979      */
dispatchWindowVisibilityChanged(@isibility int visibility)14980     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
14981         onWindowVisibilityChanged(visibility);
14982     }
14983 
14984     /**
14985      * Called when the window containing has change its visibility
14986      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
14987      * that this tells you whether or not your window is being made visible
14988      * to the window manager; this does <em>not</em> tell you whether or not
14989      * your window is obscured by other windows on the screen, even if it
14990      * is itself visible.
14991      *
14992      * @param visibility The new visibility of the window.
14993      */
onWindowVisibilityChanged(@isibility int visibility)14994     protected void onWindowVisibilityChanged(@Visibility int visibility) {
14995         if (visibility == VISIBLE) {
14996             initialAwakenScrollBars();
14997         }
14998     }
14999 
15000     /**
15001      * @return true if this view and all ancestors are visible as of the last
15002      * {@link #onVisibilityAggregated(boolean)} call.
15003      */
isAggregatedVisible()15004     boolean isAggregatedVisible() {
15005         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
15006     }
15007 
15008     /**
15009      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
15010      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
15011      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
15012      *
15013      * @param isVisible true if this view's visibility to the user is uninterrupted by its
15014      *                  ancestors or by window visibility
15015      * @return true if this view is visible to the user, not counting clipping or overlapping
15016      */
dispatchVisibilityAggregated(boolean isVisible)15017     boolean dispatchVisibilityAggregated(boolean isVisible) {
15018         final boolean thisVisible = getVisibility() == VISIBLE;
15019         // If we're not visible but something is telling us we are, ignore it.
15020         if (thisVisible || !isVisible) {
15021             onVisibilityAggregated(isVisible);
15022         }
15023         return thisVisible && isVisible;
15024     }
15025 
15026     /**
15027      * Called when the user-visibility of this View is potentially affected by a change
15028      * to this view itself, an ancestor view or the window this view is attached to.
15029      *
15030      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
15031      *                  and this view's window is also visible
15032      */
15033     @CallSuper
onVisibilityAggregated(boolean isVisible)15034     public void onVisibilityAggregated(boolean isVisible) {
15035         // Update our internal visibility tracking so we can detect changes
15036         boolean oldVisible = isAggregatedVisible();
15037         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
15038                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
15039         if (isVisible && mAttachInfo != null) {
15040             initialAwakenScrollBars();
15041         }
15042 
15043         final Drawable dr = mBackground;
15044         if (dr != null && isVisible != dr.isVisible()) {
15045             dr.setVisible(isVisible, false);
15046         }
15047         final Drawable hl = mDefaultFocusHighlight;
15048         if (hl != null && isVisible != hl.isVisible()) {
15049             hl.setVisible(isVisible, false);
15050         }
15051         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
15052         if (fg != null && isVisible != fg.isVisible()) {
15053             fg.setVisible(isVisible, false);
15054         }
15055 
15056         if (isAutofillable()) {
15057             AutofillManager afm = getAutofillManager();
15058 
15059             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
15060                 if (mVisibilityChangeForAutofillHandler != null) {
15061                     mVisibilityChangeForAutofillHandler.removeMessages(0);
15062                 }
15063 
15064                 // If the view is in the background but still part of the hierarchy this is called
15065                 // with isVisible=false. Hence visibility==false requires further checks
15066                 if (isVisible) {
15067                     afm.notifyViewVisibilityChanged(this, true);
15068                 } else {
15069                     if (mVisibilityChangeForAutofillHandler == null) {
15070                         mVisibilityChangeForAutofillHandler =
15071                                 new VisibilityChangeForAutofillHandler(afm, this);
15072                     }
15073                     // Let current operation (e.g. removal of the view from the hierarchy)
15074                     // finish before checking state
15075                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
15076                 }
15077             }
15078         }
15079 
15080         if (isVisible != oldVisible) {
15081             if (isAccessibilityPane()) {
15082                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
15083                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
15084                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
15085             }
15086 
15087             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
15088 
15089             if (!getSystemGestureExclusionRects().isEmpty()) {
15090                 postUpdateSystemGestureExclusionRects();
15091             }
15092         }
15093     }
15094 
15095     /**
15096      * Returns the current visibility of the window this view is attached to
15097      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
15098      *
15099      * @return Returns the current visibility of the view's window.
15100      */
15101     @Visibility
getWindowVisibility()15102     public int getWindowVisibility() {
15103         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
15104     }
15105 
15106     /**
15107      * Retrieve the overall visible display size in which the window this view is
15108      * attached to has been positioned in.  This takes into account screen
15109      * decorations above the window, for both cases where the window itself
15110      * is being position inside of them or the window is being placed under
15111      * then and covered insets are used for the window to position its content
15112      * inside.  In effect, this tells you the available area where content can
15113      * be placed and remain visible to users.
15114      *
15115      * @param outRect Filled in with the visible display frame.  If the view
15116      * is not attached to a window, this is simply the raw display size.
15117      */
getWindowVisibleDisplayFrame(Rect outRect)15118     public void getWindowVisibleDisplayFrame(Rect outRect) {
15119         if (mAttachInfo != null) {
15120             mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
15121             return;
15122         }
15123         // The view is not attached to a display so we don't have a context.
15124         // Make a best guess about the display size.
15125         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
15126         d.getRectSize(outRect);
15127     }
15128 
15129     /**
15130      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
15131      * is currently in without any insets.
15132      *
15133      * @hide
15134      */
15135     @UnsupportedAppUsage
getWindowDisplayFrame(Rect outRect)15136     public void getWindowDisplayFrame(Rect outRect) {
15137         if (mAttachInfo != null) {
15138             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
15139             return;
15140         }
15141         // The view is not attached to a display so we don't have a context.
15142         // Make a best guess about the display size.
15143         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
15144         d.getRectSize(outRect);
15145     }
15146 
15147     /**
15148      * Dispatch a notification about a resource configuration change down
15149      * the view hierarchy.
15150      * ViewGroups should override to route to their children.
15151      *
15152      * @param newConfig The new resource configuration.
15153      *
15154      * @see #onConfigurationChanged(android.content.res.Configuration)
15155      */
dispatchConfigurationChanged(Configuration newConfig)15156     public void dispatchConfigurationChanged(Configuration newConfig) {
15157         onConfigurationChanged(newConfig);
15158     }
15159 
15160     /**
15161      * Called when the current configuration of the resources being used
15162      * by the application have changed.  You can use this to decide when
15163      * to reload resources that can changed based on orientation and other
15164      * configuration characteristics.  You only need to use this if you are
15165      * not relying on the normal {@link android.app.Activity} mechanism of
15166      * recreating the activity instance upon a configuration change.
15167      *
15168      * @param newConfig The new resource configuration.
15169      */
onConfigurationChanged(Configuration newConfig)15170     protected void onConfigurationChanged(Configuration newConfig) {
15171     }
15172 
15173     /**
15174      * Private function to aggregate all per-view attributes in to the view
15175      * root.
15176      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)15177     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
15178         performCollectViewAttributes(attachInfo, visibility);
15179     }
15180 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)15181     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
15182         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
15183             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
15184                 attachInfo.mKeepScreenOn = true;
15185             }
15186             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
15187             ListenerInfo li = mListenerInfo;
15188             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15189                 attachInfo.mHasSystemUiListeners = true;
15190             }
15191         }
15192     }
15193 
needGlobalAttributesUpdate(boolean force)15194     void needGlobalAttributesUpdate(boolean force) {
15195         final AttachInfo ai = mAttachInfo;
15196         if (ai != null && !ai.mRecomputeGlobalAttributes) {
15197             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
15198                     || ai.mHasSystemUiListeners) {
15199                 ai.mRecomputeGlobalAttributes = true;
15200             }
15201         }
15202     }
15203 
15204     /**
15205      * Returns whether the device is currently in touch mode.  Touch mode is entered
15206      * once the user begins interacting with the device by touch, and affects various
15207      * things like whether focus is always visible to the user.
15208      *
15209      * @return Whether the device is in touch mode.
15210      */
15211     @ViewDebug.ExportedProperty
isInTouchMode()15212     public boolean isInTouchMode() {
15213         if (mAttachInfo != null) {
15214             return mAttachInfo.mInTouchMode;
15215         } else {
15216             return ViewRootImpl.isInTouchMode();
15217         }
15218     }
15219 
15220     /**
15221      * Returns the context the view is running in, through which it can
15222      * access the current theme, resources, etc.
15223      *
15224      * @return The view's Context.
15225      */
15226     @ViewDebug.CapturedViewProperty
15227     @UiContext
getContext()15228     public final Context getContext() {
15229         return mContext;
15230     }
15231 
15232     /**
15233      * Handle a key event before it is processed by any input method
15234      * associated with the view hierarchy.  This can be used to intercept
15235      * key events in special situations before the IME consumes them; a
15236      * typical example would be handling the BACK key to update the application's
15237      * UI instead of allowing the IME to see it and close itself.
15238      *
15239      * @param keyCode The value in event.getKeyCode().
15240      * @param event Description of the key event.
15241      * @return If you handled the event, return true. If you want to allow the
15242      *         event to be handled by the next receiver, return false.
15243      */
onKeyPreIme(int keyCode, KeyEvent event)15244     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
15245         return false;
15246     }
15247 
15248     /**
15249      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
15250      * KeyEvent.Callback.onKeyDown()}: perform press of the view
15251      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
15252      * is released, if the view is enabled and clickable.
15253      * <p>
15254      * Key presses in software keyboards will generally NOT trigger this
15255      * listener, although some may elect to do so in some situations. Do not
15256      * rely on this to catch software key presses.
15257      *
15258      * @param keyCode a key code that represents the button pressed, from
15259      *                {@link android.view.KeyEvent}
15260      * @param event the KeyEvent object that defines the button action
15261      */
onKeyDown(int keyCode, KeyEvent event)15262     public boolean onKeyDown(int keyCode, KeyEvent event) {
15263         if (KeyEvent.isConfirmKey(keyCode)) {
15264             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15265                 return true;
15266             }
15267 
15268             if (event.getRepeatCount() == 0) {
15269                 // Long clickable items don't necessarily have to be clickable.
15270                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
15271                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
15272                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
15273                     // For the purposes of menu anchoring and drawable hotspots,
15274                     // key events are considered to be at the center of the view.
15275                     final float x = getWidth() / 2f;
15276                     final float y = getHeight() / 2f;
15277                     if (clickable) {
15278                         setPressed(true, x, y);
15279                     }
15280                     checkForLongClick(
15281                             ViewConfiguration.getLongPressTimeout(),
15282                             x,
15283                             y,
15284                             // This is not a touch gesture -- do not classify it as one.
15285                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
15286                     return true;
15287                 }
15288             }
15289         }
15290 
15291         return false;
15292     }
15293 
15294     /**
15295      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
15296      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
15297      * the event).
15298      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15299      * although some may elect to do so in some situations. Do not rely on this to
15300      * catch software key presses.
15301      */
onKeyLongPress(int keyCode, KeyEvent event)15302     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
15303         return false;
15304     }
15305 
15306     /**
15307      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
15308      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
15309      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
15310      * or {@link KeyEvent#KEYCODE_SPACE} is released.
15311      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15312      * although some may elect to do so in some situations. Do not rely on this to
15313      * catch software key presses.
15314      *
15315      * @param keyCode A key code that represents the button pressed, from
15316      *                {@link android.view.KeyEvent}.
15317      * @param event   The KeyEvent object that defines the button action.
15318      */
onKeyUp(int keyCode, KeyEvent event)15319     public boolean onKeyUp(int keyCode, KeyEvent event) {
15320         if (KeyEvent.isConfirmKey(keyCode)) {
15321             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15322                 return true;
15323             }
15324             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
15325                 setPressed(false);
15326 
15327                 if (!mHasPerformedLongPress) {
15328                     // This is a tap, so remove the longpress check
15329                     removeLongPressCallback();
15330                     if (!event.isCanceled()) {
15331                         return performClickInternal();
15332                     }
15333                 }
15334             }
15335         }
15336         return false;
15337     }
15338 
15339     /**
15340      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
15341      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
15342      * the event).
15343      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15344      * although some may elect to do so in some situations. Do not rely on this to
15345      * catch software key presses.
15346      *
15347      * @param keyCode     A key code that represents the button pressed, from
15348      *                    {@link android.view.KeyEvent}.
15349      * @param repeatCount The number of times the action was made.
15350      * @param event       The KeyEvent object that defines the button action.
15351      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)15352     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
15353         return false;
15354     }
15355 
15356     /**
15357      * Called on the focused view when a key shortcut event is not handled.
15358      * Override this method to implement local key shortcuts for the View.
15359      * Key shortcuts can also be implemented by setting the
15360      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
15361      *
15362      * @param keyCode The value in event.getKeyCode().
15363      * @param event Description of the key event.
15364      * @return If you handled the event, return true. If you want to allow the
15365      *         event to be handled by the next receiver, return false.
15366      */
onKeyShortcut(int keyCode, KeyEvent event)15367     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
15368         return false;
15369     }
15370 
15371     /**
15372      * Check whether the called view is a text editor, in which case it
15373      * would make sense to automatically display a soft input window for
15374      * it.  Subclasses should override this if they implement
15375      * {@link #onCreateInputConnection(EditorInfo)} to return true if
15376      * a call on that method would return a non-null InputConnection, and
15377      * they are really a first-class editor that the user would normally
15378      * start typing on when the go into a window containing your view.
15379      *
15380      * <p>The default implementation always returns false.  This does
15381      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
15382      * will not be called or the user can not otherwise perform edits on your
15383      * view; it is just a hint to the system that this is not the primary
15384      * purpose of this view.
15385      *
15386      * @return Returns true if this view is a text editor, else false.
15387      */
onCheckIsTextEditor()15388     public boolean onCheckIsTextEditor() {
15389         return false;
15390     }
15391 
15392     /**
15393      * Create a new InputConnection for an InputMethod to interact
15394      * with the view.  The default implementation returns null, since it doesn't
15395      * support input methods.  You can override this to implement such support.
15396      * This is only needed for views that take focus and text input.
15397      *
15398      * <p>When implementing this, you probably also want to implement
15399      * {@link #onCheckIsTextEditor()} to indicate you will return a
15400      * non-null InputConnection.</p>
15401      *
15402      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
15403      * object correctly and in its entirety, so that the connected IME can rely
15404      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
15405      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
15406      * must be filled in with the correct cursor position for IMEs to work correctly
15407      * with your application.</p>
15408      *
15409      * @param outAttrs Fill in with attribute information about the connection.
15410      */
onCreateInputConnection(EditorInfo outAttrs)15411     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
15412         return null;
15413     }
15414 
15415     /**
15416      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
15417      * that the system has successfully initialized an {@link InputConnection} and it is ready for
15418      * use.
15419      *
15420      * <p>The default implementation does nothing, since a view doesn't support input methods by
15421      * default (see {@link #onCreateInputConnection}).
15422      *
15423      * @param inputConnection The {@link InputConnection} from {@link #onCreateInputConnection},
15424      * after it's been fully initialized by the system.
15425      * @param editorInfo The {@link EditorInfo} that was used to create the {@link InputConnection}.
15426      * @param handler The dedicated {@link Handler} on which IPC method calls from input methods
15427      * will be dispatched. This is the handler returned by {@link InputConnection#getHandler()}. If
15428      * that method returns null, this parameter will be null also.
15429      *
15430      * @hide
15431      */
onInputConnectionOpenedInternal(@onNull InputConnection inputConnection, @NonNull EditorInfo editorInfo, @Nullable Handler handler)15432     public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
15433             @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
15434 
15435     /**
15436      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
15437      * that the {@link InputConnection} has been closed.
15438      *
15439      * <p>The default implementation does nothing, since a view doesn't support input methods by
15440      * default (see {@link #onCreateInputConnection}).
15441      *
15442      * <p><strong>Note:</strong> This callback is not invoked if the view is already detached when
15443      * the {@link InputConnection} is closed or the connection is not valid and managed by
15444      * {@link com.android.server.inputmethod.InputMethodManagerService}.
15445      * TODO(b/170645312): Before un-hiding this API, handle the detached view scenario.
15446      *
15447      * @hide
15448      */
onInputConnectionClosedInternal()15449     public void onInputConnectionClosedInternal() {}
15450 
15451     /**
15452      * Called by the {@link android.view.inputmethod.InputMethodManager}
15453      * when a view who is not the current
15454      * input connection target is trying to make a call on the manager.  The
15455      * default implementation returns false; you can override this to return
15456      * true for certain views if you are performing InputConnection proxying
15457      * to them.
15458      * @param view The View that is making the InputMethodManager call.
15459      * @return Return true to allow the call, false to reject.
15460      */
checkInputConnectionProxy(View view)15461     public boolean checkInputConnectionProxy(View view) {
15462         return false;
15463     }
15464 
15465     /**
15466      * Show the context menu for this view. It is not safe to hold on to the
15467      * menu after returning from this method.
15468      *
15469      * You should normally not overload this method. Overload
15470      * {@link #onCreateContextMenu(ContextMenu)} or define an
15471      * {@link OnCreateContextMenuListener} to add items to the context menu.
15472      *
15473      * @param menu The context menu to populate
15474      */
createContextMenu(ContextMenu menu)15475     public void createContextMenu(ContextMenu menu) {
15476         ContextMenuInfo menuInfo = getContextMenuInfo();
15477 
15478         // Sets the current menu info so all items added to menu will have
15479         // my extra info set.
15480         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
15481 
15482         onCreateContextMenu(menu);
15483         ListenerInfo li = mListenerInfo;
15484         if (li != null && li.mOnCreateContextMenuListener != null) {
15485             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
15486         }
15487 
15488         // Clear the extra information so subsequent items that aren't mine don't
15489         // have my extra info.
15490         ((MenuBuilder)menu).setCurrentMenuInfo(null);
15491 
15492         if (mParent != null) {
15493             mParent.createContextMenu(menu);
15494         }
15495     }
15496 
15497     /**
15498      * Views should implement this if they have extra information to associate
15499      * with the context menu. The return result is supplied as a parameter to
15500      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
15501      * callback.
15502      *
15503      * @return Extra information about the item for which the context menu
15504      *         should be shown. This information will vary across different
15505      *         subclasses of View.
15506      */
getContextMenuInfo()15507     protected ContextMenuInfo getContextMenuInfo() {
15508         return null;
15509     }
15510 
15511     /**
15512      * Views should implement this if the view itself is going to add items to
15513      * the context menu.
15514      *
15515      * @param menu the context menu to populate
15516      */
onCreateContextMenu(ContextMenu menu)15517     protected void onCreateContextMenu(ContextMenu menu) {
15518     }
15519 
15520     /**
15521      * Implement this method to handle trackball motion events.  The
15522      * <em>relative</em> movement of the trackball since the last event
15523      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
15524      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
15525      * that a movement of 1 corresponds to the user pressing one DPAD key (so
15526      * they will often be fractional values, representing the more fine-grained
15527      * movement information available from a trackball).
15528      *
15529      * @param event The motion event.
15530      * @return True if the event was handled, false otherwise.
15531      */
onTrackballEvent(MotionEvent event)15532     public boolean onTrackballEvent(MotionEvent event) {
15533         return false;
15534     }
15535 
15536     /**
15537      * Implement this method to handle generic motion events.
15538      * <p>
15539      * Generic motion events describe joystick movements, mouse hovers, track pad
15540      * touches, scroll wheel movements and other input events.  The
15541      * {@link MotionEvent#getSource() source} of the motion event specifies
15542      * the class of input that was received.  Implementations of this method
15543      * must examine the bits in the source before processing the event.
15544      * The following code example shows how this is done.
15545      * </p><p>
15546      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
15547      * are delivered to the view under the pointer.  All other generic motion events are
15548      * delivered to the focused view.
15549      * </p>
15550      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
15551      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
15552      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
15553      *             // process the joystick movement...
15554      *             return true;
15555      *         }
15556      *     }
15557      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
15558      *         switch (event.getAction()) {
15559      *             case MotionEvent.ACTION_HOVER_MOVE:
15560      *                 // process the mouse hover movement...
15561      *                 return true;
15562      *             case MotionEvent.ACTION_SCROLL:
15563      *                 // process the scroll wheel movement...
15564      *                 return true;
15565      *         }
15566      *     }
15567      *     return super.onGenericMotionEvent(event);
15568      * }</pre>
15569      *
15570      * @param event The generic motion event being processed.
15571      * @return True if the event was handled, false otherwise.
15572      */
onGenericMotionEvent(MotionEvent event)15573     public boolean onGenericMotionEvent(MotionEvent event) {
15574         return false;
15575     }
15576 
15577     /**
15578      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
15579      * <p>
15580      * This method is dispatching hover events to the delegate target to support explore by touch.
15581      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
15582      * the delegate target according to the pointer and the touch area of the delegate while touch
15583      * exploration enabled.
15584      * </p>
15585      *
15586      * @param event The motion event dispatch to the delegate target.
15587      * @return True if the event was handled, false otherwise.
15588      *
15589      * @see #onHoverEvent
15590      */
dispatchTouchExplorationHoverEvent(MotionEvent event)15591     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
15592         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
15593         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
15594             return false;
15595         }
15596 
15597         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
15598         final int action = event.getActionMasked();
15599         boolean pointInDelegateRegion = false;
15600         boolean handled = false;
15601 
15602         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
15603         for (int i = 0; i < info.getRegionCount(); i++) {
15604             Region r = info.getRegionAt(i);
15605             if (r.contains((int) event.getX(), (int) event.getY())) {
15606                 pointInDelegateRegion = true;
15607             }
15608         }
15609 
15610         // Explore by touch should dispatch events to children under the pointer first if any
15611         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
15612         // hover events but receive accessibility focus, it should also not delegate to these
15613         // views when hovered.
15614         if (!oldHoveringTouchDelegate) {
15615             if ((action == MotionEvent.ACTION_HOVER_ENTER
15616                     || action == MotionEvent.ACTION_HOVER_MOVE)
15617                     && !pointInHoveredChild(event)
15618                     && pointInDelegateRegion) {
15619                 mHoveringTouchDelegate = true;
15620             }
15621         } else {
15622             if (action == MotionEvent.ACTION_HOVER_EXIT
15623                     || (action == MotionEvent.ACTION_HOVER_MOVE
15624                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
15625                 mHoveringTouchDelegate = false;
15626             }
15627         }
15628         switch (action) {
15629             case MotionEvent.ACTION_HOVER_MOVE:
15630                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15631                     // Inside bounds, dispatch as is.
15632                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
15633                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15634                     // Moving inbound, synthesize hover enter.
15635                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
15636                             ? event : MotionEvent.obtainNoHistory(event);
15637                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
15638                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15639                     eventNoHistory.setAction(action);
15640                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15641                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
15642                     // Moving outbound, synthesize hover exit.
15643                     final boolean hoverExitPending = event.isHoverExitPending();
15644                     event.setHoverExitPending(true);
15645                     mTouchDelegate.onTouchExplorationHoverEvent(event);
15646                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
15647                             ? event : MotionEvent.obtainNoHistory(event);
15648                     eventNoHistory.setHoverExitPending(hoverExitPending);
15649                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
15650                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15651                 }  // else: outside bounds, do nothing.
15652                 break;
15653             case MotionEvent.ACTION_HOVER_ENTER:
15654                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15655                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
15656                 }
15657                 break;
15658             case MotionEvent.ACTION_HOVER_EXIT:
15659                 if (oldHoveringTouchDelegate) {
15660                     mTouchDelegate.onTouchExplorationHoverEvent(event);
15661                 }
15662                 break;
15663         }
15664         return handled;
15665     }
15666 
15667     /**
15668      * Implement this method to handle hover events.
15669      * <p>
15670      * This method is called whenever a pointer is hovering into, over, or out of the
15671      * bounds of a view and the view is not currently being touched.
15672      * Hover events are represented as pointer events with action
15673      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
15674      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
15675      * </p>
15676      * <ul>
15677      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
15678      * when the pointer enters the bounds of the view.</li>
15679      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
15680      * when the pointer has already entered the bounds of the view and has moved.</li>
15681      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
15682      * when the pointer has exited the bounds of the view or when the pointer is
15683      * about to go down due to a button click, tap, or similar user action that
15684      * causes the view to be touched.</li>
15685      * </ul>
15686      * <p>
15687      * The view should implement this method to return true to indicate that it is
15688      * handling the hover event, such as by changing its drawable state.
15689      * </p><p>
15690      * The default implementation calls {@link #setHovered} to update the hovered state
15691      * of the view when a hover enter or hover exit event is received, if the view
15692      * is enabled and is clickable.  The default implementation also sends hover
15693      * accessibility events.
15694      * </p>
15695      *
15696      * @param event The motion event that describes the hover.
15697      * @return True if the view handled the hover event.
15698      *
15699      * @see #isHovered
15700      * @see #setHovered
15701      * @see #onHoverChanged
15702      */
onHoverEvent(MotionEvent event)15703     public boolean onHoverEvent(MotionEvent event) {
15704         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
15705             return true;
15706         }
15707 
15708         // The root view may receive hover (or touch) events that are outside the bounds of
15709         // the window.  This code ensures that we only send accessibility events for
15710         // hovers that are actually within the bounds of the root view.
15711         final int action = event.getActionMasked();
15712         if (!mSendingHoverAccessibilityEvents) {
15713             if ((action == MotionEvent.ACTION_HOVER_ENTER
15714                     || action == MotionEvent.ACTION_HOVER_MOVE)
15715                     && !hasHoveredChild()
15716                     && pointInView(event.getX(), event.getY())) {
15717                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
15718                 mSendingHoverAccessibilityEvents = true;
15719             }
15720         } else {
15721             if (action == MotionEvent.ACTION_HOVER_EXIT
15722                     || (action == MotionEvent.ACTION_HOVER_MOVE
15723                             && !pointInView(event.getX(), event.getY()))) {
15724                 mSendingHoverAccessibilityEvents = false;
15725                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
15726             }
15727         }
15728 
15729         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
15730                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
15731                 && isOnScrollbar(event.getX(), event.getY())) {
15732             awakenScrollBars();
15733         }
15734 
15735         // If we consider ourself hoverable, or if we we're already hovered,
15736         // handle changing state in response to ENTER and EXIT events.
15737         if (isHoverable() || isHovered()) {
15738             switch (action) {
15739                 case MotionEvent.ACTION_HOVER_ENTER:
15740                     setHovered(true);
15741                     break;
15742                 case MotionEvent.ACTION_HOVER_EXIT:
15743                     setHovered(false);
15744                     break;
15745             }
15746 
15747             // Dispatch the event to onGenericMotionEvent before returning true.
15748             // This is to provide compatibility with existing applications that
15749             // handled HOVER_MOVE events in onGenericMotionEvent and that would
15750             // break because of the new default handling for hoverable views
15751             // in onHoverEvent.
15752             // Note that onGenericMotionEvent will be called by default when
15753             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
15754             dispatchGenericMotionEventInternal(event);
15755             // The event was already handled by calling setHovered(), so always
15756             // return true.
15757             return true;
15758         }
15759 
15760         return false;
15761     }
15762 
15763     /**
15764      * Returns true if the view should handle {@link #onHoverEvent}
15765      * by calling {@link #setHovered} to change its hovered state.
15766      *
15767      * @return True if the view is hoverable.
15768      */
isHoverable()15769     private boolean isHoverable() {
15770         final int viewFlags = mViewFlags;
15771         if ((viewFlags & ENABLED_MASK) == DISABLED) {
15772             return false;
15773         }
15774 
15775         return (viewFlags & CLICKABLE) == CLICKABLE
15776                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
15777                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15778     }
15779 
15780     /**
15781      * Returns true if the view is currently hovered.
15782      *
15783      * @return True if the view is currently hovered.
15784      *
15785      * @see #setHovered
15786      * @see #onHoverChanged
15787      */
15788     @ViewDebug.ExportedProperty
isHovered()15789     public boolean isHovered() {
15790         return (mPrivateFlags & PFLAG_HOVERED) != 0;
15791     }
15792 
15793     /**
15794      * Sets whether the view is currently hovered.
15795      * <p>
15796      * Calling this method also changes the drawable state of the view.  This
15797      * enables the view to react to hover by using different drawable resources
15798      * to change its appearance.
15799      * </p><p>
15800      * The {@link #onHoverChanged} method is called when the hovered state changes.
15801      * </p>
15802      *
15803      * @param hovered True if the view is hovered.
15804      *
15805      * @see #isHovered
15806      * @see #onHoverChanged
15807      */
setHovered(boolean hovered)15808     public void setHovered(boolean hovered) {
15809         if (hovered) {
15810             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
15811                 mPrivateFlags |= PFLAG_HOVERED;
15812                 refreshDrawableState();
15813                 onHoverChanged(true);
15814             }
15815         } else {
15816             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
15817                 mPrivateFlags &= ~PFLAG_HOVERED;
15818                 refreshDrawableState();
15819                 onHoverChanged(false);
15820             }
15821         }
15822     }
15823 
15824     /**
15825      * Implement this method to handle hover state changes.
15826      * <p>
15827      * This method is called whenever the hover state changes as a result of a
15828      * call to {@link #setHovered}.
15829      * </p>
15830      *
15831      * @param hovered The current hover state, as returned by {@link #isHovered}.
15832      *
15833      * @see #isHovered
15834      * @see #setHovered
15835      */
onHoverChanged(boolean hovered)15836     public void onHoverChanged(boolean hovered) {
15837     }
15838 
15839     /**
15840      * Handles scroll bar dragging by mouse input.
15841      *
15842      * @hide
15843      * @param event The motion event.
15844      *
15845      * @return true if the event was handled as a scroll bar dragging, false otherwise.
15846      */
handleScrollBarDragging(MotionEvent event)15847     protected boolean handleScrollBarDragging(MotionEvent event) {
15848         if (mScrollCache == null) {
15849             return false;
15850         }
15851         final float x = event.getX();
15852         final float y = event.getY();
15853         final int action = event.getAction();
15854         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
15855                 && action != MotionEvent.ACTION_DOWN)
15856                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
15857                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
15858             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15859             return false;
15860         }
15861 
15862         switch (action) {
15863             case MotionEvent.ACTION_MOVE:
15864                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
15865                     return false;
15866                 }
15867                 if (mScrollCache.mScrollBarDraggingState
15868                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
15869                     final Rect bounds = mScrollCache.mScrollBarBounds;
15870                     getVerticalScrollBarBounds(bounds, null);
15871                     final int range = computeVerticalScrollRange();
15872                     final int offset = computeVerticalScrollOffset();
15873                     final int extent = computeVerticalScrollExtent();
15874 
15875                     final int thumbLength = ScrollBarUtils.getThumbLength(
15876                             bounds.height(), bounds.width(), extent, range);
15877                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15878                             bounds.height(), thumbLength, extent, range, offset);
15879 
15880                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
15881                     final float maxThumbOffset = bounds.height() - thumbLength;
15882                     final float newThumbOffset =
15883                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15884                     final int height = getHeight();
15885                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15886                             && height > 0 && extent > 0) {
15887                         final int newY = Math.round((range - extent)
15888                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
15889                         if (newY != getScrollY()) {
15890                             mScrollCache.mScrollBarDraggingPos = y;
15891                             setScrollY(newY);
15892                         }
15893                     }
15894                     return true;
15895                 }
15896                 if (mScrollCache.mScrollBarDraggingState
15897                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
15898                     final Rect bounds = mScrollCache.mScrollBarBounds;
15899                     getHorizontalScrollBarBounds(bounds, null);
15900                     final int range = computeHorizontalScrollRange();
15901                     final int offset = computeHorizontalScrollOffset();
15902                     final int extent = computeHorizontalScrollExtent();
15903 
15904                     final int thumbLength = ScrollBarUtils.getThumbLength(
15905                             bounds.width(), bounds.height(), extent, range);
15906                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15907                             bounds.width(), thumbLength, extent, range, offset);
15908 
15909                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
15910                     final float maxThumbOffset = bounds.width() - thumbLength;
15911                     final float newThumbOffset =
15912                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15913                     final int width = getWidth();
15914                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15915                             && width > 0 && extent > 0) {
15916                         final int newX = Math.round((range - extent)
15917                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
15918                         if (newX != getScrollX()) {
15919                             mScrollCache.mScrollBarDraggingPos = x;
15920                             setScrollX(newX);
15921                         }
15922                     }
15923                     return true;
15924                 }
15925             case MotionEvent.ACTION_DOWN:
15926                 if (mScrollCache.state == ScrollabilityCache.OFF) {
15927                     return false;
15928                 }
15929                 if (isOnVerticalScrollbarThumb(x, y)) {
15930                     mScrollCache.mScrollBarDraggingState =
15931                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
15932                     mScrollCache.mScrollBarDraggingPos = y;
15933                     return true;
15934                 }
15935                 if (isOnHorizontalScrollbarThumb(x, y)) {
15936                     mScrollCache.mScrollBarDraggingState =
15937                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
15938                     mScrollCache.mScrollBarDraggingPos = x;
15939                     return true;
15940                 }
15941         }
15942         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15943         return false;
15944     }
15945 
15946     /**
15947      * Implement this method to handle touch screen motion events.
15948      * <p>
15949      * If this method is used to detect click actions, it is recommended that
15950      * the actions be performed by implementing and calling
15951      * {@link #performClick()}. This will ensure consistent system behavior,
15952      * including:
15953      * <ul>
15954      * <li>obeying click sound preferences
15955      * <li>dispatching OnClickListener calls
15956      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
15957      * accessibility features are enabled
15958      * </ul>
15959      *
15960      * @param event The motion event.
15961      * @return True if the event was handled, false otherwise.
15962      */
onTouchEvent(MotionEvent event)15963     public boolean onTouchEvent(MotionEvent event) {
15964         final float x = event.getX();
15965         final float y = event.getY();
15966         final int viewFlags = mViewFlags;
15967         final int action = event.getAction();
15968 
15969         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
15970                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
15971                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15972 
15973         if ((viewFlags & ENABLED_MASK) == DISABLED
15974                 && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
15975             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
15976                 setPressed(false);
15977             }
15978             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15979             // A disabled view that is clickable still consumes the touch
15980             // events, it just doesn't respond to them.
15981             return clickable;
15982         }
15983         if (mTouchDelegate != null) {
15984             if (mTouchDelegate.onTouchEvent(event)) {
15985                 return true;
15986             }
15987         }
15988 
15989         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
15990             switch (action) {
15991                 case MotionEvent.ACTION_UP:
15992                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15993                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
15994                         handleTooltipUp();
15995                     }
15996                     if (!clickable) {
15997                         removeTapCallback();
15998                         removeLongPressCallback();
15999                         mInContextButtonPress = false;
16000                         mHasPerformedLongPress = false;
16001                         mIgnoreNextUpEvent = false;
16002                         break;
16003                     }
16004                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
16005                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
16006                         // take focus if we don't have it already and we should in
16007                         // touch mode.
16008                         boolean focusTaken = false;
16009                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
16010                             focusTaken = requestFocus();
16011                         }
16012 
16013                         if (prepressed) {
16014                             // The button is being released before we actually
16015                             // showed it as pressed.  Make it show the pressed
16016                             // state now (before scheduling the click) to ensure
16017                             // the user sees it.
16018                             setPressed(true, x, y);
16019                         }
16020 
16021                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
16022                             // This is a tap, so remove the longpress check
16023                             removeLongPressCallback();
16024 
16025                             // Only perform take click actions if we were in the pressed state
16026                             if (!focusTaken) {
16027                                 // Use a Runnable and post this rather than calling
16028                                 // performClick directly. This lets other visual state
16029                                 // of the view update before click actions start.
16030                                 if (mPerformClick == null) {
16031                                     mPerformClick = new PerformClick();
16032                                 }
16033                                 if (!post(mPerformClick)) {
16034                                     performClickInternal();
16035                                 }
16036                             }
16037                         }
16038 
16039                         if (mUnsetPressedState == null) {
16040                             mUnsetPressedState = new UnsetPressedState();
16041                         }
16042 
16043                         if (prepressed) {
16044                             postDelayed(mUnsetPressedState,
16045                                     ViewConfiguration.getPressedStateDuration());
16046                         } else if (!post(mUnsetPressedState)) {
16047                             // If the post failed, unpress right now
16048                             mUnsetPressedState.run();
16049                         }
16050 
16051                         removeTapCallback();
16052                     }
16053                     mIgnoreNextUpEvent = false;
16054                     break;
16055 
16056                 case MotionEvent.ACTION_DOWN:
16057                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
16058                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
16059                     }
16060                     mHasPerformedLongPress = false;
16061 
16062                     if (!clickable) {
16063                         checkForLongClick(
16064                                 ViewConfiguration.getLongPressTimeout(),
16065                                 x,
16066                                 y,
16067                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16068                         break;
16069                     }
16070 
16071                     if (performButtonActionOnTouchDown(event)) {
16072                         break;
16073                     }
16074 
16075                     // Walk up the hierarchy to determine if we're inside a scrolling container.
16076                     boolean isInScrollingContainer = isInScrollingContainer();
16077 
16078                     // For views inside a scrolling container, delay the pressed feedback for
16079                     // a short period in case this is a scroll.
16080                     if (isInScrollingContainer) {
16081                         mPrivateFlags |= PFLAG_PREPRESSED;
16082                         if (mPendingCheckForTap == null) {
16083                             mPendingCheckForTap = new CheckForTap();
16084                         }
16085                         mPendingCheckForTap.x = event.getX();
16086                         mPendingCheckForTap.y = event.getY();
16087                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
16088                     } else {
16089                         // Not inside a scrolling container, so show the feedback right away
16090                         setPressed(true, x, y);
16091                         checkForLongClick(
16092                                 ViewConfiguration.getLongPressTimeout(),
16093                                 x,
16094                                 y,
16095                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16096                     }
16097                     break;
16098 
16099                 case MotionEvent.ACTION_CANCEL:
16100                     if (clickable) {
16101                         setPressed(false);
16102                     }
16103                     removeTapCallback();
16104                     removeLongPressCallback();
16105                     mInContextButtonPress = false;
16106                     mHasPerformedLongPress = false;
16107                     mIgnoreNextUpEvent = false;
16108                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16109                     break;
16110 
16111                 case MotionEvent.ACTION_MOVE:
16112                     if (clickable) {
16113                         drawableHotspotChanged(x, y);
16114                     }
16115 
16116                     final int motionClassification = event.getClassification();
16117                     final boolean ambiguousGesture =
16118                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
16119                     int touchSlop = mTouchSlop;
16120                     if (ambiguousGesture && hasPendingLongPressCallback()) {
16121                         if (!pointInView(x, y, touchSlop)) {
16122                             // The default action here is to cancel long press. But instead, we
16123                             // just extend the timeout here, in case the classification
16124                             // stays ambiguous.
16125                             removeLongPressCallback();
16126                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
16127                                     * mAmbiguousGestureMultiplier);
16128                             // Subtract the time already spent
16129                             delay -= event.getEventTime() - event.getDownTime();
16130                             checkForLongClick(
16131                                     delay,
16132                                     x,
16133                                     y,
16134                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16135                         }
16136                         touchSlop *= mAmbiguousGestureMultiplier;
16137                     }
16138 
16139                     // Be lenient about moving outside of buttons
16140                     if (!pointInView(x, y, touchSlop)) {
16141                         // Outside button
16142                         // Remove any future long press/tap checks
16143                         removeTapCallback();
16144                         removeLongPressCallback();
16145                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
16146                             setPressed(false);
16147                         }
16148                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16149                     }
16150 
16151                     final boolean deepPress =
16152                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
16153                     if (deepPress && hasPendingLongPressCallback()) {
16154                         // process the long click action immediately
16155                         removeLongPressCallback();
16156                         checkForLongClick(
16157                                 0 /* send immediately */,
16158                                 x,
16159                                 y,
16160                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
16161                     }
16162 
16163                     break;
16164             }
16165 
16166             return true;
16167         }
16168 
16169         return false;
16170     }
16171 
16172     /**
16173      * @hide
16174      */
16175     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInScrollingContainer()16176     public boolean isInScrollingContainer() {
16177         ViewParent p = getParent();
16178         while (p != null && p instanceof ViewGroup) {
16179             if (((ViewGroup) p).shouldDelayChildPressedState()) {
16180                 return true;
16181             }
16182             p = p.getParent();
16183         }
16184         return false;
16185     }
16186 
16187     /**
16188      * Remove the longpress detection timer.
16189      */
removeLongPressCallback()16190     private void removeLongPressCallback() {
16191         if (mPendingCheckForLongPress != null) {
16192             removeCallbacks(mPendingCheckForLongPress);
16193         }
16194     }
16195 
16196     /**
16197      * Return true if the long press callback is scheduled to run sometime in the future.
16198      * Return false if there is no scheduled long press callback at the moment.
16199      */
hasPendingLongPressCallback()16200     private boolean hasPendingLongPressCallback() {
16201         if (mPendingCheckForLongPress == null) {
16202             return false;
16203         }
16204         final AttachInfo attachInfo = mAttachInfo;
16205         if (attachInfo == null) {
16206             return false;
16207         }
16208         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
16209     }
16210 
16211    /**
16212      * Remove the pending click action
16213      */
16214     @UnsupportedAppUsage
removePerformClickCallback()16215     private void removePerformClickCallback() {
16216         if (mPerformClick != null) {
16217             removeCallbacks(mPerformClick);
16218         }
16219     }
16220 
16221     /**
16222      * Remove the prepress detection timer.
16223      */
removeUnsetPressCallback()16224     private void removeUnsetPressCallback() {
16225         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
16226             setPressed(false);
16227             removeCallbacks(mUnsetPressedState);
16228         }
16229     }
16230 
16231     /**
16232      * Remove the tap detection timer.
16233      */
removeTapCallback()16234     private void removeTapCallback() {
16235         if (mPendingCheckForTap != null) {
16236             mPrivateFlags &= ~PFLAG_PREPRESSED;
16237             removeCallbacks(mPendingCheckForTap);
16238         }
16239     }
16240 
16241     /**
16242      * Cancels a pending long press.  Your subclass can use this if you
16243      * want the context menu to come up if the user presses and holds
16244      * at the same place, but you don't want it to come up if they press
16245      * and then move around enough to cause scrolling.
16246      */
cancelLongPress()16247     public void cancelLongPress() {
16248         removeLongPressCallback();
16249 
16250         /*
16251          * The prepressed state handled by the tap callback is a display
16252          * construct, but the tap callback will post a long press callback
16253          * less its own timeout. Remove it here.
16254          */
16255         removeTapCallback();
16256     }
16257 
16258     /**
16259      * Sets the TouchDelegate for this View.
16260      */
setTouchDelegate(TouchDelegate delegate)16261     public void setTouchDelegate(TouchDelegate delegate) {
16262         mTouchDelegate = delegate;
16263     }
16264 
16265     /**
16266      * Gets the TouchDelegate for this View.
16267      */
getTouchDelegate()16268     public TouchDelegate getTouchDelegate() {
16269         return mTouchDelegate;
16270     }
16271 
16272     /**
16273      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
16274      *
16275      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
16276      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
16277      * available. This method should only be called for touch events.
16278      *
16279      * <p class="note">This API is not intended for most applications. Buffered dispatch
16280      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
16281      * streams will not improve your input latency. Side effects include: increased latency,
16282      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
16283      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
16284      * you.</p>
16285      *
16286      * To receive unbuffered events for arbitrary input device source classes, use
16287      * {@link #requestUnbufferedDispatch(int)},
16288      *
16289      * @see View#requestUnbufferedDispatch(int)
16290      */
requestUnbufferedDispatch(MotionEvent event)16291     public final void requestUnbufferedDispatch(MotionEvent event) {
16292         final int action = event.getAction();
16293         if (mAttachInfo == null
16294                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
16295                 || !event.isTouchEvent()) {
16296             return;
16297         }
16298         mAttachInfo.mUnbufferedDispatchRequested = true;
16299     }
16300 
16301     /**
16302      * Request unbuffered dispatch of the given event source class to this view.
16303      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
16304      * automatically terminate, and allows the specification of arbitrary input source classes.
16305      *
16306      * @param source The combined input source class to request unbuffered dispatch for. All
16307      *               events coming from these source classes will not be buffered. Set to
16308      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
16309      *
16310      * @see View#requestUnbufferedDispatch(MotionEvent)
16311      */
requestUnbufferedDispatch(@nputSourceClass int source)16312     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
16313         if (mUnbufferedInputSource == source) {
16314             return;
16315         }
16316         mUnbufferedInputSource = source;
16317         if (mParent != null) {
16318             mParent.onDescendantUnbufferedRequested();
16319         }
16320     }
16321 
hasSize()16322     private boolean hasSize() {
16323         return (mBottom > mTop) && (mRight > mLeft);
16324     }
16325 
canTakeFocus()16326     private boolean canTakeFocus() {
16327         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
16328                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
16329                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
16330                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
16331     }
16332 
16333     /**
16334      * Set flags controlling behavior of this view.
16335      *
16336      * @param flags Constant indicating the value which should be set
16337      * @param mask Constant indicating the bit range that should be changed
16338      */
16339     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)16340     void setFlags(int flags, int mask) {
16341         final boolean accessibilityEnabled =
16342                 AccessibilityManager.getInstance(mContext).isEnabled();
16343         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
16344 
16345         int old = mViewFlags;
16346         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
16347 
16348         int changed = mViewFlags ^ old;
16349         if (changed == 0) {
16350             return;
16351         }
16352         int privateFlags = mPrivateFlags;
16353         boolean shouldNotifyFocusableAvailable = false;
16354 
16355         // If focusable is auto, update the FOCUSABLE bit.
16356         int focusableChangedByAuto = 0;
16357         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
16358                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
16359             // Heuristic only takes into account whether view is clickable.
16360             final int newFocus;
16361             if ((mViewFlags & CLICKABLE) != 0) {
16362                 newFocus = FOCUSABLE;
16363             } else {
16364                 newFocus = NOT_FOCUSABLE;
16365             }
16366             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
16367             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
16368             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
16369         }
16370 
16371         /* Check if the FOCUSABLE bit has changed */
16372         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
16373             if (((old & FOCUSABLE) == FOCUSABLE)
16374                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
16375                 /* Give up focus if we are no longer focusable */
16376                 clearFocus();
16377                 if (mParent instanceof ViewGroup) {
16378                     ((ViewGroup) mParent).clearFocusedInCluster();
16379                 }
16380             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
16381                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
16382                 /*
16383                  * Tell the view system that we are now available to take focus
16384                  * if no one else already has it.
16385                  */
16386                 if (mParent != null) {
16387                     ViewRootImpl viewRootImpl = getViewRootImpl();
16388                     if (!sAutoFocusableOffUIThreadWontNotifyParents
16389                             || focusableChangedByAuto == 0
16390                             || viewRootImpl == null
16391                             || viewRootImpl.mThread == Thread.currentThread()) {
16392                         shouldNotifyFocusableAvailable = canTakeFocus();
16393                     }
16394                 }
16395             }
16396         }
16397 
16398         final int newVisibility = flags & VISIBILITY_MASK;
16399         if (newVisibility == VISIBLE) {
16400             if ((changed & VISIBILITY_MASK) != 0) {
16401                 /*
16402                  * If this view is becoming visible, invalidate it in case it changed while
16403                  * it was not visible. Marking it drawn ensures that the invalidation will
16404                  * go through.
16405                  */
16406                 mPrivateFlags |= PFLAG_DRAWN;
16407                 invalidate(true);
16408 
16409                 needGlobalAttributesUpdate(true);
16410 
16411                 // a view becoming visible is worth notifying the parent about in case nothing has
16412                 // focus. Even if this specific view isn't focusable, it may contain something that
16413                 // is, so let the root view try to give this focus if nothing else does.
16414                 shouldNotifyFocusableAvailable = hasSize();
16415             }
16416         }
16417 
16418         if ((changed & ENABLED_MASK) != 0) {
16419             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
16420                 // a view becoming enabled should notify the parent as long as the view is also
16421                 // visible and the parent wasn't already notified by becoming visible during this
16422                 // setFlags invocation.
16423                 shouldNotifyFocusableAvailable = canTakeFocus();
16424             } else {
16425                 if (isFocused()) clearFocus();
16426             }
16427         }
16428 
16429         if (shouldNotifyFocusableAvailable && mParent != null) {
16430             mParent.focusableViewAvailable(this);
16431         }
16432 
16433         /* Check if the GONE bit has changed */
16434         if ((changed & GONE) != 0) {
16435             needGlobalAttributesUpdate(false);
16436             requestLayout();
16437 
16438             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
16439                 if (hasFocus()) {
16440                     clearFocus();
16441                     if (mParent instanceof ViewGroup) {
16442                         ((ViewGroup) mParent).clearFocusedInCluster();
16443                     }
16444                 }
16445                 clearAccessibilityFocus();
16446                 destroyDrawingCache();
16447                 if (mParent instanceof View) {
16448                     // GONE views noop invalidation, so invalidate the parent
16449                     ((View) mParent).invalidate(true);
16450                 }
16451                 // Mark the view drawn to ensure that it gets invalidated properly the next
16452                 // time it is visible and gets invalidated
16453                 mPrivateFlags |= PFLAG_DRAWN;
16454             }
16455             if (mAttachInfo != null) {
16456                 mAttachInfo.mViewVisibilityChanged = true;
16457             }
16458         }
16459 
16460         /* Check if the VISIBLE bit has changed */
16461         if ((changed & INVISIBLE) != 0) {
16462             needGlobalAttributesUpdate(false);
16463             /*
16464              * If this view is becoming invisible, set the DRAWN flag so that
16465              * the next invalidate() will not be skipped.
16466              */
16467             mPrivateFlags |= PFLAG_DRAWN;
16468 
16469             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
16470                 // root view becoming invisible shouldn't clear focus and accessibility focus
16471                 if (getRootView() != this) {
16472                     if (hasFocus()) {
16473                         clearFocus();
16474                         if (mParent instanceof ViewGroup) {
16475                             ((ViewGroup) mParent).clearFocusedInCluster();
16476                         }
16477                     }
16478                     clearAccessibilityFocus();
16479                 }
16480             }
16481             if (mAttachInfo != null) {
16482                 mAttachInfo.mViewVisibilityChanged = true;
16483             }
16484         }
16485 
16486         if ((changed & VISIBILITY_MASK) != 0) {
16487             // If the view is invisible, cleanup its display list to free up resources
16488             if (newVisibility != VISIBLE && mAttachInfo != null) {
16489                 cleanupDraw();
16490             }
16491 
16492             if (mParent instanceof ViewGroup) {
16493                 ViewGroup parent = (ViewGroup) mParent;
16494                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
16495                         newVisibility);
16496                 parent.invalidate(true);
16497             } else if (mParent != null) {
16498                 mParent.invalidateChild(this, null);
16499             }
16500 
16501             if (mAttachInfo != null) {
16502                 dispatchVisibilityChanged(this, newVisibility);
16503 
16504                 // Aggregated visibility changes are dispatched to attached views
16505                 // in visible windows where the parent is currently shown/drawn
16506                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
16507                 // discounting clipping or overlapping. This makes it a good place
16508                 // to change animation states.
16509                 if (mParent != null && getWindowVisibility() == VISIBLE &&
16510                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
16511                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
16512                 }
16513                 // If this view is invisible from visible, then sending the A11y event by its
16514                 // parent which is shown and has the accessibility important.
16515                 if ((old & VISIBILITY_MASK) == VISIBLE) {
16516                     notifySubtreeAccessibilityStateChangedByParentIfNeeded();
16517                 } else {
16518                     notifySubtreeAccessibilityStateChangedIfNeeded();
16519                 }
16520             }
16521         }
16522 
16523         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
16524             destroyDrawingCache();
16525         }
16526 
16527         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
16528             destroyDrawingCache();
16529             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16530             invalidateParentCaches();
16531         }
16532 
16533         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
16534             destroyDrawingCache();
16535             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16536         }
16537 
16538         if ((changed & DRAW_MASK) != 0) {
16539             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
16540                 if (mBackground != null
16541                         || mDefaultFocusHighlight != null
16542                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
16543                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16544                 } else {
16545                     mPrivateFlags |= PFLAG_SKIP_DRAW;
16546                 }
16547             } else {
16548                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16549             }
16550             requestLayout();
16551             invalidate(true);
16552         }
16553 
16554         if ((changed & KEEP_SCREEN_ON) != 0) {
16555             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16556                 mParent.recomputeViewAttributes(this);
16557             }
16558         }
16559 
16560         if (accessibilityEnabled) {
16561             // If we're an accessibility pane and the visibility changed, we already have sent
16562             // a state change, so we really don't need to report other changes.
16563             if (isAccessibilityPane()) {
16564                 changed &= ~VISIBILITY_MASK;
16565             }
16566             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
16567                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
16568                     || (changed & CONTEXT_CLICKABLE) != 0) {
16569                 if (oldIncludeForAccessibility != includeForAccessibility()) {
16570                     notifySubtreeAccessibilityStateChangedIfNeeded();
16571                 } else {
16572                     notifyViewAccessibilityStateChangedIfNeeded(
16573                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16574                 }
16575             } else if ((changed & ENABLED_MASK) != 0) {
16576                 notifyViewAccessibilityStateChangedIfNeeded(
16577                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16578             }
16579         }
16580     }
16581 
16582     /**
16583      * Change the view's z order in the tree, so it's on top of other sibling
16584      * views. This ordering change may affect layout, if the parent container
16585      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
16586      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
16587      * method should be followed by calls to {@link #requestLayout()} and
16588      * {@link View#invalidate()} on the view's parent to force the parent to redraw
16589      * with the new child ordering.
16590      *
16591      * @see ViewGroup#bringChildToFront(View)
16592      */
bringToFront()16593     public void bringToFront() {
16594         if (mParent != null) {
16595             mParent.bringChildToFront(this);
16596         }
16597     }
16598 
16599     /**
16600      * This is called in response to an internal scroll in this view (i.e., the
16601      * view scrolled its own contents). This is typically as a result of
16602      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
16603      * called.
16604      *
16605      * @param l Current horizontal scroll origin.
16606      * @param t Current vertical scroll origin.
16607      * @param oldl Previous horizontal scroll origin.
16608      * @param oldt Previous vertical scroll origin.
16609      */
onScrollChanged(int l, int t, int oldl, int oldt)16610     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
16611         notifySubtreeAccessibilityStateChangedIfNeeded();
16612         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
16613 
16614         mBackgroundSizeChanged = true;
16615         mDefaultFocusHighlightSizeChanged = true;
16616         if (mForegroundInfo != null) {
16617             mForegroundInfo.mBoundsChanged = true;
16618         }
16619 
16620         final AttachInfo ai = mAttachInfo;
16621         if (ai != null) {
16622             ai.mViewScrollChanged = true;
16623         }
16624 
16625         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
16626             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
16627         }
16628     }
16629 
16630     /**
16631      * Interface definition for a callback to be invoked when the scroll
16632      * X or Y positions of a view change.
16633      * <p>
16634      * <b>Note:</b> Some views handle scrolling independently from View and may
16635      * have their own separate listeners for scroll-type events. For example,
16636      * {@link android.widget.ListView ListView} allows clients to register an
16637      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
16638      * to listen for changes in list scroll position.
16639      *
16640      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
16641      */
16642     public interface OnScrollChangeListener {
16643         /**
16644          * Called when the scroll position of a view changes.
16645          *
16646          * @param v The view whose scroll position has changed.
16647          * @param scrollX Current horizontal scroll origin.
16648          * @param scrollY Current vertical scroll origin.
16649          * @param oldScrollX Previous horizontal scroll origin.
16650          * @param oldScrollY Previous vertical scroll origin.
16651          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)16652         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
16653     }
16654 
16655     /**
16656      * Interface definition for a callback to be invoked when the layout bounds of a view
16657      * changes due to layout processing.
16658      */
16659     public interface OnLayoutChangeListener {
16660         /**
16661          * Called when the layout bounds of a view changes due to layout processing.
16662          *
16663          * @param v The view whose bounds have changed.
16664          * @param left The new value of the view's left property.
16665          * @param top The new value of the view's top property.
16666          * @param right The new value of the view's right property.
16667          * @param bottom The new value of the view's bottom property.
16668          * @param oldLeft The previous value of the view's left property.
16669          * @param oldTop The previous value of the view's top property.
16670          * @param oldRight The previous value of the view's right property.
16671          * @param oldBottom The previous value of the view's bottom property.
16672          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)16673         void onLayoutChange(View v, int left, int top, int right, int bottom,
16674             int oldLeft, int oldTop, int oldRight, int oldBottom);
16675     }
16676 
16677     /**
16678      * This is called during layout when the size of this view has changed. If
16679      * you were just added to the view hierarchy, you're called with the old
16680      * values of 0.
16681      *
16682      * @param w Current width of this view.
16683      * @param h Current height of this view.
16684      * @param oldw Old width of this view.
16685      * @param oldh Old height of this view.
16686      */
onSizeChanged(int w, int h, int oldw, int oldh)16687     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
16688     }
16689 
16690     /**
16691      * Called by draw to draw the child views. This may be overridden
16692      * by derived classes to gain control just before its children are drawn
16693      * (but after its own view has been drawn).
16694      * @param canvas the canvas on which to draw the view
16695      */
dispatchDraw(Canvas canvas)16696     protected void dispatchDraw(Canvas canvas) {
16697 
16698     }
16699 
16700     /**
16701      * Gets the parent of this view. Note that the parent is a
16702      * ViewParent and not necessarily a View.
16703      *
16704      * @return Parent of this view.
16705      */
getParent()16706     public final ViewParent getParent() {
16707         return mParent;
16708     }
16709 
16710     /**
16711      * Set the horizontal scrolled position of your view. This will cause a call to
16712      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16713      * invalidated.
16714      * @param value the x position to scroll to
16715      */
setScrollX(int value)16716     public void setScrollX(int value) {
16717         scrollTo(value, mScrollY);
16718     }
16719 
16720     /**
16721      * Set the vertical scrolled position of your view. This will cause a call to
16722      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16723      * invalidated.
16724      * @param value the y position to scroll to
16725      */
setScrollY(int value)16726     public void setScrollY(int value) {
16727         scrollTo(mScrollX, value);
16728     }
16729 
16730     /**
16731      * Return the scrolled left position of this view. This is the left edge of
16732      * the displayed part of your view. You do not need to draw any pixels
16733      * farther left, since those are outside of the frame of your view on
16734      * screen.
16735      *
16736      * @return The left edge of the displayed part of your view, in pixels.
16737      */
16738     @InspectableProperty
getScrollX()16739     public final int getScrollX() {
16740         return mScrollX;
16741     }
16742 
16743     /**
16744      * Return the scrolled top position of this view. This is the top edge of
16745      * the displayed part of your view. You do not need to draw any pixels above
16746      * it, since those are outside of the frame of your view on screen.
16747      *
16748      * @return The top edge of the displayed part of your view, in pixels.
16749      */
16750     @InspectableProperty
getScrollY()16751     public final int getScrollY() {
16752         return mScrollY;
16753     }
16754 
16755     /**
16756      * Return the width of your view.
16757      *
16758      * @return The width of your view, in pixels.
16759      */
16760     @ViewDebug.ExportedProperty(category = "layout")
getWidth()16761     public final int getWidth() {
16762         return mRight - mLeft;
16763     }
16764 
16765     /**
16766      * Return the height of your view.
16767      *
16768      * @return The height of your view, in pixels.
16769      */
16770     @ViewDebug.ExportedProperty(category = "layout")
getHeight()16771     public final int getHeight() {
16772         return mBottom - mTop;
16773     }
16774 
16775     /**
16776      * Return the visible drawing bounds of your view. Fills in the output
16777      * rectangle with the values from getScrollX(), getScrollY(),
16778      * getWidth(), and getHeight(). These bounds do not account for any
16779      * transformation properties currently set on the view, such as
16780      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
16781      *
16782      * @param outRect The (scrolled) drawing bounds of the view.
16783      */
getDrawingRect(Rect outRect)16784     public void getDrawingRect(Rect outRect) {
16785         outRect.left = mScrollX;
16786         outRect.top = mScrollY;
16787         outRect.right = mScrollX + (mRight - mLeft);
16788         outRect.bottom = mScrollY + (mBottom - mTop);
16789     }
16790 
16791     /**
16792      * Like {@link #getMeasuredWidthAndState()}, but only returns the
16793      * raw width component (that is the result is masked by
16794      * {@link #MEASURED_SIZE_MASK}).
16795      *
16796      * @return The raw measured width of this view.
16797      */
getMeasuredWidth()16798     public final int getMeasuredWidth() {
16799         return mMeasuredWidth & MEASURED_SIZE_MASK;
16800     }
16801 
16802     /**
16803      * Return the full width measurement information for this view as computed
16804      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16805      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16806      * This should be used during measurement and layout calculations only. Use
16807      * {@link #getWidth()} to see how wide a view is after layout.
16808      *
16809      * @return The measured width of this view as a bit mask.
16810      */
16811     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16812             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16813                     name = "MEASURED_STATE_TOO_SMALL"),
16814     })
getMeasuredWidthAndState()16815     public final int getMeasuredWidthAndState() {
16816         return mMeasuredWidth;
16817     }
16818 
16819     /**
16820      * Like {@link #getMeasuredHeightAndState()}, but only returns the
16821      * raw height component (that is the result is masked by
16822      * {@link #MEASURED_SIZE_MASK}).
16823      *
16824      * @return The raw measured height of this view.
16825      */
getMeasuredHeight()16826     public final int getMeasuredHeight() {
16827         return mMeasuredHeight & MEASURED_SIZE_MASK;
16828     }
16829 
16830     /**
16831      * Return the full height measurement information for this view as computed
16832      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16833      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16834      * This should be used during measurement and layout calculations only. Use
16835      * {@link #getHeight()} to see how high a view is after layout.
16836      *
16837      * @return The measured height of this view as a bit mask.
16838      */
16839     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16840             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16841                     name = "MEASURED_STATE_TOO_SMALL"),
16842     })
getMeasuredHeightAndState()16843     public final int getMeasuredHeightAndState() {
16844         return mMeasuredHeight;
16845     }
16846 
16847     /**
16848      * Return only the state bits of {@link #getMeasuredWidthAndState()}
16849      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
16850      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
16851      * and the height component is at the shifted bits
16852      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
16853      */
getMeasuredState()16854     public final int getMeasuredState() {
16855         return (mMeasuredWidth&MEASURED_STATE_MASK)
16856                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
16857                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
16858     }
16859 
16860     /**
16861      * The transform matrix of this view, which is calculated based on the current
16862      * rotation, scale, and pivot properties.
16863      *
16864      * @see #getRotation()
16865      * @see #getScaleX()
16866      * @see #getScaleY()
16867      * @see #getPivotX()
16868      * @see #getPivotY()
16869      * @return The current transform matrix for the view
16870      */
getMatrix()16871     public Matrix getMatrix() {
16872         ensureTransformationInfo();
16873         final Matrix matrix = mTransformationInfo.mMatrix;
16874         mRenderNode.getMatrix(matrix);
16875         return matrix;
16876     }
16877 
16878     /**
16879      * Returns true if the transform matrix is the identity matrix.
16880      * Recomputes the matrix if necessary.
16881      *
16882      * @return True if the transform matrix is the identity matrix, false otherwise.
16883      * @hide
16884      */
16885     @UnsupportedAppUsage
hasIdentityMatrix()16886     public final boolean hasIdentityMatrix() {
16887         return mRenderNode.hasIdentityMatrix();
16888     }
16889 
16890     @UnsupportedAppUsage
ensureTransformationInfo()16891     void ensureTransformationInfo() {
16892         if (mTransformationInfo == null) {
16893             mTransformationInfo = new TransformationInfo();
16894         }
16895     }
16896 
16897     /**
16898      * Utility method to retrieve the inverse of the current mMatrix property.
16899      * We cache the matrix to avoid recalculating it when transform properties
16900      * have not changed.
16901      *
16902      * @return The inverse of the current matrix of this view.
16903      * @hide
16904      */
16905     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getInverseMatrix()16906     public final Matrix getInverseMatrix() {
16907         ensureTransformationInfo();
16908         if (mTransformationInfo.mInverseMatrix == null) {
16909             mTransformationInfo.mInverseMatrix = new Matrix();
16910         }
16911         final Matrix matrix = mTransformationInfo.mInverseMatrix;
16912         mRenderNode.getInverseMatrix(matrix);
16913         return matrix;
16914     }
16915 
16916     /**
16917      * Gets the distance along the Z axis from the camera to this view.
16918      *
16919      * @see #setCameraDistance(float)
16920      *
16921      * @return The distance along the Z axis.
16922      */
getCameraDistance()16923     public float getCameraDistance() {
16924         final float dpi = mResources.getDisplayMetrics().densityDpi;
16925         return mRenderNode.getCameraDistance() * dpi;
16926     }
16927 
16928     /**
16929      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
16930      * views are drawn) from the camera to this view. The camera's distance
16931      * affects 3D transformations, for instance rotations around the X and Y
16932      * axis. If the rotationX or rotationY properties are changed and this view is
16933      * large (more than half the size of the screen), it is recommended to always
16934      * use a camera distance that's greater than the height (X axis rotation) or
16935      * the width (Y axis rotation) of this view.</p>
16936      *
16937      * <p>The distance of the camera from the view plane can have an affect on the
16938      * perspective distortion of the view when it is rotated around the x or y axis.
16939      * For example, a large distance will result in a large viewing angle, and there
16940      * will not be much perspective distortion of the view as it rotates. A short
16941      * distance may cause much more perspective distortion upon rotation, and can
16942      * also result in some drawing artifacts if the rotated view ends up partially
16943      * behind the camera (which is why the recommendation is to use a distance at
16944      * least as far as the size of the view, if the view is to be rotated.)</p>
16945      *
16946      * <p>The distance is expressed in "depth pixels." The default distance depends
16947      * on the screen density. For instance, on a medium density display, the
16948      * default distance is 1280. On a high density display, the default distance
16949      * is 1920.</p>
16950      *
16951      * <p>If you want to specify a distance that leads to visually consistent
16952      * results across various densities, use the following formula:</p>
16953      * <pre>
16954      * float scale = context.getResources().getDisplayMetrics().density;
16955      * view.setCameraDistance(distance * scale);
16956      * </pre>
16957      *
16958      * <p>The density scale factor of a high density display is 1.5,
16959      * and 1920 = 1280 * 1.5.</p>
16960      *
16961      * @param distance The distance in "depth pixels", if negative the opposite
16962      *        value is used
16963      *
16964      * @see #setRotationX(float)
16965      * @see #setRotationY(float)
16966      */
setCameraDistance(float distance)16967     public void setCameraDistance(float distance) {
16968         final float dpi = mResources.getDisplayMetrics().densityDpi;
16969 
16970         invalidateViewProperty(true, false);
16971         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
16972         invalidateViewProperty(false, false);
16973 
16974         invalidateParentIfNeededAndWasQuickRejected();
16975     }
16976 
16977     /**
16978      * The degrees that the view is rotated around the pivot point.
16979      *
16980      * @see #setRotation(float)
16981      * @see #getPivotX()
16982      * @see #getPivotY()
16983      *
16984      * @return The degrees of rotation.
16985      */
16986     @ViewDebug.ExportedProperty(category = "drawing")
16987     @InspectableProperty
getRotation()16988     public float getRotation() {
16989         return mRenderNode.getRotationZ();
16990     }
16991 
16992     /**
16993      * Sets the degrees that the view is rotated around the pivot point. Increasing values
16994      * result in clockwise rotation.
16995      *
16996      * @param rotation The degrees of rotation.
16997      *
16998      * @see #getRotation()
16999      * @see #getPivotX()
17000      * @see #getPivotY()
17001      * @see #setRotationX(float)
17002      * @see #setRotationY(float)
17003      *
17004      * @attr ref android.R.styleable#View_rotation
17005      */
17006     @RemotableViewMethod
setRotation(float rotation)17007     public void setRotation(float rotation) {
17008         if (rotation != getRotation()) {
17009             // Double-invalidation is necessary to capture view's old and new areas
17010             invalidateViewProperty(true, false);
17011             mRenderNode.setRotationZ(rotation);
17012             invalidateViewProperty(false, true);
17013 
17014             invalidateParentIfNeededAndWasQuickRejected();
17015             notifySubtreeAccessibilityStateChangedIfNeeded();
17016         }
17017     }
17018 
17019     /**
17020      * The degrees that the view is rotated around the vertical axis through the pivot point.
17021      *
17022      * @see #getPivotX()
17023      * @see #getPivotY()
17024      * @see #setRotationY(float)
17025      *
17026      * @return The degrees of Y rotation.
17027      */
17028     @ViewDebug.ExportedProperty(category = "drawing")
17029     @InspectableProperty
getRotationY()17030     public float getRotationY() {
17031         return mRenderNode.getRotationY();
17032     }
17033 
17034     /**
17035      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
17036      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
17037      * down the y axis.
17038      *
17039      * When rotating large views, it is recommended to adjust the camera distance
17040      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
17041      *
17042      * @param rotationY The degrees of Y rotation.
17043      *
17044      * @see #getRotationY()
17045      * @see #getPivotX()
17046      * @see #getPivotY()
17047      * @see #setRotation(float)
17048      * @see #setRotationX(float)
17049      * @see #setCameraDistance(float)
17050      *
17051      * @attr ref android.R.styleable#View_rotationY
17052      */
17053     @RemotableViewMethod
setRotationY(float rotationY)17054     public void setRotationY(float rotationY) {
17055         if (rotationY != getRotationY()) {
17056             invalidateViewProperty(true, false);
17057             mRenderNode.setRotationY(rotationY);
17058             invalidateViewProperty(false, true);
17059 
17060             invalidateParentIfNeededAndWasQuickRejected();
17061             notifySubtreeAccessibilityStateChangedIfNeeded();
17062         }
17063     }
17064 
17065     /**
17066      * The degrees that the view is rotated around the horizontal axis through the pivot point.
17067      *
17068      * @see #getPivotX()
17069      * @see #getPivotY()
17070      * @see #setRotationX(float)
17071      *
17072      * @return The degrees of X rotation.
17073      */
17074     @ViewDebug.ExportedProperty(category = "drawing")
17075     @InspectableProperty
getRotationX()17076     public float getRotationX() {
17077         return mRenderNode.getRotationX();
17078     }
17079 
17080     /**
17081      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
17082      * Increasing values result in clockwise rotation from the viewpoint of looking down the
17083      * x axis.
17084      *
17085      * When rotating large views, it is recommended to adjust the camera distance
17086      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
17087      *
17088      * @param rotationX The degrees of X rotation.
17089      *
17090      * @see #getRotationX()
17091      * @see #getPivotX()
17092      * @see #getPivotY()
17093      * @see #setRotation(float)
17094      * @see #setRotationY(float)
17095      * @see #setCameraDistance(float)
17096      *
17097      * @attr ref android.R.styleable#View_rotationX
17098      */
17099     @RemotableViewMethod
setRotationX(float rotationX)17100     public void setRotationX(float rotationX) {
17101         if (rotationX != getRotationX()) {
17102             invalidateViewProperty(true, false);
17103             mRenderNode.setRotationX(rotationX);
17104             invalidateViewProperty(false, true);
17105 
17106             invalidateParentIfNeededAndWasQuickRejected();
17107             notifySubtreeAccessibilityStateChangedIfNeeded();
17108         }
17109     }
17110 
17111     /**
17112      * The amount that the view is scaled in x around the pivot point, as a proportion of
17113      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
17114      *
17115      * <p>By default, this is 1.0f.
17116      *
17117      * @see #getPivotX()
17118      * @see #getPivotY()
17119      * @return The scaling factor.
17120      */
17121     @ViewDebug.ExportedProperty(category = "drawing")
17122     @InspectableProperty
getScaleX()17123     public float getScaleX() {
17124         return mRenderNode.getScaleX();
17125     }
17126 
17127     /**
17128      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
17129      * the view's unscaled width. A value of 1 means that no scaling is applied.
17130      *
17131      * @param scaleX The scaling factor.
17132      * @see #getPivotX()
17133      * @see #getPivotY()
17134      *
17135      * @attr ref android.R.styleable#View_scaleX
17136      */
17137     @RemotableViewMethod
setScaleX(float scaleX)17138     public void setScaleX(float scaleX) {
17139         if (scaleX != getScaleX()) {
17140             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
17141             invalidateViewProperty(true, false);
17142             mRenderNode.setScaleX(scaleX);
17143             invalidateViewProperty(false, true);
17144 
17145             invalidateParentIfNeededAndWasQuickRejected();
17146             notifySubtreeAccessibilityStateChangedIfNeeded();
17147         }
17148     }
17149 
17150     /**
17151      * The amount that the view is scaled in y around the pivot point, as a proportion of
17152      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
17153      *
17154      * <p>By default, this is 1.0f.
17155      *
17156      * @see #getPivotX()
17157      * @see #getPivotY()
17158      * @return The scaling factor.
17159      */
17160     @ViewDebug.ExportedProperty(category = "drawing")
17161     @InspectableProperty
getScaleY()17162     public float getScaleY() {
17163         return mRenderNode.getScaleY();
17164     }
17165 
17166     /**
17167      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
17168      * the view's unscaled width. A value of 1 means that no scaling is applied.
17169      *
17170      * @param scaleY The scaling factor.
17171      * @see #getPivotX()
17172      * @see #getPivotY()
17173      *
17174      * @attr ref android.R.styleable#View_scaleY
17175      */
17176     @RemotableViewMethod
setScaleY(float scaleY)17177     public void setScaleY(float scaleY) {
17178         if (scaleY != getScaleY()) {
17179             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
17180             invalidateViewProperty(true, false);
17181             mRenderNode.setScaleY(scaleY);
17182             invalidateViewProperty(false, true);
17183 
17184             invalidateParentIfNeededAndWasQuickRejected();
17185             notifySubtreeAccessibilityStateChangedIfNeeded();
17186         }
17187     }
17188 
17189     /**
17190      * The x location of the point around which the view is {@link #setRotation(float) rotated}
17191      * and {@link #setScaleX(float) scaled}.
17192      *
17193      * @see #getRotation()
17194      * @see #getScaleX()
17195      * @see #getScaleY()
17196      * @see #getPivotY()
17197      * @return The x location of the pivot point.
17198      *
17199      * @attr ref android.R.styleable#View_transformPivotX
17200      */
17201     @ViewDebug.ExportedProperty(category = "drawing")
17202     @InspectableProperty(name = "transformPivotX")
getPivotX()17203     public float getPivotX() {
17204         return mRenderNode.getPivotX();
17205     }
17206 
17207     /**
17208      * Sets the x location of the point around which the view is
17209      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
17210      * By default, the pivot point is centered on the object.
17211      * Setting this property disables this behavior and causes the view to use only the
17212      * explicitly set pivotX and pivotY values.
17213      *
17214      * @param pivotX The x location of the pivot point.
17215      * @see #getRotation()
17216      * @see #getScaleX()
17217      * @see #getScaleY()
17218      * @see #getPivotY()
17219      *
17220      * @attr ref android.R.styleable#View_transformPivotX
17221      */
17222     @RemotableViewMethod
setPivotX(float pivotX)17223     public void setPivotX(float pivotX) {
17224         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
17225             invalidateViewProperty(true, false);
17226             mRenderNode.setPivotX(pivotX);
17227             invalidateViewProperty(false, true);
17228 
17229             invalidateParentIfNeededAndWasQuickRejected();
17230         }
17231     }
17232 
17233     /**
17234      * The y location of the point around which the view is {@link #setRotation(float) rotated}
17235      * and {@link #setScaleY(float) scaled}.
17236      *
17237      * @see #getRotation()
17238      * @see #getScaleX()
17239      * @see #getScaleY()
17240      * @see #getPivotY()
17241      * @return The y location of the pivot point.
17242      *
17243      * @attr ref android.R.styleable#View_transformPivotY
17244      */
17245     @ViewDebug.ExportedProperty(category = "drawing")
17246     @InspectableProperty(name = "transformPivotY")
getPivotY()17247     public float getPivotY() {
17248         return mRenderNode.getPivotY();
17249     }
17250 
17251     /**
17252      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
17253      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
17254      * Setting this property disables this behavior and causes the view to use only the
17255      * explicitly set pivotX and pivotY values.
17256      *
17257      * @param pivotY The y location of the pivot point.
17258      * @see #getRotation()
17259      * @see #getScaleX()
17260      * @see #getScaleY()
17261      * @see #getPivotY()
17262      *
17263      * @attr ref android.R.styleable#View_transformPivotY
17264      */
17265     @RemotableViewMethod
setPivotY(float pivotY)17266     public void setPivotY(float pivotY) {
17267         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
17268             invalidateViewProperty(true, false);
17269             mRenderNode.setPivotY(pivotY);
17270             invalidateViewProperty(false, true);
17271 
17272             invalidateParentIfNeededAndWasQuickRejected();
17273         }
17274     }
17275 
17276     /**
17277      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
17278      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
17279      * of the view.
17280      *
17281      * @return True if a pivot has been set, false if the default pivot is being used
17282      */
isPivotSet()17283     public boolean isPivotSet() {
17284         return mRenderNode.isPivotExplicitlySet();
17285     }
17286 
17287     /**
17288      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
17289      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
17290      * and the pivot used for rotation will return to default of being centered on the view.
17291      */
resetPivot()17292     public void resetPivot() {
17293         if (mRenderNode.resetPivot()) {
17294             invalidateViewProperty(false, false);
17295         }
17296     }
17297 
17298     /**
17299      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
17300      * completely transparent and 1 means the view is completely opaque.
17301      *
17302      * <p>By default this is 1.0f.
17303      * @return The opacity of the view.
17304      */
17305     @ViewDebug.ExportedProperty(category = "drawing")
17306     @InspectableProperty
getAlpha()17307     public float getAlpha() {
17308         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
17309     }
17310 
17311     /**
17312      * Sets the behavior for overlapping rendering for this view (see {@link
17313      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
17314      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
17315      * providing the value which is then used internally. That is, when {@link
17316      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
17317      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
17318      * instead.
17319      *
17320      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
17321      * instead of that returned by {@link #hasOverlappingRendering()}.
17322      *
17323      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
17324      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)17325     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
17326         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
17327         if (hasOverlappingRendering) {
17328             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17329         } else {
17330             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17331         }
17332     }
17333 
17334     /**
17335      * Returns the value for overlapping rendering that is used internally. This is either
17336      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
17337      * the return value of {@link #hasOverlappingRendering()}, otherwise.
17338      *
17339      * @return The value for overlapping rendering being used internally.
17340      */
getHasOverlappingRendering()17341     public final boolean getHasOverlappingRendering() {
17342         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
17343                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
17344                 hasOverlappingRendering();
17345     }
17346 
17347     /**
17348      * Returns whether this View has content which overlaps.
17349      *
17350      * <p>This function, intended to be overridden by specific View types, is an optimization when
17351      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
17352      * an offscreen buffer and then composited into place, which can be expensive. If the view has
17353      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
17354      * directly. An example of overlapping rendering is a TextView with a background image, such as
17355      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
17356      * ImageView with only the foreground image. The default implementation returns true; subclasses
17357      * should override if they have cases which can be optimized.</p>
17358      *
17359      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
17360      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
17361      *
17362      * @return true if the content in this view might overlap, false otherwise.
17363      */
17364     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()17365     public boolean hasOverlappingRendering() {
17366         return true;
17367     }
17368 
17369     /**
17370      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
17371      * completely transparent and 1 means the view is completely opaque.
17372      *
17373      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
17374      * can have significant performance implications, especially for large views. It is best to use
17375      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
17376      *
17377      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
17378      * strongly recommended for performance reasons to either override
17379      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
17380      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
17381      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
17382      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
17383      * of rendering cost, even for simple or small views. Starting with
17384      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
17385      * applied to the view at the rendering level.</p>
17386      *
17387      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
17388      * responsible for applying the opacity itself.</p>
17389      *
17390      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
17391      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
17392      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
17393      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
17394      *
17395      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
17396      * value will clip a View to its bounds, unless the View returns <code>false</code> from
17397      * {@link #hasOverlappingRendering}.</p>
17398      *
17399      * @param alpha The opacity of the view.
17400      *
17401      * @see #hasOverlappingRendering()
17402      * @see #setLayerType(int, android.graphics.Paint)
17403      *
17404      * @attr ref android.R.styleable#View_alpha
17405      */
17406     @RemotableViewMethod
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)17407     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
17408         ensureTransformationInfo();
17409         if (mTransformationInfo.mAlpha != alpha) {
17410             setAlphaInternal(alpha);
17411             if (onSetAlpha((int) (alpha * 255))) {
17412                 mPrivateFlags |= PFLAG_ALPHA_SET;
17413                 // subclass is handling alpha - don't optimize rendering cache invalidation
17414                 invalidateParentCaches();
17415                 invalidate(true);
17416             } else {
17417                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17418                 invalidateViewProperty(true, false);
17419                 mRenderNode.setAlpha(getFinalAlpha());
17420             }
17421         }
17422     }
17423 
17424     /**
17425      * Faster version of setAlpha() which performs the same steps except there are
17426      * no calls to invalidate(). The caller of this function should perform proper invalidation
17427      * on the parent and this object. The return value indicates whether the subclass handles
17428      * alpha (the return value for onSetAlpha()).
17429      *
17430      * @param alpha The new value for the alpha property
17431      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
17432      *         the new value for the alpha property is different from the old value
17433      */
17434     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)17435     boolean setAlphaNoInvalidation(float alpha) {
17436         ensureTransformationInfo();
17437         if (mTransformationInfo.mAlpha != alpha) {
17438             setAlphaInternal(alpha);
17439             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
17440             if (subclassHandlesAlpha) {
17441                 mPrivateFlags |= PFLAG_ALPHA_SET;
17442                 return true;
17443             } else {
17444                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17445                 mRenderNode.setAlpha(getFinalAlpha());
17446             }
17447         }
17448         return false;
17449     }
17450 
setAlphaInternal(float alpha)17451     void setAlphaInternal(float alpha) {
17452         float oldAlpha = mTransformationInfo.mAlpha;
17453         mTransformationInfo.mAlpha = alpha;
17454         // Report visibility changes, which can affect children, to accessibility
17455         if ((alpha == 0) ^ (oldAlpha == 0)) {
17456             notifySubtreeAccessibilityStateChangedIfNeeded();
17457         }
17458     }
17459 
17460     /**
17461      * This property is intended only for use by the Fade transition, which animates it
17462      * to produce a visual translucency that does not side-effect (or get affected by)
17463      * the real alpha property. This value is composited with the other alpha value
17464      * (and the AlphaAnimation value, when that is present) to produce a final visual
17465      * translucency result, which is what is passed into the DisplayList.
17466      */
setTransitionAlpha(float alpha)17467     public void setTransitionAlpha(float alpha) {
17468         ensureTransformationInfo();
17469         if (mTransformationInfo.mTransitionAlpha != alpha) {
17470             mTransformationInfo.mTransitionAlpha = alpha;
17471             mPrivateFlags &= ~PFLAG_ALPHA_SET;
17472             invalidateViewProperty(true, false);
17473             mRenderNode.setAlpha(getFinalAlpha());
17474         }
17475     }
17476 
17477     /**
17478      * Calculates the visual alpha of this view, which is a combination of the actual
17479      * alpha value and the transitionAlpha value (if set).
17480      */
getFinalAlpha()17481     private float getFinalAlpha() {
17482         if (mTransformationInfo != null) {
17483             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
17484         }
17485         return 1;
17486     }
17487 
17488     /**
17489      * This property is intended only for use by the Fade transition, which animates
17490      * it to produce a visual translucency that does not side-effect (or get affected
17491      * by) the real alpha property. This value is composited with the other alpha
17492      * value (and the AlphaAnimation value, when that is present) to produce a final
17493      * visual translucency result, which is what is passed into the DisplayList.
17494      */
17495     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()17496     public float getTransitionAlpha() {
17497         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
17498     }
17499 
17500     /**
17501      * Sets whether or not to allow force dark to apply to this view.
17502      *
17503      * Setting this to false will disable the auto-dark feature on everything this view
17504      * draws, including any descendants.
17505      *
17506      * Setting this to true will allow this view to be automatically made dark, however
17507      * a value of 'true' will not override any 'false' value in its parent chain nor will
17508      * it prevent any 'false' in any of its children.
17509      *
17510      * The default behavior of force dark is also influenced by the Theme's
17511      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
17512      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
17513      *
17514      * @param allow Whether or not to allow force dark.
17515      */
setForceDarkAllowed(boolean allow)17516     public void setForceDarkAllowed(boolean allow) {
17517         if (mRenderNode.setForceDarkAllowed(allow)) {
17518             // Currently toggling force-dark requires a new display list push to apply
17519             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
17520             invalidate();
17521         }
17522     }
17523 
17524     /**
17525      * See {@link #setForceDarkAllowed(boolean)}
17526      *
17527      * @return true if force dark is allowed (default), false if it is disabled
17528      */
17529     @ViewDebug.ExportedProperty(category = "drawing")
17530     @InspectableProperty
isForceDarkAllowed()17531     public boolean isForceDarkAllowed() {
17532         return mRenderNode.isForceDarkAllowed();
17533     }
17534 
17535     /**
17536      * Top position of this view relative to its parent.
17537      *
17538      * @return The top of this view, in pixels.
17539      */
17540     @ViewDebug.CapturedViewProperty
getTop()17541     public final int getTop() {
17542         return mTop;
17543     }
17544 
17545     /**
17546      * Sets the top position of this view relative to its parent. This method is meant to be called
17547      * by the layout system and should not generally be called otherwise, because the property
17548      * may be changed at any time by the layout.
17549      *
17550      * @param top The top of this view, in pixels.
17551      */
setTop(int top)17552     public final void setTop(int top) {
17553         if (top != mTop) {
17554             final boolean matrixIsIdentity = hasIdentityMatrix();
17555             if (matrixIsIdentity) {
17556                 if (mAttachInfo != null) {
17557                     int minTop;
17558                     int yLoc;
17559                     if (top < mTop) {
17560                         minTop = top;
17561                         yLoc = top - mTop;
17562                     } else {
17563                         minTop = mTop;
17564                         yLoc = 0;
17565                     }
17566                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
17567                 }
17568             } else {
17569                 // Double-invalidation is necessary to capture view's old and new areas
17570                 invalidate(true);
17571             }
17572 
17573             int width = mRight - mLeft;
17574             int oldHeight = mBottom - mTop;
17575 
17576             mTop = top;
17577             mRenderNode.setTop(mTop);
17578 
17579             sizeChange(width, mBottom - mTop, width, oldHeight);
17580 
17581             if (!matrixIsIdentity) {
17582                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17583                 invalidate(true);
17584             }
17585             mBackgroundSizeChanged = true;
17586             mDefaultFocusHighlightSizeChanged = true;
17587             if (mForegroundInfo != null) {
17588                 mForegroundInfo.mBoundsChanged = true;
17589             }
17590             invalidateParentIfNeeded();
17591         }
17592     }
17593 
17594     /**
17595      * Bottom position of this view relative to its parent.
17596      *
17597      * @return The bottom of this view, in pixels.
17598      */
17599     @ViewDebug.CapturedViewProperty
getBottom()17600     public final int getBottom() {
17601         return mBottom;
17602     }
17603 
17604     /**
17605      * True if this view has changed since the last time being drawn.
17606      *
17607      * @return The dirty state of this view.
17608      */
isDirty()17609     public boolean isDirty() {
17610         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
17611     }
17612 
17613     /**
17614      * Sets the bottom position of this view relative to its parent. This method is meant to be
17615      * called by the layout system and should not generally be called otherwise, because the
17616      * property may be changed at any time by the layout.
17617      *
17618      * @param bottom The bottom of this view, in pixels.
17619      */
setBottom(int bottom)17620     public final void setBottom(int bottom) {
17621         if (bottom != mBottom) {
17622             final boolean matrixIsIdentity = hasIdentityMatrix();
17623             if (matrixIsIdentity) {
17624                 if (mAttachInfo != null) {
17625                     int maxBottom;
17626                     if (bottom < mBottom) {
17627                         maxBottom = mBottom;
17628                     } else {
17629                         maxBottom = bottom;
17630                     }
17631                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
17632                 }
17633             } else {
17634                 // Double-invalidation is necessary to capture view's old and new areas
17635                 invalidate(true);
17636             }
17637 
17638             int width = mRight - mLeft;
17639             int oldHeight = mBottom - mTop;
17640 
17641             mBottom = bottom;
17642             mRenderNode.setBottom(mBottom);
17643 
17644             sizeChange(width, mBottom - mTop, width, oldHeight);
17645 
17646             if (!matrixIsIdentity) {
17647                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17648                 invalidate(true);
17649             }
17650             mBackgroundSizeChanged = true;
17651             mDefaultFocusHighlightSizeChanged = true;
17652             if (mForegroundInfo != null) {
17653                 mForegroundInfo.mBoundsChanged = true;
17654             }
17655             invalidateParentIfNeeded();
17656         }
17657     }
17658 
17659     /**
17660      * Left position of this view relative to its parent.
17661      *
17662      * @return The left edge of this view, in pixels.
17663      */
17664     @ViewDebug.CapturedViewProperty
getLeft()17665     public final int getLeft() {
17666         return mLeft;
17667     }
17668 
17669     /**
17670      * Sets the left position of this view relative to its parent. This method is meant to be called
17671      * by the layout system and should not generally be called otherwise, because the property
17672      * may be changed at any time by the layout.
17673      *
17674      * @param left The left of this view, in pixels.
17675      */
setLeft(int left)17676     public final void setLeft(int left) {
17677         if (left != mLeft) {
17678             final boolean matrixIsIdentity = hasIdentityMatrix();
17679             if (matrixIsIdentity) {
17680                 if (mAttachInfo != null) {
17681                     int minLeft;
17682                     int xLoc;
17683                     if (left < mLeft) {
17684                         minLeft = left;
17685                         xLoc = left - mLeft;
17686                     } else {
17687                         minLeft = mLeft;
17688                         xLoc = 0;
17689                     }
17690                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
17691                 }
17692             } else {
17693                 // Double-invalidation is necessary to capture view's old and new areas
17694                 invalidate(true);
17695             }
17696 
17697             int oldWidth = mRight - mLeft;
17698             int height = mBottom - mTop;
17699 
17700             mLeft = left;
17701             mRenderNode.setLeft(left);
17702 
17703             sizeChange(mRight - mLeft, height, oldWidth, height);
17704 
17705             if (!matrixIsIdentity) {
17706                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17707                 invalidate(true);
17708             }
17709             mBackgroundSizeChanged = true;
17710             mDefaultFocusHighlightSizeChanged = true;
17711             if (mForegroundInfo != null) {
17712                 mForegroundInfo.mBoundsChanged = true;
17713             }
17714             invalidateParentIfNeeded();
17715         }
17716     }
17717 
17718     /**
17719      * Right position of this view relative to its parent.
17720      *
17721      * @return The right edge of this view, in pixels.
17722      */
17723     @ViewDebug.CapturedViewProperty
getRight()17724     public final int getRight() {
17725         return mRight;
17726     }
17727 
17728     /**
17729      * Sets the right position of this view relative to its parent. This method is meant to be called
17730      * by the layout system and should not generally be called otherwise, because the property
17731      * may be changed at any time by the layout.
17732      *
17733      * @param right The right of this view, in pixels.
17734      */
setRight(int right)17735     public final void setRight(int right) {
17736         if (right != mRight) {
17737             final boolean matrixIsIdentity = hasIdentityMatrix();
17738             if (matrixIsIdentity) {
17739                 if (mAttachInfo != null) {
17740                     int maxRight;
17741                     if (right < mRight) {
17742                         maxRight = mRight;
17743                     } else {
17744                         maxRight = right;
17745                     }
17746                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
17747                 }
17748             } else {
17749                 // Double-invalidation is necessary to capture view's old and new areas
17750                 invalidate(true);
17751             }
17752 
17753             int oldWidth = mRight - mLeft;
17754             int height = mBottom - mTop;
17755 
17756             mRight = right;
17757             mRenderNode.setRight(mRight);
17758 
17759             sizeChange(mRight - mLeft, height, oldWidth, height);
17760 
17761             if (!matrixIsIdentity) {
17762                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17763                 invalidate(true);
17764             }
17765             mBackgroundSizeChanged = true;
17766             mDefaultFocusHighlightSizeChanged = true;
17767             if (mForegroundInfo != null) {
17768                 mForegroundInfo.mBoundsChanged = true;
17769             }
17770             invalidateParentIfNeeded();
17771         }
17772     }
17773 
sanitizeFloatPropertyValue(float value, String propertyName)17774     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
17775         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
17776     }
17777 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)17778     private static float sanitizeFloatPropertyValue(float value, String propertyName,
17779             float min, float max) {
17780         // The expected "nothing bad happened" path
17781         if (value >= min && value <= max) return value;
17782 
17783         if (value < min || value == Float.NEGATIVE_INFINITY) {
17784             if (sThrowOnInvalidFloatProperties) {
17785                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17786                         + value + ", the value must be >= " + min);
17787             }
17788             return min;
17789         }
17790 
17791         if (value > max || value == Float.POSITIVE_INFINITY) {
17792             if (sThrowOnInvalidFloatProperties) {
17793                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17794                         + value + ", the value must be <= " + max);
17795             }
17796             return max;
17797         }
17798 
17799         if (Float.isNaN(value)) {
17800             if (sThrowOnInvalidFloatProperties) {
17801                 throw new IllegalArgumentException(
17802                         "Cannot set '" + propertyName + "' to Float.NaN");
17803             }
17804             return 0; // Unclear which direction this NaN went so... 0?
17805         }
17806 
17807         // Shouldn't be possible to reach this.
17808         throw new IllegalStateException("How do you get here?? " + value);
17809     }
17810 
17811     /**
17812      * The visual x position of this view, in pixels. This is equivalent to the
17813      * {@link #setTranslationX(float) translationX} property plus the current
17814      * {@link #getLeft() left} property.
17815      *
17816      * @return The visual x position of this view, in pixels.
17817      */
17818     @ViewDebug.ExportedProperty(category = "drawing")
getX()17819     public float getX() {
17820         return mLeft + getTranslationX();
17821     }
17822 
17823     /**
17824      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
17825      * {@link #setTranslationX(float) translationX} property to be the difference between
17826      * the x value passed in and the current {@link #getLeft() left} property.
17827      *
17828      * @param x The visual x position of this view, in pixels.
17829      */
setX(float x)17830     public void setX(float x) {
17831         setTranslationX(x - mLeft);
17832     }
17833 
17834     /**
17835      * The visual y position of this view, in pixels. This is equivalent to the
17836      * {@link #setTranslationY(float) translationY} property plus the current
17837      * {@link #getTop() top} property.
17838      *
17839      * @return The visual y position of this view, in pixels.
17840      */
17841     @ViewDebug.ExportedProperty(category = "drawing")
getY()17842     public float getY() {
17843         return mTop + getTranslationY();
17844     }
17845 
17846     /**
17847      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
17848      * {@link #setTranslationY(float) translationY} property to be the difference between
17849      * the y value passed in and the current {@link #getTop() top} property.
17850      *
17851      * @param y The visual y position of this view, in pixels.
17852      */
setY(float y)17853     public void setY(float y) {
17854         setTranslationY(y - mTop);
17855     }
17856 
17857     /**
17858      * The visual z position of this view, in pixels. This is equivalent to the
17859      * {@link #setTranslationZ(float) translationZ} property plus the current
17860      * {@link #getElevation() elevation} property.
17861      *
17862      * @return The visual z position of this view, in pixels.
17863      */
17864     @ViewDebug.ExportedProperty(category = "drawing")
getZ()17865     public float getZ() {
17866         return getElevation() + getTranslationZ();
17867     }
17868 
17869     /**
17870      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
17871      * {@link #setTranslationZ(float) translationZ} property to be the difference between
17872      * the z value passed in and the current {@link #getElevation() elevation} property.
17873      *
17874      * @param z The visual z position of this view, in pixels.
17875      */
setZ(float z)17876     public void setZ(float z) {
17877         setTranslationZ(z - getElevation());
17878     }
17879 
17880     /**
17881      * The base elevation of this view relative to its parent, in pixels.
17882      *
17883      * @return The base depth position of the view, in pixels.
17884      */
17885     @ViewDebug.ExportedProperty(category = "drawing")
17886     @InspectableProperty
getElevation()17887     public float getElevation() {
17888         return mRenderNode.getElevation();
17889     }
17890 
17891     /**
17892      * Sets the base elevation of this view, in pixels.
17893      *
17894      * @attr ref android.R.styleable#View_elevation
17895      */
17896     @RemotableViewMethod
setElevation(float elevation)17897     public void setElevation(float elevation) {
17898         if (elevation != getElevation()) {
17899             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
17900             invalidateViewProperty(true, false);
17901             mRenderNode.setElevation(elevation);
17902             invalidateViewProperty(false, true);
17903 
17904             invalidateParentIfNeededAndWasQuickRejected();
17905         }
17906     }
17907 
17908     /**
17909      * The horizontal location of this view relative to its {@link #getLeft() left} position.
17910      * This position is post-layout, in addition to wherever the object's
17911      * layout placed it.
17912      *
17913      * @return The horizontal position of this view relative to its left position, in pixels.
17914      */
17915     @ViewDebug.ExportedProperty(category = "drawing")
17916     @InspectableProperty
getTranslationX()17917     public float getTranslationX() {
17918         return mRenderNode.getTranslationX();
17919     }
17920 
17921     /**
17922      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
17923      * This effectively positions the object post-layout, in addition to wherever the object's
17924      * layout placed it.
17925      *
17926      * @param translationX The horizontal position of this view relative to its left position,
17927      * in pixels.
17928      *
17929      * @attr ref android.R.styleable#View_translationX
17930      */
17931     @RemotableViewMethod
setTranslationX(float translationX)17932     public void setTranslationX(float translationX) {
17933         if (translationX != getTranslationX()) {
17934             invalidateViewProperty(true, false);
17935             mRenderNode.setTranslationX(translationX);
17936             invalidateViewProperty(false, true);
17937 
17938             invalidateParentIfNeededAndWasQuickRejected();
17939             notifySubtreeAccessibilityStateChangedIfNeeded();
17940         }
17941     }
17942 
17943     /**
17944      * The vertical location of this view relative to its {@link #getTop() top} position.
17945      * This position is post-layout, in addition to wherever the object's
17946      * layout placed it.
17947      *
17948      * @return The vertical position of this view relative to its top position,
17949      * in pixels.
17950      */
17951     @ViewDebug.ExportedProperty(category = "drawing")
17952     @InspectableProperty
getTranslationY()17953     public float getTranslationY() {
17954         return mRenderNode.getTranslationY();
17955     }
17956 
17957     /**
17958      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
17959      * This effectively positions the object post-layout, in addition to wherever the object's
17960      * layout placed it.
17961      *
17962      * @param translationY The vertical position of this view relative to its top position,
17963      * in pixels.
17964      *
17965      * @attr ref android.R.styleable#View_translationY
17966      */
17967     @RemotableViewMethod
setTranslationY(float translationY)17968     public void setTranslationY(float translationY) {
17969         if (translationY != getTranslationY()) {
17970             invalidateViewProperty(true, false);
17971             mRenderNode.setTranslationY(translationY);
17972             invalidateViewProperty(false, true);
17973 
17974             invalidateParentIfNeededAndWasQuickRejected();
17975             notifySubtreeAccessibilityStateChangedIfNeeded();
17976         }
17977     }
17978 
17979     /**
17980      * The depth location of this view relative to its {@link #getElevation() elevation}.
17981      *
17982      * @return The depth of this view relative to its elevation.
17983      */
17984     @ViewDebug.ExportedProperty(category = "drawing")
17985     @InspectableProperty
getTranslationZ()17986     public float getTranslationZ() {
17987         return mRenderNode.getTranslationZ();
17988     }
17989 
17990     /**
17991      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
17992      *
17993      * @attr ref android.R.styleable#View_translationZ
17994      */
17995     @RemotableViewMethod
setTranslationZ(float translationZ)17996     public void setTranslationZ(float translationZ) {
17997         if (translationZ != getTranslationZ()) {
17998             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
17999             invalidateViewProperty(true, false);
18000             mRenderNode.setTranslationZ(translationZ);
18001             invalidateViewProperty(false, true);
18002 
18003             invalidateParentIfNeededAndWasQuickRejected();
18004         }
18005     }
18006 
18007     /**
18008      * Changes the transformation matrix on the view. This is used in animation frameworks,
18009      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
18010      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
18011      * Application developers should use transformation methods like {@link #setRotation(float)},
18012      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
18013      * and {@link #setTranslationY(float)} (float)}} instead.
18014      *
18015      * @param matrix The matrix, null indicates that the matrix should be cleared.
18016      * @see #getAnimationMatrix()
18017      */
setAnimationMatrix(@ullable Matrix matrix)18018     public void setAnimationMatrix(@Nullable Matrix matrix) {
18019         invalidateViewProperty(true, false);
18020         mRenderNode.setAnimationMatrix(matrix);
18021         invalidateViewProperty(false, true);
18022 
18023         invalidateParentIfNeededAndWasQuickRejected();
18024     }
18025 
18026     /**
18027      * Return the current transformation matrix of the view. This is used in animation frameworks,
18028      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
18029      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
18030      * Application developers should use transformation methods like {@link #setRotation(float)},
18031      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
18032      * and {@link #setTranslationY(float)} (float)}} instead.
18033      *
18034      * @return the Matrix, null indicates there is no transformation
18035      * @see #setAnimationMatrix(Matrix)
18036      */
18037     @Nullable
getAnimationMatrix()18038     public Matrix getAnimationMatrix() {
18039         return mRenderNode.getAnimationMatrix();
18040     }
18041 
18042     /**
18043      * Returns the current StateListAnimator if exists.
18044      *
18045      * @return StateListAnimator or null if it does not exists
18046      * @see    #setStateListAnimator(android.animation.StateListAnimator)
18047      */
18048     @InspectableProperty
getStateListAnimator()18049     public StateListAnimator getStateListAnimator() {
18050         return mStateListAnimator;
18051     }
18052 
18053     /**
18054      * Attaches the provided StateListAnimator to this View.
18055      * <p>
18056      * Any previously attached StateListAnimator will be detached.
18057      *
18058      * @param stateListAnimator The StateListAnimator to update the view
18059      * @see android.animation.StateListAnimator
18060      */
setStateListAnimator(StateListAnimator stateListAnimator)18061     public void setStateListAnimator(StateListAnimator stateListAnimator) {
18062         if (mStateListAnimator == stateListAnimator) {
18063             return;
18064         }
18065         if (mStateListAnimator != null) {
18066             mStateListAnimator.setTarget(null);
18067         }
18068         mStateListAnimator = stateListAnimator;
18069         if (stateListAnimator != null) {
18070             stateListAnimator.setTarget(this);
18071             if (isAttachedToWindow()) {
18072                 stateListAnimator.setState(getDrawableState());
18073             }
18074         }
18075     }
18076 
18077     /**
18078      * Returns whether the Outline should be used to clip the contents of the View.
18079      * <p>
18080      * Note that this flag will only be respected if the View's Outline returns true from
18081      * {@link Outline#canClip()}.
18082      *
18083      * @see #setOutlineProvider(ViewOutlineProvider)
18084      * @see #setClipToOutline(boolean)
18085      */
getClipToOutline()18086     public final boolean getClipToOutline() {
18087         return mRenderNode.getClipToOutline();
18088     }
18089 
18090     /**
18091      * Sets whether the View's Outline should be used to clip the contents of the View.
18092      * <p>
18093      * Only a single non-rectangular clip can be applied on a View at any time.
18094      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
18095      * circular reveal} animation take priority over Outline clipping, and
18096      * child Outline clipping takes priority over Outline clipping done by a
18097      * parent.
18098      * <p>
18099      * Note that this flag will only be respected if the View's Outline returns true from
18100      * {@link Outline#canClip()}.
18101      *
18102      * @see #setOutlineProvider(ViewOutlineProvider)
18103      * @see #getClipToOutline()
18104      *
18105      * @attr ref android.R.styleable#View_clipToOutline
18106      */
18107     @RemotableViewMethod
setClipToOutline(boolean clipToOutline)18108     public void setClipToOutline(boolean clipToOutline) {
18109         damageInParent();
18110         if (getClipToOutline() != clipToOutline) {
18111             mRenderNode.setClipToOutline(clipToOutline);
18112         }
18113     }
18114 
18115     // correspond to the enum values of View_outlineProvider
18116     private static final int PROVIDER_BACKGROUND = 0;
18117     private static final int PROVIDER_NONE = 1;
18118     private static final int PROVIDER_BOUNDS = 2;
18119     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)18120     private void setOutlineProviderFromAttribute(int providerInt) {
18121         switch (providerInt) {
18122             case PROVIDER_BACKGROUND:
18123                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
18124                 break;
18125             case PROVIDER_NONE:
18126                 setOutlineProvider(null);
18127                 break;
18128             case PROVIDER_BOUNDS:
18129                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
18130                 break;
18131             case PROVIDER_PADDED_BOUNDS:
18132                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
18133                 break;
18134         }
18135     }
18136 
18137     /**
18138      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
18139      * the shape of the shadow it casts, and enables outline clipping.
18140      * <p>
18141      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
18142      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
18143      * outline provider with this method allows this behavior to be overridden.
18144      * <p>
18145      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
18146      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
18147      * <p>
18148      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
18149      *
18150      * @see #setClipToOutline(boolean)
18151      * @see #getClipToOutline()
18152      * @see #getOutlineProvider()
18153      */
setOutlineProvider(ViewOutlineProvider provider)18154     public void setOutlineProvider(ViewOutlineProvider provider) {
18155         mOutlineProvider = provider;
18156         invalidateOutline();
18157     }
18158 
18159     /**
18160      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
18161      * that defines the shape of the shadow it casts, and enables outline clipping.
18162      *
18163      * @see #setOutlineProvider(ViewOutlineProvider)
18164      */
18165     @InspectableProperty
getOutlineProvider()18166     public ViewOutlineProvider getOutlineProvider() {
18167         return mOutlineProvider;
18168     }
18169 
18170     /**
18171      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
18172      *
18173      * @see #setOutlineProvider(ViewOutlineProvider)
18174      */
invalidateOutline()18175     public void invalidateOutline() {
18176         rebuildOutline();
18177 
18178         notifySubtreeAccessibilityStateChangedIfNeeded();
18179         invalidateViewProperty(false, false);
18180     }
18181 
18182     /**
18183      * Internal version of {@link #invalidateOutline()} which invalidates the
18184      * outline without invalidating the view itself. This is intended to be called from
18185      * within methods in the View class itself which are the result of the view being
18186      * invalidated already. For example, when we are drawing the background of a View,
18187      * we invalidate the outline in case it changed in the meantime, but we do not
18188      * need to invalidate the view because we're already drawing the background as part
18189      * of drawing the view in response to an earlier invalidation of the view.
18190      */
rebuildOutline()18191     private void rebuildOutline() {
18192         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
18193         if (mAttachInfo == null) return;
18194 
18195         if (mOutlineProvider == null) {
18196             // no provider, remove outline
18197             mRenderNode.setOutline(null);
18198         } else {
18199             final Outline outline = mAttachInfo.mTmpOutline;
18200             outline.setEmpty();
18201             outline.setAlpha(1.0f);
18202 
18203             mOutlineProvider.getOutline(this, outline);
18204             mRenderNode.setOutline(outline);
18205         }
18206     }
18207 
18208     /**
18209      * HierarchyViewer only
18210      *
18211      * @hide
18212      */
18213     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()18214     public boolean hasShadow() {
18215         return mRenderNode.hasShadow();
18216     }
18217 
18218     /**
18219      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
18220      * elevation value.
18221      * <p>
18222      * By default the shadow color is black. Generally, this color will be opaque so the intensity
18223      * of the shadow is consistent between different views with different colors.
18224      * <p>
18225      * The opacity of the final spot shadow is a function of the shadow caster height, the
18226      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
18227      * {@link android.R.attr#spotShadowAlpha} theme attribute.
18228      *
18229      * @attr ref android.R.styleable#View_outlineSpotShadowColor
18230      * @param color The color this View will cast for its elevation spot shadow.
18231      */
setOutlineSpotShadowColor(@olorInt int color)18232     public void setOutlineSpotShadowColor(@ColorInt int color) {
18233         if (mRenderNode.setSpotShadowColor(color)) {
18234             invalidateViewProperty(true, true);
18235         }
18236     }
18237 
18238     /**
18239      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
18240      * was set
18241      */
18242     @InspectableProperty
getOutlineSpotShadowColor()18243     public @ColorInt int getOutlineSpotShadowColor() {
18244         return mRenderNode.getSpotShadowColor();
18245     }
18246 
18247     /**
18248      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
18249      * elevation value.
18250      * <p>
18251      * By default the shadow color is black. Generally, this color will be opaque so the intensity
18252      * of the shadow is consistent between different views with different colors.
18253      * <p>
18254      * The opacity of the final ambient shadow is a function of the shadow caster height, the
18255      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
18256      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
18257      *
18258      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
18259      * @param color The color this View will cast for its elevation shadow.
18260      */
setOutlineAmbientShadowColor(@olorInt int color)18261     public void setOutlineAmbientShadowColor(@ColorInt int color) {
18262         if (mRenderNode.setAmbientShadowColor(color)) {
18263             invalidateViewProperty(true, true);
18264         }
18265     }
18266 
18267     /**
18268      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
18269      * nothing was set
18270      */
18271     @InspectableProperty
getOutlineAmbientShadowColor()18272     public @ColorInt int getOutlineAmbientShadowColor() {
18273         return mRenderNode.getAmbientShadowColor();
18274     }
18275 
18276 
18277     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)18278     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
18279         mRenderNode.setRevealClip(shouldClip, x, y, radius);
18280         invalidateViewProperty(false, false);
18281     }
18282 
18283     /**
18284      * Hit rectangle in parent's coordinates
18285      *
18286      * @param outRect The hit rectangle of the view.
18287      */
getHitRect(Rect outRect)18288     public void getHitRect(Rect outRect) {
18289         if (hasIdentityMatrix() || mAttachInfo == null) {
18290             outRect.set(mLeft, mTop, mRight, mBottom);
18291         } else {
18292             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
18293             tmpRect.set(0, 0, getWidth(), getHeight());
18294             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
18295             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
18296                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
18297         }
18298     }
18299 
18300     /**
18301      * Determines whether the given point, in local coordinates is inside the view.
18302      */
pointInView(float localX, float localY)18303     /*package*/ final boolean pointInView(float localX, float localY) {
18304         return pointInView(localX, localY, 0);
18305     }
18306 
18307     /**
18308      * Utility method to determine whether the given point, in local coordinates,
18309      * is inside the view, where the area of the view is expanded by the slop factor.
18310      * This method is called while processing touch-move events to determine if the event
18311      * is still within the view.
18312      *
18313      * @hide
18314      */
18315     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)18316     public boolean pointInView(float localX, float localY, float slop) {
18317         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
18318                 localY < ((mBottom - mTop) + slop);
18319     }
18320 
18321     /**
18322      * When a view has focus and the user navigates away from it, the next view is searched for
18323      * starting from the rectangle filled in by this method.
18324      *
18325      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
18326      * of the view.  However, if your view maintains some idea of internal selection,
18327      * such as a cursor, or a selected row or column, you should override this method and
18328      * fill in a more specific rectangle.
18329      *
18330      * @param r The rectangle to fill in, in this view's coordinates.
18331      */
getFocusedRect(Rect r)18332     public void getFocusedRect(Rect r) {
18333         getDrawingRect(r);
18334     }
18335 
18336     /**
18337      * If some part of this view is not clipped by any of its parents, then
18338      * return that area in r in global (root) coordinates. To convert r to local
18339      * coordinates (without taking possible View rotations into account), offset
18340      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
18341      * If the view is completely clipped or translated out, return false.
18342      *
18343      * @param r If true is returned, r holds the global coordinates of the
18344      *        visible portion of this view.
18345      * @param globalOffset If true is returned, globalOffset holds the dx,dy
18346      *        between this view and its root. globalOffet may be null.
18347      * @return true if r is non-empty (i.e. part of the view is visible at the
18348      *         root level.
18349      */
getGlobalVisibleRect(Rect r, Point globalOffset)18350     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
18351         int width = mRight - mLeft;
18352         int height = mBottom - mTop;
18353         if (width > 0 && height > 0) {
18354             r.set(0, 0, width, height);
18355             if (globalOffset != null) {
18356                 globalOffset.set(-mScrollX, -mScrollY);
18357             }
18358             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
18359         }
18360         return false;
18361     }
18362 
getGlobalVisibleRect(Rect r)18363     public final boolean getGlobalVisibleRect(Rect r) {
18364         return getGlobalVisibleRect(r, null);
18365     }
18366 
getLocalVisibleRect(Rect r)18367     public final boolean getLocalVisibleRect(Rect r) {
18368         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
18369         if (getGlobalVisibleRect(r, offset)) {
18370             r.offset(-offset.x, -offset.y); // make r local
18371             return true;
18372         }
18373         return false;
18374     }
18375 
18376     /**
18377      * Offset this view's vertical location by the specified number of pixels.
18378      *
18379      * @param offset the number of pixels to offset the view by
18380      */
offsetTopAndBottom(int offset)18381     public void offsetTopAndBottom(int offset) {
18382         if (offset != 0) {
18383             final boolean matrixIsIdentity = hasIdentityMatrix();
18384             if (matrixIsIdentity) {
18385                 if (isHardwareAccelerated()) {
18386                     invalidateViewProperty(false, false);
18387                 } else {
18388                     final ViewParent p = mParent;
18389                     if (p != null && mAttachInfo != null) {
18390                         final Rect r = mAttachInfo.mTmpInvalRect;
18391                         int minTop;
18392                         int maxBottom;
18393                         int yLoc;
18394                         if (offset < 0) {
18395                             minTop = mTop + offset;
18396                             maxBottom = mBottom;
18397                             yLoc = offset;
18398                         } else {
18399                             minTop = mTop;
18400                             maxBottom = mBottom + offset;
18401                             yLoc = 0;
18402                         }
18403                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
18404                         p.invalidateChild(this, r);
18405                     }
18406                 }
18407             } else {
18408                 invalidateViewProperty(false, false);
18409             }
18410 
18411             mTop += offset;
18412             mBottom += offset;
18413             mRenderNode.offsetTopAndBottom(offset);
18414             if (isHardwareAccelerated()) {
18415                 invalidateViewProperty(false, false);
18416                 invalidateParentIfNeededAndWasQuickRejected();
18417             } else {
18418                 if (!matrixIsIdentity) {
18419                     invalidateViewProperty(false, true);
18420                 }
18421                 invalidateParentIfNeeded();
18422             }
18423             notifySubtreeAccessibilityStateChangedIfNeeded();
18424         }
18425     }
18426 
18427     /**
18428      * Offset this view's horizontal location by the specified amount of pixels.
18429      *
18430      * @param offset the number of pixels to offset the view by
18431      */
offsetLeftAndRight(int offset)18432     public void offsetLeftAndRight(int offset) {
18433         if (offset != 0) {
18434             final boolean matrixIsIdentity = hasIdentityMatrix();
18435             if (matrixIsIdentity) {
18436                 if (isHardwareAccelerated()) {
18437                     invalidateViewProperty(false, false);
18438                 } else {
18439                     final ViewParent p = mParent;
18440                     if (p != null && mAttachInfo != null) {
18441                         final Rect r = mAttachInfo.mTmpInvalRect;
18442                         int minLeft;
18443                         int maxRight;
18444                         if (offset < 0) {
18445                             minLeft = mLeft + offset;
18446                             maxRight = mRight;
18447                         } else {
18448                             minLeft = mLeft;
18449                             maxRight = mRight + offset;
18450                         }
18451                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
18452                         p.invalidateChild(this, r);
18453                     }
18454                 }
18455             } else {
18456                 invalidateViewProperty(false, false);
18457             }
18458 
18459             mLeft += offset;
18460             mRight += offset;
18461             mRenderNode.offsetLeftAndRight(offset);
18462             if (isHardwareAccelerated()) {
18463                 invalidateViewProperty(false, false);
18464                 invalidateParentIfNeededAndWasQuickRejected();
18465             } else {
18466                 if (!matrixIsIdentity) {
18467                     invalidateViewProperty(false, true);
18468                 }
18469                 invalidateParentIfNeeded();
18470             }
18471             notifySubtreeAccessibilityStateChangedIfNeeded();
18472         }
18473     }
18474 
18475     /**
18476      * Get the LayoutParams associated with this view. All views should have
18477      * layout parameters. These supply parameters to the <i>parent</i> of this
18478      * view specifying how it should be arranged. There are many subclasses of
18479      * ViewGroup.LayoutParams, and these correspond to the different subclasses
18480      * of ViewGroup that are responsible for arranging their children.
18481      *
18482      * This method may return null if this View is not attached to a parent
18483      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
18484      * was not invoked successfully. When a View is attached to a parent
18485      * ViewGroup, this method must not return null.
18486      *
18487      * @return The LayoutParams associated with this view, or null if no
18488      *         parameters have been set yet
18489      */
18490     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()18491     public ViewGroup.LayoutParams getLayoutParams() {
18492         return mLayoutParams;
18493     }
18494 
18495     /**
18496      * Set the layout parameters associated with this view. These supply
18497      * parameters to the <i>parent</i> of this view specifying how it should be
18498      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
18499      * correspond to the different subclasses of ViewGroup that are responsible
18500      * for arranging their children.
18501      *
18502      * @param params The layout parameters for this view, cannot be null
18503      */
setLayoutParams(ViewGroup.LayoutParams params)18504     public void setLayoutParams(ViewGroup.LayoutParams params) {
18505         if (params == null) {
18506             throw new NullPointerException("Layout parameters cannot be null");
18507         }
18508         mLayoutParams = params;
18509         resolveLayoutParams();
18510         if (mParent instanceof ViewGroup) {
18511             ((ViewGroup) mParent).onSetLayoutParams(this, params);
18512         }
18513         requestLayout();
18514     }
18515 
18516     /**
18517      * Resolve the layout parameters depending on the resolved layout direction
18518      *
18519      * @hide
18520      */
resolveLayoutParams()18521     public void resolveLayoutParams() {
18522         if (mLayoutParams != null) {
18523             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
18524         }
18525     }
18526 
18527     /**
18528      * Set the scrolled position of your view. This will cause a call to
18529      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18530      * invalidated.
18531      * @param x the x position to scroll to
18532      * @param y the y position to scroll to
18533      */
scrollTo(int x, int y)18534     public void scrollTo(int x, int y) {
18535         if (mScrollX != x || mScrollY != y) {
18536             int oldX = mScrollX;
18537             int oldY = mScrollY;
18538             mScrollX = x;
18539             mScrollY = y;
18540             invalidateParentCaches();
18541             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
18542             if (!awakenScrollBars()) {
18543                 postInvalidateOnAnimation();
18544             }
18545         }
18546     }
18547 
18548     /**
18549      * Move the scrolled position of your view. This will cause a call to
18550      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18551      * invalidated.
18552      * @param x the amount of pixels to scroll by horizontally
18553      * @param y the amount of pixels to scroll by vertically
18554      */
scrollBy(int x, int y)18555     public void scrollBy(int x, int y) {
18556         scrollTo(mScrollX + x, mScrollY + y);
18557     }
18558 
18559     /**
18560      * <p>Trigger the scrollbars to draw. When invoked this method starts an
18561      * animation to fade the scrollbars out after a default delay. If a subclass
18562      * provides animated scrolling, the start delay should equal the duration
18563      * of the scrolling animation.</p>
18564      *
18565      * <p>The animation starts only if at least one of the scrollbars is
18566      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
18567      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18568      * this method returns true, and false otherwise. If the animation is
18569      * started, this method calls {@link #invalidate()}; in that case the
18570      * caller should not call {@link #invalidate()}.</p>
18571      *
18572      * <p>This method should be invoked every time a subclass directly updates
18573      * the scroll parameters.</p>
18574      *
18575      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
18576      * and {@link #scrollTo(int, int)}.</p>
18577      *
18578      * @return true if the animation is played, false otherwise
18579      *
18580      * @see #awakenScrollBars(int)
18581      * @see #scrollBy(int, int)
18582      * @see #scrollTo(int, int)
18583      * @see #isHorizontalScrollBarEnabled()
18584      * @see #isVerticalScrollBarEnabled()
18585      * @see #setHorizontalScrollBarEnabled(boolean)
18586      * @see #setVerticalScrollBarEnabled(boolean)
18587      */
awakenScrollBars()18588     protected boolean awakenScrollBars() {
18589         return mScrollCache != null &&
18590                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
18591     }
18592 
18593     /**
18594      * Trigger the scrollbars to draw.
18595      * This method differs from awakenScrollBars() only in its default duration.
18596      * initialAwakenScrollBars() will show the scroll bars for longer than
18597      * usual to give the user more of a chance to notice them.
18598      *
18599      * @return true if the animation is played, false otherwise.
18600      */
initialAwakenScrollBars()18601     private boolean initialAwakenScrollBars() {
18602         return mScrollCache != null &&
18603                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
18604     }
18605 
18606     /**
18607      * <p>
18608      * Trigger the scrollbars to draw. When invoked this method starts an
18609      * animation to fade the scrollbars out after a fixed delay. If a subclass
18610      * provides animated scrolling, the start delay should equal the duration of
18611      * the scrolling animation.
18612      * </p>
18613      *
18614      * <p>
18615      * The animation starts only if at least one of the scrollbars is enabled,
18616      * as specified by {@link #isHorizontalScrollBarEnabled()} and
18617      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18618      * this method returns true, and false otherwise. If the animation is
18619      * started, this method calls {@link #invalidate()}; in that case the caller
18620      * should not call {@link #invalidate()}.
18621      * </p>
18622      *
18623      * <p>
18624      * This method should be invoked every time a subclass directly updates the
18625      * scroll parameters.
18626      * </p>
18627      *
18628      * @param startDelay the delay, in milliseconds, after which the animation
18629      *        should start; when the delay is 0, the animation starts
18630      *        immediately
18631      * @return true if the animation is played, false otherwise
18632      *
18633      * @see #scrollBy(int, int)
18634      * @see #scrollTo(int, int)
18635      * @see #isHorizontalScrollBarEnabled()
18636      * @see #isVerticalScrollBarEnabled()
18637      * @see #setHorizontalScrollBarEnabled(boolean)
18638      * @see #setVerticalScrollBarEnabled(boolean)
18639      */
awakenScrollBars(int startDelay)18640     protected boolean awakenScrollBars(int startDelay) {
18641         return awakenScrollBars(startDelay, true);
18642     }
18643 
18644     /**
18645      * <p>
18646      * Trigger the scrollbars to draw. When invoked this method starts an
18647      * animation to fade the scrollbars out after a fixed delay. If a subclass
18648      * provides animated scrolling, the start delay should equal the duration of
18649      * the scrolling animation.
18650      * </p>
18651      *
18652      * <p>
18653      * The animation starts only if at least one of the scrollbars is enabled,
18654      * as specified by {@link #isHorizontalScrollBarEnabled()} and
18655      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18656      * this method returns true, and false otherwise. If the animation is
18657      * started, this method calls {@link #invalidate()} if the invalidate parameter
18658      * is set to true; in that case the caller
18659      * should not call {@link #invalidate()}.
18660      * </p>
18661      *
18662      * <p>
18663      * This method should be invoked every time a subclass directly updates the
18664      * scroll parameters.
18665      * </p>
18666      *
18667      * @param startDelay the delay, in milliseconds, after which the animation
18668      *        should start; when the delay is 0, the animation starts
18669      *        immediately
18670      *
18671      * @param invalidate Whether this method should call invalidate
18672      *
18673      * @return true if the animation is played, false otherwise
18674      *
18675      * @see #scrollBy(int, int)
18676      * @see #scrollTo(int, int)
18677      * @see #isHorizontalScrollBarEnabled()
18678      * @see #isVerticalScrollBarEnabled()
18679      * @see #setHorizontalScrollBarEnabled(boolean)
18680      * @see #setVerticalScrollBarEnabled(boolean)
18681      */
awakenScrollBars(int startDelay, boolean invalidate)18682     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
18683         final ScrollabilityCache scrollCache = mScrollCache;
18684 
18685         if (scrollCache == null || !scrollCache.fadeScrollBars) {
18686             return false;
18687         }
18688 
18689         if (scrollCache.scrollBar == null) {
18690             scrollCache.scrollBar = new ScrollBarDrawable();
18691             scrollCache.scrollBar.setState(getDrawableState());
18692             scrollCache.scrollBar.setCallback(this);
18693         }
18694 
18695         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
18696 
18697             if (invalidate) {
18698                 // Invalidate to show the scrollbars
18699                 postInvalidateOnAnimation();
18700             }
18701 
18702             if (scrollCache.state == ScrollabilityCache.OFF) {
18703                 // FIXME: this is copied from WindowManagerService.
18704                 // We should get this value from the system when it
18705                 // is possible to do so.
18706                 final int KEY_REPEAT_FIRST_DELAY = 750;
18707                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
18708             }
18709 
18710             // Tell mScrollCache when we should start fading. This may
18711             // extend the fade start time if one was already scheduled
18712             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
18713             scrollCache.fadeStartTime = fadeStartTime;
18714             scrollCache.state = ScrollabilityCache.ON;
18715 
18716             // Schedule our fader to run, unscheduling any old ones first
18717             if (mAttachInfo != null) {
18718                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
18719                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
18720             }
18721 
18722             return true;
18723         }
18724 
18725         return false;
18726     }
18727 
18728     /**
18729      * Do not invalidate views which are not visible and which are not running an animation. They
18730      * will not get drawn and they should not set dirty flags as if they will be drawn
18731      */
skipInvalidate()18732     private boolean skipInvalidate() {
18733         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
18734                 (!(mParent instanceof ViewGroup) ||
18735                         !((ViewGroup) mParent).isViewTransitioning(this));
18736     }
18737 
18738     /**
18739      * Mark the area defined by dirty as needing to be drawn. If the view is
18740      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18741      * point in the future.
18742      * <p>
18743      * This must be called from a UI thread. To call from a non-UI thread, call
18744      * {@link #postInvalidate()}.
18745      * <p>
18746      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
18747      * {@code dirty}.
18748      *
18749      * @param dirty the rectangle representing the bounds of the dirty region
18750      *
18751      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18752      * the importance of the dirty rectangle. In API 21 the given rectangle is
18753      * ignored entirely in favor of an internally-calculated area instead.
18754      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18755      */
18756     @Deprecated
invalidate(Rect dirty)18757     public void invalidate(Rect dirty) {
18758         final int scrollX = mScrollX;
18759         final int scrollY = mScrollY;
18760         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
18761                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
18762     }
18763 
18764     /**
18765      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
18766      * coordinates of the dirty rect are relative to the view. If the view is
18767      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18768      * point in the future.
18769      * <p>
18770      * This must be called from a UI thread. To call from a non-UI thread, call
18771      * {@link #postInvalidate()}.
18772      *
18773      * @param l the left position of the dirty region
18774      * @param t the top position of the dirty region
18775      * @param r the right position of the dirty region
18776      * @param b the bottom position of the dirty region
18777      *
18778      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18779      * the importance of the dirty rectangle. In API 21 the given rectangle is
18780      * ignored entirely in favor of an internally-calculated area instead.
18781      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18782      */
18783     @Deprecated
invalidate(int l, int t, int r, int b)18784     public void invalidate(int l, int t, int r, int b) {
18785         final int scrollX = mScrollX;
18786         final int scrollY = mScrollY;
18787         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
18788     }
18789 
18790     /**
18791      * Invalidate the whole view. If the view is visible,
18792      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
18793      * the future.
18794      * <p>
18795      * This must be called from a UI thread. To call from a non-UI thread, call
18796      * {@link #postInvalidate()}.
18797      */
invalidate()18798     public void invalidate() {
18799         invalidate(true);
18800     }
18801 
18802     /**
18803      * This is where the invalidate() work actually happens. A full invalidate()
18804      * causes the drawing cache to be invalidated, but this function can be
18805      * called with invalidateCache set to false to skip that invalidation step
18806      * for cases that do not need it (for example, a component that remains at
18807      * the same dimensions with the same content).
18808      *
18809      * @param invalidateCache Whether the drawing cache for this view should be
18810      *            invalidated as well. This is usually true for a full
18811      *            invalidate, but may be set to false if the View's contents or
18812      *            dimensions have not changed.
18813      * @hide
18814      */
18815     @UnsupportedAppUsage
invalidate(boolean invalidateCache)18816     public void invalidate(boolean invalidateCache) {
18817         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
18818     }
18819 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)18820     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
18821             boolean fullInvalidate) {
18822         if (mGhostView != null) {
18823             mGhostView.invalidate(true);
18824             return;
18825         }
18826 
18827         if (skipInvalidate()) {
18828             return;
18829         }
18830 
18831         // Reset content capture caches
18832         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
18833         mContentCaptureSessionCached = false;
18834 
18835         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
18836                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
18837                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
18838                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
18839             if (fullInvalidate) {
18840                 mLastIsOpaque = isOpaque();
18841                 mPrivateFlags &= ~PFLAG_DRAWN;
18842             }
18843 
18844             mPrivateFlags |= PFLAG_DIRTY;
18845 
18846             if (invalidateCache) {
18847                 mPrivateFlags |= PFLAG_INVALIDATED;
18848                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18849             }
18850 
18851             // Propagate the damage rectangle to the parent view.
18852             final AttachInfo ai = mAttachInfo;
18853             final ViewParent p = mParent;
18854             if (p != null && ai != null && l < r && t < b) {
18855                 final Rect damage = ai.mTmpInvalRect;
18856                 damage.set(l, t, r, b);
18857                 p.invalidateChild(this, damage);
18858             }
18859 
18860             // Damage the entire projection receiver, if necessary.
18861             if (mBackground != null && mBackground.isProjected()) {
18862                 final View receiver = getProjectionReceiver();
18863                 if (receiver != null) {
18864                     receiver.damageInParent();
18865                 }
18866             }
18867         }
18868     }
18869 
18870     /**
18871      * @return this view's projection receiver, or {@code null} if none exists
18872      */
getProjectionReceiver()18873     private View getProjectionReceiver() {
18874         ViewParent p = getParent();
18875         while (p != null && p instanceof View) {
18876             final View v = (View) p;
18877             if (v.isProjectionReceiver()) {
18878                 return v;
18879             }
18880             p = p.getParent();
18881         }
18882 
18883         return null;
18884     }
18885 
18886     /**
18887      * @return whether the view is a projection receiver
18888      */
isProjectionReceiver()18889     private boolean isProjectionReceiver() {
18890         return mBackground != null;
18891     }
18892 
18893     /**
18894      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
18895      * set any flags or handle all of the cases handled by the default invalidation methods.
18896      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
18897      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
18898      * walk up the hierarchy, transforming the dirty rect as necessary.
18899      *
18900      * The method also handles normal invalidation logic if display list properties are not
18901      * being used in this view. The invalidateParent and forceRedraw flags are used by that
18902      * backup approach, to handle these cases used in the various property-setting methods.
18903      *
18904      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
18905      * are not being used in this view
18906      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
18907      * list properties are not being used in this view
18908      */
18909     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)18910     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
18911         if (!isHardwareAccelerated()
18912                 || !mRenderNode.hasDisplayList()
18913                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
18914             if (invalidateParent) {
18915                 invalidateParentCaches();
18916             }
18917             if (forceRedraw) {
18918                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18919             }
18920             invalidate(false);
18921         } else {
18922             damageInParent();
18923         }
18924     }
18925 
18926     /**
18927      * Tells the parent view to damage this view's bounds.
18928      *
18929      * @hide
18930      */
damageInParent()18931     protected void damageInParent() {
18932         if (mParent != null && mAttachInfo != null) {
18933             mParent.onDescendantInvalidated(this, this);
18934         }
18935     }
18936 
18937     /**
18938      * Used to indicate that the parent of this view should clear its caches. This functionality
18939      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18940      * which is necessary when various parent-managed properties of the view change, such as
18941      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
18942      * clears the parent caches and does not causes an invalidate event.
18943      *
18944      * @hide
18945      */
18946     @UnsupportedAppUsage
invalidateParentCaches()18947     protected void invalidateParentCaches() {
18948         if (mParent instanceof View) {
18949             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
18950         }
18951     }
18952 
18953     /**
18954      * Used to indicate that the parent of this view should be invalidated. This functionality
18955      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18956      * which is necessary when various parent-managed properties of the view change, such as
18957      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
18958      * an invalidation event to the parent.
18959      *
18960      * @hide
18961      */
18962     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
invalidateParentIfNeeded()18963     protected void invalidateParentIfNeeded() {
18964         if (isHardwareAccelerated() && mParent instanceof View) {
18965             ((View) mParent).invalidate(true);
18966         }
18967     }
18968 
18969     /**
18970      * @hide
18971      */
invalidateParentIfNeededAndWasQuickRejected()18972     protected void invalidateParentIfNeededAndWasQuickRejected() {
18973         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
18974             // View was rejected last time it was drawn by its parent; this may have changed
18975             invalidateParentIfNeeded();
18976         }
18977     }
18978 
18979     /**
18980      * Indicates whether this View is opaque. An opaque View guarantees that it will
18981      * draw all the pixels overlapping its bounds using a fully opaque color.
18982      *
18983      * Subclasses of View should override this method whenever possible to indicate
18984      * whether an instance is opaque. Opaque Views are treated in a special way by
18985      * the View hierarchy, possibly allowing it to perform optimizations during
18986      * invalidate/draw passes.
18987      *
18988      * @return True if this View is guaranteed to be fully opaque, false otherwise.
18989      */
18990     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()18991     public boolean isOpaque() {
18992         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
18993                 getFinalAlpha() >= 1.0f;
18994     }
18995 
18996     /**
18997      * @hide
18998      */
18999     @UnsupportedAppUsage
computeOpaqueFlags()19000     protected void computeOpaqueFlags() {
19001         // Opaque if:
19002         //   - Has a background
19003         //   - Background is opaque
19004         //   - Doesn't have scrollbars or scrollbars overlay
19005 
19006         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
19007             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
19008         } else {
19009             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
19010         }
19011 
19012         final int flags = mViewFlags;
19013         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
19014                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
19015                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
19016             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
19017         } else {
19018             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
19019         }
19020     }
19021 
19022     /**
19023      * @hide
19024      */
hasOpaqueScrollbars()19025     protected boolean hasOpaqueScrollbars() {
19026         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
19027     }
19028 
19029     /**
19030      * @return A handler associated with the thread running the View. This
19031      * handler can be used to pump events in the UI events queue.
19032      */
getHandler()19033     public Handler getHandler() {
19034         final AttachInfo attachInfo = mAttachInfo;
19035         if (attachInfo != null) {
19036             return attachInfo.mHandler;
19037         }
19038         return null;
19039     }
19040 
19041     /**
19042      * Returns the queue of runnable for this view.
19043      *
19044      * @return the queue of runnables for this view
19045      */
getRunQueue()19046     private HandlerActionQueue getRunQueue() {
19047         if (mRunQueue == null) {
19048             mRunQueue = new HandlerActionQueue();
19049         }
19050         return mRunQueue;
19051     }
19052 
19053     /**
19054      * Gets the view root associated with the View.
19055      * @return The view root, or null if none.
19056      * @hide
19057      */
19058     @UnsupportedAppUsage
getViewRootImpl()19059     public ViewRootImpl getViewRootImpl() {
19060         if (mAttachInfo != null) {
19061             return mAttachInfo.mViewRootImpl;
19062         }
19063         return null;
19064     }
19065 
19066     /**
19067      * @hide
19068      */
19069     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getThreadedRenderer()19070     public ThreadedRenderer getThreadedRenderer() {
19071         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
19072     }
19073 
19074     /**
19075      * <p>Causes the Runnable to be added to the message queue.
19076      * The runnable will be run on the user interface thread.</p>
19077      *
19078      * @param action The Runnable that will be executed.
19079      *
19080      * @return Returns true if the Runnable was successfully placed in to the
19081      *         message queue.  Returns false on failure, usually because the
19082      *         looper processing the message queue is exiting.
19083      *
19084      * @see #postDelayed
19085      * @see #removeCallbacks
19086      */
post(Runnable action)19087     public boolean post(Runnable action) {
19088         final AttachInfo attachInfo = mAttachInfo;
19089         if (attachInfo != null) {
19090             return attachInfo.mHandler.post(action);
19091         }
19092 
19093         // Postpone the runnable until we know on which thread it needs to run.
19094         // Assume that the runnable will be successfully placed after attach.
19095         getRunQueue().post(action);
19096         return true;
19097     }
19098 
19099     /**
19100      * <p>Causes the Runnable to be added to the message queue, to be run
19101      * after the specified amount of time elapses.
19102      * The runnable will be run on the user interface thread.</p>
19103      *
19104      * @param action The Runnable that will be executed.
19105      * @param delayMillis The delay (in milliseconds) until the Runnable
19106      *        will be executed.
19107      *
19108      * @return true if the Runnable was successfully placed in to the
19109      *         message queue.  Returns false on failure, usually because the
19110      *         looper processing the message queue is exiting.  Note that a
19111      *         result of true does not mean the Runnable will be processed --
19112      *         if the looper is quit before the delivery time of the message
19113      *         occurs then the message will be dropped.
19114      *
19115      * @see #post
19116      * @see #removeCallbacks
19117      */
postDelayed(Runnable action, long delayMillis)19118     public boolean postDelayed(Runnable action, long delayMillis) {
19119         final AttachInfo attachInfo = mAttachInfo;
19120         if (attachInfo != null) {
19121             return attachInfo.mHandler.postDelayed(action, delayMillis);
19122         }
19123 
19124         // Postpone the runnable until we know on which thread it needs to run.
19125         // Assume that the runnable will be successfully placed after attach.
19126         getRunQueue().postDelayed(action, delayMillis);
19127         return true;
19128     }
19129 
19130     /**
19131      * <p>Causes the Runnable to execute on the next animation time step.
19132      * The runnable will be run on the user interface thread.</p>
19133      *
19134      * @param action The Runnable that will be executed.
19135      *
19136      * @see #postOnAnimationDelayed
19137      * @see #removeCallbacks
19138      */
postOnAnimation(Runnable action)19139     public void postOnAnimation(Runnable action) {
19140         final AttachInfo attachInfo = mAttachInfo;
19141         if (attachInfo != null) {
19142             attachInfo.mViewRootImpl.mChoreographer.postCallback(
19143                     Choreographer.CALLBACK_ANIMATION, action, null);
19144         } else {
19145             // Postpone the runnable until we know
19146             // on which thread it needs to run.
19147             getRunQueue().post(action);
19148         }
19149     }
19150 
19151     /**
19152      * <p>Causes the Runnable to execute on the next animation time step,
19153      * after the specified amount of time elapses.
19154      * The runnable will be run on the user interface thread.</p>
19155      *
19156      * @param action The Runnable that will be executed.
19157      * @param delayMillis The delay (in milliseconds) until the Runnable
19158      *        will be executed.
19159      *
19160      * @see #postOnAnimation
19161      * @see #removeCallbacks
19162      */
postOnAnimationDelayed(Runnable action, long delayMillis)19163     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
19164         final AttachInfo attachInfo = mAttachInfo;
19165         if (attachInfo != null) {
19166             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19167                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
19168         } else {
19169             // Postpone the runnable until we know
19170             // on which thread it needs to run.
19171             getRunQueue().postDelayed(action, delayMillis);
19172         }
19173     }
19174 
19175     /**
19176      * <p>Removes the specified Runnable from the message queue.</p>
19177      *
19178      * @param action The Runnable to remove from the message handling queue
19179      *
19180      * @return true if this view could ask the Handler to remove the Runnable,
19181      *         false otherwise. When the returned value is true, the Runnable
19182      *         may or may not have been actually removed from the message queue
19183      *         (for instance, if the Runnable was not in the queue already.)
19184      *
19185      * @see #post
19186      * @see #postDelayed
19187      * @see #postOnAnimation
19188      * @see #postOnAnimationDelayed
19189      */
removeCallbacks(Runnable action)19190     public boolean removeCallbacks(Runnable action) {
19191         if (action != null) {
19192             final AttachInfo attachInfo = mAttachInfo;
19193             if (attachInfo != null) {
19194                 attachInfo.mHandler.removeCallbacks(action);
19195                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19196                         Choreographer.CALLBACK_ANIMATION, action, null);
19197             }
19198             getRunQueue().removeCallbacks(action);
19199         }
19200         return true;
19201     }
19202 
19203     /**
19204      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
19205      * Use this to invalidate the View from a non-UI thread.</p>
19206      *
19207      * <p>This method can be invoked from outside of the UI thread
19208      * only when this View is attached to a window.</p>
19209      *
19210      * @see #invalidate()
19211      * @see #postInvalidateDelayed(long)
19212      */
postInvalidate()19213     public void postInvalidate() {
19214         postInvalidateDelayed(0);
19215     }
19216 
19217     /**
19218      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
19219      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
19220      *
19221      * <p>This method can be invoked from outside of the UI thread
19222      * only when this View is attached to a window.</p>
19223      *
19224      * @param left The left coordinate of the rectangle to invalidate.
19225      * @param top The top coordinate of the rectangle to invalidate.
19226      * @param right The right coordinate of the rectangle to invalidate.
19227      * @param bottom The bottom coordinate of the rectangle to invalidate.
19228      *
19229      * @see #invalidate(int, int, int, int)
19230      * @see #invalidate(Rect)
19231      * @see #postInvalidateDelayed(long, int, int, int, int)
19232      */
postInvalidate(int left, int top, int right, int bottom)19233     public void postInvalidate(int left, int top, int right, int bottom) {
19234         postInvalidateDelayed(0, left, top, right, bottom);
19235     }
19236 
19237     /**
19238      * <p>Cause an invalidate to happen on a subsequent cycle through the event
19239      * loop. Waits for the specified amount of time.</p>
19240      *
19241      * <p>This method can be invoked from outside of the UI thread
19242      * only when this View is attached to a window.</p>
19243      *
19244      * @param delayMilliseconds the duration in milliseconds to delay the
19245      *         invalidation by
19246      *
19247      * @see #invalidate()
19248      * @see #postInvalidate()
19249      */
postInvalidateDelayed(long delayMilliseconds)19250     public void postInvalidateDelayed(long delayMilliseconds) {
19251         // We try only with the AttachInfo because there's no point in invalidating
19252         // if we are not attached to our window
19253         final AttachInfo attachInfo = mAttachInfo;
19254         if (attachInfo != null) {
19255             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
19256         }
19257     }
19258 
19259     /**
19260      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
19261      * through the event loop. Waits for the specified amount of time.</p>
19262      *
19263      * <p>This method can be invoked from outside of the UI thread
19264      * only when this View is attached to a window.</p>
19265      *
19266      * @param delayMilliseconds the duration in milliseconds to delay the
19267      *         invalidation by
19268      * @param left The left coordinate of the rectangle to invalidate.
19269      * @param top The top coordinate of the rectangle to invalidate.
19270      * @param right The right coordinate of the rectangle to invalidate.
19271      * @param bottom The bottom coordinate of the rectangle to invalidate.
19272      *
19273      * @see #invalidate(int, int, int, int)
19274      * @see #invalidate(Rect)
19275      * @see #postInvalidate(int, int, int, int)
19276      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)19277     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
19278             int right, int bottom) {
19279 
19280         // We try only with the AttachInfo because there's no point in invalidating
19281         // if we are not attached to our window
19282         final AttachInfo attachInfo = mAttachInfo;
19283         if (attachInfo != null) {
19284             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19285             info.target = this;
19286             info.left = left;
19287             info.top = top;
19288             info.right = right;
19289             info.bottom = bottom;
19290 
19291             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
19292         }
19293     }
19294 
19295     /**
19296      * <p>Cause an invalidate to happen on the next animation time step, typically the
19297      * next display frame.</p>
19298      *
19299      * <p>This method can be invoked from outside of the UI thread
19300      * only when this View is attached to a window.</p>
19301      *
19302      * @see #invalidate()
19303      */
postInvalidateOnAnimation()19304     public void postInvalidateOnAnimation() {
19305         // We try only with the AttachInfo because there's no point in invalidating
19306         // if we are not attached to our window
19307         final AttachInfo attachInfo = mAttachInfo;
19308         if (attachInfo != null) {
19309             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
19310         }
19311     }
19312 
19313     /**
19314      * <p>Cause an invalidate of the specified area to happen on the next animation
19315      * time step, typically the next display frame.</p>
19316      *
19317      * <p>This method can be invoked from outside of the UI thread
19318      * only when this View is attached to a window.</p>
19319      *
19320      * @param left The left coordinate of the rectangle to invalidate.
19321      * @param top The top coordinate of the rectangle to invalidate.
19322      * @param right The right coordinate of the rectangle to invalidate.
19323      * @param bottom The bottom coordinate of the rectangle to invalidate.
19324      *
19325      * @see #invalidate(int, int, int, int)
19326      * @see #invalidate(Rect)
19327      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)19328     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
19329         // We try only with the AttachInfo because there's no point in invalidating
19330         // if we are not attached to our window
19331         final AttachInfo attachInfo = mAttachInfo;
19332         if (attachInfo != null) {
19333             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19334             info.target = this;
19335             info.left = left;
19336             info.top = top;
19337             info.right = right;
19338             info.bottom = bottom;
19339 
19340             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
19341         }
19342     }
19343 
19344     /**
19345      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
19346      * This event is sent at most once every
19347      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
19348      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)19349     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
19350         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
19351             AccessibilityEvent event =
19352                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
19353             event.setScrollDeltaX(dx);
19354             event.setScrollDeltaY(dy);
19355             sendAccessibilityEventUnchecked(event);
19356         }
19357     }
19358 
19359     /**
19360      * Called by a parent to request that a child update its values for mScrollX
19361      * and mScrollY if necessary. This will typically be done if the child is
19362      * animating a scroll using a {@link android.widget.Scroller Scroller}
19363      * object.
19364      */
computeScroll()19365     public void computeScroll() {
19366     }
19367 
19368     /**
19369      * <p>Indicate whether the horizontal edges are faded when the view is
19370      * scrolled horizontally.</p>
19371      *
19372      * @return true if the horizontal edges should are faded on scroll, false
19373      *         otherwise
19374      *
19375      * @see #setHorizontalFadingEdgeEnabled(boolean)
19376      *
19377      * @attr ref android.R.styleable#View_requiresFadingEdge
19378      */
isHorizontalFadingEdgeEnabled()19379     public boolean isHorizontalFadingEdgeEnabled() {
19380         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
19381     }
19382 
19383     /**
19384      * <p>Define whether the horizontal edges should be faded when this view
19385      * is scrolled horizontally.</p>
19386      *
19387      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
19388      *                                    be faded when the view is scrolled
19389      *                                    horizontally
19390      *
19391      * @see #isHorizontalFadingEdgeEnabled()
19392      *
19393      * @attr ref android.R.styleable#View_requiresFadingEdge
19394      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)19395     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
19396         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
19397             if (horizontalFadingEdgeEnabled) {
19398                 initScrollCache();
19399             }
19400 
19401             mViewFlags ^= FADING_EDGE_HORIZONTAL;
19402         }
19403     }
19404 
19405     /**
19406      * <p>Indicate whether the vertical edges are faded when the view is
19407      * scrolled horizontally.</p>
19408      *
19409      * @return true if the vertical edges should are faded on scroll, false
19410      *         otherwise
19411      *
19412      * @see #setVerticalFadingEdgeEnabled(boolean)
19413      *
19414      * @attr ref android.R.styleable#View_requiresFadingEdge
19415      */
isVerticalFadingEdgeEnabled()19416     public boolean isVerticalFadingEdgeEnabled() {
19417         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
19418     }
19419 
19420     /**
19421      * <p>Define whether the vertical edges should be faded when this view
19422      * is scrolled vertically.</p>
19423      *
19424      * @param verticalFadingEdgeEnabled true if the vertical edges should
19425      *                                  be faded when the view is scrolled
19426      *                                  vertically
19427      *
19428      * @see #isVerticalFadingEdgeEnabled()
19429      *
19430      * @attr ref android.R.styleable#View_requiresFadingEdge
19431      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)19432     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
19433         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
19434             if (verticalFadingEdgeEnabled) {
19435                 initScrollCache();
19436             }
19437 
19438             mViewFlags ^= FADING_EDGE_VERTICAL;
19439         }
19440     }
19441 
19442     /**
19443      * Get the fading edge flags, used for inspection.
19444      *
19445      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
19446      *         or {@link #FADING_EDGE_HORIZONTAL}
19447      * @hide
19448      */
19449     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
19450             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
19451             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
19452             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
19453     })
getFadingEdge()19454     public int getFadingEdge() {
19455         return mViewFlags & FADING_EDGE_MASK;
19456     }
19457 
19458     /**
19459      * Get the fading edge length, used for inspection
19460      *
19461      * @return The fading edge length or 0
19462      * @hide
19463      */
19464     @InspectableProperty
getFadingEdgeLength()19465     public int getFadingEdgeLength() {
19466         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
19467             return mScrollCache.fadingEdgeLength;
19468         }
19469         return 0;
19470     }
19471 
19472     /**
19473      * Returns the strength, or intensity, of the top faded edge. The strength is
19474      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19475      * returns 0.0 or 1.0 but no value in between.
19476      *
19477      * Subclasses should override this method to provide a smoother fade transition
19478      * when scrolling occurs.
19479      *
19480      * @return the intensity of the top fade as a float between 0.0f and 1.0f
19481      */
getTopFadingEdgeStrength()19482     protected float getTopFadingEdgeStrength() {
19483         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
19484     }
19485 
19486     /**
19487      * Returns the strength, or intensity, of the bottom faded edge. The strength is
19488      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19489      * returns 0.0 or 1.0 but no value in between.
19490      *
19491      * Subclasses should override this method to provide a smoother fade transition
19492      * when scrolling occurs.
19493      *
19494      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
19495      */
getBottomFadingEdgeStrength()19496     protected float getBottomFadingEdgeStrength() {
19497         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
19498                 computeVerticalScrollRange() ? 1.0f : 0.0f;
19499     }
19500 
19501     /**
19502      * Returns the strength, or intensity, of the left faded edge. The strength is
19503      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19504      * returns 0.0 or 1.0 but no value in between.
19505      *
19506      * Subclasses should override this method to provide a smoother fade transition
19507      * when scrolling occurs.
19508      *
19509      * @return the intensity of the left fade as a float between 0.0f and 1.0f
19510      */
getLeftFadingEdgeStrength()19511     protected float getLeftFadingEdgeStrength() {
19512         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
19513     }
19514 
19515     /**
19516      * Returns the strength, or intensity, of the right faded edge. The strength is
19517      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19518      * returns 0.0 or 1.0 but no value in between.
19519      *
19520      * Subclasses should override this method to provide a smoother fade transition
19521      * when scrolling occurs.
19522      *
19523      * @return the intensity of the right fade as a float between 0.0f and 1.0f
19524      */
getRightFadingEdgeStrength()19525     protected float getRightFadingEdgeStrength() {
19526         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
19527                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
19528     }
19529 
19530     /**
19531      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
19532      * scrollbar is not drawn by default.</p>
19533      *
19534      * @return true if the horizontal scrollbar should be painted, false
19535      *         otherwise
19536      *
19537      * @see #setHorizontalScrollBarEnabled(boolean)
19538      */
isHorizontalScrollBarEnabled()19539     public boolean isHorizontalScrollBarEnabled() {
19540         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
19541     }
19542 
19543     /**
19544      * <p>Define whether the horizontal scrollbar should be drawn or not. The
19545      * scrollbar is not drawn by default.</p>
19546      *
19547      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
19548      *                                   be painted
19549      *
19550      * @see #isHorizontalScrollBarEnabled()
19551      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)19552     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
19553         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
19554             mViewFlags ^= SCROLLBARS_HORIZONTAL;
19555             computeOpaqueFlags();
19556             resolvePadding();
19557         }
19558     }
19559 
19560     /**
19561      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
19562      * scrollbar is not drawn by default.</p>
19563      *
19564      * @return true if the vertical scrollbar should be painted, false
19565      *         otherwise
19566      *
19567      * @see #setVerticalScrollBarEnabled(boolean)
19568      */
isVerticalScrollBarEnabled()19569     public boolean isVerticalScrollBarEnabled() {
19570         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
19571     }
19572 
19573     /**
19574      * <p>Define whether the vertical scrollbar should be drawn or not. The
19575      * scrollbar is not drawn by default.</p>
19576      *
19577      * @param verticalScrollBarEnabled true if the vertical scrollbar should
19578      *                                 be painted
19579      *
19580      * @see #isVerticalScrollBarEnabled()
19581      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)19582     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
19583         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
19584             mViewFlags ^= SCROLLBARS_VERTICAL;
19585             computeOpaqueFlags();
19586             resolvePadding();
19587         }
19588     }
19589 
19590     /**
19591      * @hide
19592      */
19593     @UnsupportedAppUsage
recomputePadding()19594     protected void recomputePadding() {
19595         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
19596     }
19597 
19598     /**
19599      * Define whether scrollbars will fade when the view is not scrolling.
19600      *
19601      * @param fadeScrollbars whether to enable fading
19602      *
19603      * @attr ref android.R.styleable#View_fadeScrollbars
19604      */
setScrollbarFadingEnabled(boolean fadeScrollbars)19605     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
19606         initScrollCache();
19607         final ScrollabilityCache scrollabilityCache = mScrollCache;
19608         scrollabilityCache.fadeScrollBars = fadeScrollbars;
19609         if (fadeScrollbars) {
19610             scrollabilityCache.state = ScrollabilityCache.OFF;
19611         } else {
19612             scrollabilityCache.state = ScrollabilityCache.ON;
19613         }
19614     }
19615 
19616     /**
19617      *
19618      * Returns true if scrollbars will fade when this view is not scrolling
19619      *
19620      * @return true if scrollbar fading is enabled
19621      *
19622      * @attr ref android.R.styleable#View_fadeScrollbars
19623      */
isScrollbarFadingEnabled()19624     public boolean isScrollbarFadingEnabled() {
19625         return mScrollCache != null && mScrollCache.fadeScrollBars;
19626     }
19627 
19628     /**
19629      *
19630      * Returns the delay before scrollbars fade.
19631      *
19632      * @return the delay before scrollbars fade
19633      *
19634      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
19635      */
19636     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()19637     public int getScrollBarDefaultDelayBeforeFade() {
19638         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
19639                 mScrollCache.scrollBarDefaultDelayBeforeFade;
19640     }
19641 
19642     /**
19643      * Define the delay before scrollbars fade.
19644      *
19645      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
19646      *
19647      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
19648      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)19649     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
19650         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
19651     }
19652 
19653     /**
19654      *
19655      * Returns the scrollbar fade duration.
19656      *
19657      * @return the scrollbar fade duration, in milliseconds
19658      *
19659      * @attr ref android.R.styleable#View_scrollbarFadeDuration
19660      */
19661     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()19662     public int getScrollBarFadeDuration() {
19663         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
19664                 mScrollCache.scrollBarFadeDuration;
19665     }
19666 
19667     /**
19668      * Define the scrollbar fade duration.
19669      *
19670      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
19671      *
19672      * @attr ref android.R.styleable#View_scrollbarFadeDuration
19673      */
setScrollBarFadeDuration(int scrollBarFadeDuration)19674     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
19675         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
19676     }
19677 
19678     /**
19679      *
19680      * Returns the scrollbar size.
19681      *
19682      * @return the scrollbar size
19683      *
19684      * @attr ref android.R.styleable#View_scrollbarSize
19685      */
19686     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()19687     public int getScrollBarSize() {
19688         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
19689                 mScrollCache.scrollBarSize;
19690     }
19691 
19692     /**
19693      * Define the scrollbar size.
19694      *
19695      * @param scrollBarSize - the scrollbar size
19696      *
19697      * @attr ref android.R.styleable#View_scrollbarSize
19698      */
setScrollBarSize(int scrollBarSize)19699     public void setScrollBarSize(int scrollBarSize) {
19700         getScrollCache().scrollBarSize = scrollBarSize;
19701     }
19702 
19703     /**
19704      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
19705      * inset. When inset, they add to the padding of the view. And the scrollbars
19706      * can be drawn inside the padding area or on the edge of the view. For example,
19707      * if a view has a background drawable and you want to draw the scrollbars
19708      * inside the padding specified by the drawable, you can use
19709      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
19710      * appear at the edge of the view, ignoring the padding, then you can use
19711      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
19712      * @param style the style of the scrollbars. Should be one of
19713      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
19714      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
19715      * @see #SCROLLBARS_INSIDE_OVERLAY
19716      * @see #SCROLLBARS_INSIDE_INSET
19717      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19718      * @see #SCROLLBARS_OUTSIDE_INSET
19719      *
19720      * @attr ref android.R.styleable#View_scrollbarStyle
19721      */
setScrollBarStyle(@crollBarStyle int style)19722     public void setScrollBarStyle(@ScrollBarStyle int style) {
19723         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
19724             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
19725             computeOpaqueFlags();
19726             resolvePadding();
19727         }
19728     }
19729 
19730     /**
19731      * <p>Returns the current scrollbar style.</p>
19732      * @return the current scrollbar style
19733      * @see #SCROLLBARS_INSIDE_OVERLAY
19734      * @see #SCROLLBARS_INSIDE_INSET
19735      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19736      * @see #SCROLLBARS_OUTSIDE_INSET
19737      *
19738      * @attr ref android.R.styleable#View_scrollbarStyle
19739      */
19740     @ViewDebug.ExportedProperty(mapping = {
19741             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
19742             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
19743             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
19744             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
19745     })
19746     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
19747             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
19748             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
19749             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
19750             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
19751     })
19752     @ScrollBarStyle
getScrollBarStyle()19753     public int getScrollBarStyle() {
19754         return mViewFlags & SCROLLBARS_STYLE_MASK;
19755     }
19756 
19757     /**
19758      * <p>Compute the horizontal range that the horizontal scrollbar
19759      * represents.</p>
19760      *
19761      * <p>The range is expressed in arbitrary units that must be the same as the
19762      * units used by {@link #computeHorizontalScrollExtent()} and
19763      * {@link #computeHorizontalScrollOffset()}.</p>
19764      *
19765      * <p>The default range is the drawing width of this view.</p>
19766      *
19767      * @return the total horizontal range represented by the horizontal
19768      *         scrollbar
19769      *
19770      * @see #computeHorizontalScrollExtent()
19771      * @see #computeHorizontalScrollOffset()
19772      */
computeHorizontalScrollRange()19773     protected int computeHorizontalScrollRange() {
19774         return getWidth();
19775     }
19776 
19777     /**
19778      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
19779      * within the horizontal range. This value is used to compute the position
19780      * of the thumb within the scrollbar's track.</p>
19781      *
19782      * <p>The range is expressed in arbitrary units that must be the same as the
19783      * units used by {@link #computeHorizontalScrollRange()} and
19784      * {@link #computeHorizontalScrollExtent()}.</p>
19785      *
19786      * <p>The default offset is the scroll offset of this view.</p>
19787      *
19788      * @return the horizontal offset of the scrollbar's thumb
19789      *
19790      * @see #computeHorizontalScrollRange()
19791      * @see #computeHorizontalScrollExtent()
19792      */
computeHorizontalScrollOffset()19793     protected int computeHorizontalScrollOffset() {
19794         return mScrollX;
19795     }
19796 
19797     /**
19798      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
19799      * within the horizontal range. This value is used to compute the length
19800      * of the thumb within the scrollbar's track.</p>
19801      *
19802      * <p>The range is expressed in arbitrary units that must be the same as the
19803      * units used by {@link #computeHorizontalScrollRange()} and
19804      * {@link #computeHorizontalScrollOffset()}.</p>
19805      *
19806      * <p>The default extent is the drawing width of this view.</p>
19807      *
19808      * @return the horizontal extent of the scrollbar's thumb
19809      *
19810      * @see #computeHorizontalScrollRange()
19811      * @see #computeHorizontalScrollOffset()
19812      */
computeHorizontalScrollExtent()19813     protected int computeHorizontalScrollExtent() {
19814         return getWidth();
19815     }
19816 
19817     /**
19818      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
19819      *
19820      * <p>The range is expressed in arbitrary units that must be the same as the
19821      * units used by {@link #computeVerticalScrollExtent()} and
19822      * {@link #computeVerticalScrollOffset()}.</p>
19823      *
19824      * @return the total vertical range represented by the vertical scrollbar
19825      *
19826      * <p>The default range is the drawing height of this view.</p>
19827      *
19828      * @see #computeVerticalScrollExtent()
19829      * @see #computeVerticalScrollOffset()
19830      */
computeVerticalScrollRange()19831     protected int computeVerticalScrollRange() {
19832         return getHeight();
19833     }
19834 
19835     /**
19836      * <p>Compute the vertical offset of the vertical scrollbar's thumb
19837      * within the horizontal range. This value is used to compute the position
19838      * of the thumb within the scrollbar's track.</p>
19839      *
19840      * <p>The range is expressed in arbitrary units that must be the same as the
19841      * units used by {@link #computeVerticalScrollRange()} and
19842      * {@link #computeVerticalScrollExtent()}.</p>
19843      *
19844      * <p>The default offset is the scroll offset of this view.</p>
19845      *
19846      * @return the vertical offset of the scrollbar's thumb
19847      *
19848      * @see #computeVerticalScrollRange()
19849      * @see #computeVerticalScrollExtent()
19850      */
computeVerticalScrollOffset()19851     protected int computeVerticalScrollOffset() {
19852         return mScrollY;
19853     }
19854 
19855     /**
19856      * <p>Compute the vertical extent of the vertical scrollbar's thumb
19857      * within the vertical range. This value is used to compute the length
19858      * of the thumb within the scrollbar's track.</p>
19859      *
19860      * <p>The range is expressed in arbitrary units that must be the same as the
19861      * units used by {@link #computeVerticalScrollRange()} and
19862      * {@link #computeVerticalScrollOffset()}.</p>
19863      *
19864      * <p>The default extent is the drawing height of this view.</p>
19865      *
19866      * @return the vertical extent of the scrollbar's thumb
19867      *
19868      * @see #computeVerticalScrollRange()
19869      * @see #computeVerticalScrollOffset()
19870      */
computeVerticalScrollExtent()19871     protected int computeVerticalScrollExtent() {
19872         return getHeight();
19873     }
19874 
19875     /**
19876      * Check if this view can be scrolled horizontally in a certain direction.
19877      *
19878      * @param direction Negative to check scrolling left, positive to check scrolling right.
19879      * @return true if this view can be scrolled in the specified direction, false otherwise.
19880      */
canScrollHorizontally(int direction)19881     public boolean canScrollHorizontally(int direction) {
19882         final int offset = computeHorizontalScrollOffset();
19883         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
19884         if (range == 0) return false;
19885         if (direction < 0) {
19886             return offset > 0;
19887         } else {
19888             return offset < range - 1;
19889         }
19890     }
19891 
19892     /**
19893      * Check if this view can be scrolled vertically in a certain direction.
19894      *
19895      * @param direction Negative to check scrolling up, positive to check scrolling down.
19896      * @return true if this view can be scrolled in the specified direction, false otherwise.
19897      */
canScrollVertically(int direction)19898     public boolean canScrollVertically(int direction) {
19899         final int offset = computeVerticalScrollOffset();
19900         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
19901         if (range == 0) return false;
19902         if (direction < 0) {
19903             return offset > 0;
19904         } else {
19905             return offset < range - 1;
19906         }
19907     }
19908 
getScrollIndicatorBounds(@onNull Rect out)19909     void getScrollIndicatorBounds(@NonNull Rect out) {
19910         out.left = mScrollX;
19911         out.right = mScrollX + mRight - mLeft;
19912         out.top = mScrollY;
19913         out.bottom = mScrollY + mBottom - mTop;
19914     }
19915 
onDrawScrollIndicators(Canvas c)19916     private void onDrawScrollIndicators(Canvas c) {
19917         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
19918             // No scroll indicators enabled.
19919             return;
19920         }
19921 
19922         final Drawable dr = mScrollIndicatorDrawable;
19923         if (dr == null) {
19924             // Scroll indicators aren't supported here.
19925             return;
19926         }
19927 
19928         if (mAttachInfo == null) {
19929             // View is not attached.
19930             return;
19931         }
19932 
19933         final int h = dr.getIntrinsicHeight();
19934         final int w = dr.getIntrinsicWidth();
19935         final Rect rect = mAttachInfo.mTmpInvalRect;
19936         getScrollIndicatorBounds(rect);
19937 
19938         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
19939             final boolean canScrollUp = canScrollVertically(-1);
19940             if (canScrollUp) {
19941                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
19942                 dr.draw(c);
19943             }
19944         }
19945 
19946         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
19947             final boolean canScrollDown = canScrollVertically(1);
19948             if (canScrollDown) {
19949                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
19950                 dr.draw(c);
19951             }
19952         }
19953 
19954         final int leftRtl;
19955         final int rightRtl;
19956         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
19957             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
19958             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
19959         } else {
19960             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
19961             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
19962         }
19963 
19964         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
19965         if ((mPrivateFlags3 & leftMask) != 0) {
19966             final boolean canScrollLeft = canScrollHorizontally(-1);
19967             if (canScrollLeft) {
19968                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
19969                 dr.draw(c);
19970             }
19971         }
19972 
19973         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
19974         if ((mPrivateFlags3 & rightMask) != 0) {
19975             final boolean canScrollRight = canScrollHorizontally(1);
19976             if (canScrollRight) {
19977                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
19978                 dr.draw(c);
19979             }
19980         }
19981     }
19982 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19983     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
19984             @Nullable Rect touchBounds) {
19985         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19986         if (bounds == null) {
19987             return;
19988         }
19989         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19990         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
19991                 && !isVerticalScrollBarHidden();
19992         final int size = getHorizontalScrollbarHeight();
19993         final int verticalScrollBarGap = drawVerticalScrollBar ?
19994                 getVerticalScrollbarWidth() : 0;
19995         final int width = mRight - mLeft;
19996         final int height = mBottom - mTop;
19997         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
19998         bounds.left = mScrollX + (mPaddingLeft & inside);
19999         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
20000         bounds.bottom = bounds.top + size;
20001 
20002         if (touchBounds == null) {
20003             return;
20004         }
20005         if (touchBounds != bounds) {
20006             touchBounds.set(bounds);
20007         }
20008         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
20009         if (touchBounds.height() < minTouchTarget) {
20010             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
20011             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
20012             touchBounds.top = touchBounds.bottom - minTouchTarget;
20013         }
20014         if (touchBounds.width() < minTouchTarget) {
20015             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
20016             touchBounds.left -= adjust;
20017             touchBounds.right = touchBounds.left + minTouchTarget;
20018         }
20019     }
20020 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)20021     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
20022         if (mRoundScrollbarRenderer == null) {
20023             getStraightVerticalScrollBarBounds(bounds, touchBounds);
20024         } else {
20025             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
20026         }
20027     }
20028 
getRoundVerticalScrollBarBounds(Rect bounds)20029     private void getRoundVerticalScrollBarBounds(Rect bounds) {
20030         final int width = mRight - mLeft;
20031         final int height = mBottom - mTop;
20032         // Do not take padding into account as we always want the scrollbars
20033         // to hug the screen for round wearable devices.
20034         bounds.left = mScrollX;
20035         bounds.top = mScrollY;
20036         bounds.right = bounds.left + width;
20037         bounds.bottom = mScrollY + height;
20038     }
20039 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)20040     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
20041             @Nullable Rect touchBounds) {
20042         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
20043         if (bounds == null) {
20044             return;
20045         }
20046         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
20047         final int size = getVerticalScrollbarWidth();
20048         int verticalScrollbarPosition = mVerticalScrollbarPosition;
20049         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
20050             verticalScrollbarPosition = isLayoutRtl() ?
20051                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
20052         }
20053         final int width = mRight - mLeft;
20054         final int height = mBottom - mTop;
20055         switch (verticalScrollbarPosition) {
20056             default:
20057             case SCROLLBAR_POSITION_RIGHT:
20058                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
20059                 break;
20060             case SCROLLBAR_POSITION_LEFT:
20061                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
20062                 break;
20063         }
20064         bounds.top = mScrollY + (mPaddingTop & inside);
20065         bounds.right = bounds.left + size;
20066         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
20067 
20068         if (touchBounds == null) {
20069             return;
20070         }
20071         if (touchBounds != bounds) {
20072             touchBounds.set(bounds);
20073         }
20074         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
20075         if (touchBounds.width() < minTouchTarget) {
20076             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
20077             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
20078                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
20079                 touchBounds.left = touchBounds.right - minTouchTarget;
20080             } else {
20081                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
20082                 touchBounds.right = touchBounds.left + minTouchTarget;
20083             }
20084         }
20085         if (touchBounds.height() < minTouchTarget) {
20086             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
20087             touchBounds.top -= adjust;
20088             touchBounds.bottom = touchBounds.top + minTouchTarget;
20089         }
20090     }
20091 
20092     /**
20093      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
20094      * scrollbars are painted only if they have been awakened first.</p>
20095      *
20096      * @param canvas the canvas on which to draw the scrollbars
20097      *
20098      * @see #awakenScrollBars(int)
20099      */
onDrawScrollBars(Canvas canvas)20100     protected final void onDrawScrollBars(Canvas canvas) {
20101         // scrollbars are drawn only when the animation is running
20102         final ScrollabilityCache cache = mScrollCache;
20103 
20104         if (cache != null) {
20105 
20106             int state = cache.state;
20107 
20108             if (state == ScrollabilityCache.OFF) {
20109                 return;
20110             }
20111 
20112             boolean invalidate = false;
20113 
20114             if (state == ScrollabilityCache.FADING) {
20115                 // We're fading -- get our fade interpolation
20116                 if (cache.interpolatorValues == null) {
20117                     cache.interpolatorValues = new float[1];
20118                 }
20119 
20120                 float[] values = cache.interpolatorValues;
20121 
20122                 // Stops the animation if we're done
20123                 if (cache.scrollBarInterpolator.timeToValues(values) ==
20124                         Interpolator.Result.FREEZE_END) {
20125                     cache.state = ScrollabilityCache.OFF;
20126                 } else {
20127                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
20128                 }
20129 
20130                 // This will make the scroll bars inval themselves after
20131                 // drawing. We only want this when we're fading so that
20132                 // we prevent excessive redraws
20133                 invalidate = true;
20134             } else {
20135                 // We're just on -- but we may have been fading before so
20136                 // reset alpha
20137                 cache.scrollBar.mutate().setAlpha(255);
20138             }
20139 
20140             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
20141             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
20142                     && !isVerticalScrollBarHidden();
20143 
20144             // Fork out the scroll bar drawing for round wearable devices.
20145             if (mRoundScrollbarRenderer != null) {
20146                 if (drawVerticalScrollBar) {
20147                     final Rect bounds = cache.mScrollBarBounds;
20148                     getVerticalScrollBarBounds(bounds, null);
20149                     mRoundScrollbarRenderer.drawRoundScrollbars(
20150                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
20151                     if (invalidate) {
20152                         invalidate();
20153                     }
20154                 }
20155                 // Do not draw horizontal scroll bars for round wearable devices.
20156             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
20157                 final ScrollBarDrawable scrollBar = cache.scrollBar;
20158 
20159                 if (drawHorizontalScrollBar) {
20160                     scrollBar.setParameters(computeHorizontalScrollRange(),
20161                             computeHorizontalScrollOffset(),
20162                             computeHorizontalScrollExtent(), false);
20163                     final Rect bounds = cache.mScrollBarBounds;
20164                     getHorizontalScrollBarBounds(bounds, null);
20165                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
20166                             bounds.right, bounds.bottom);
20167                     if (invalidate) {
20168                         invalidate(bounds);
20169                     }
20170                 }
20171 
20172                 if (drawVerticalScrollBar) {
20173                     scrollBar.setParameters(computeVerticalScrollRange(),
20174                             computeVerticalScrollOffset(),
20175                             computeVerticalScrollExtent(), true);
20176                     final Rect bounds = cache.mScrollBarBounds;
20177                     getVerticalScrollBarBounds(bounds, null);
20178                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
20179                             bounds.right, bounds.bottom);
20180                     if (invalidate) {
20181                         invalidate(bounds);
20182                     }
20183                 }
20184             }
20185         }
20186     }
20187 
20188     /**
20189      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
20190      * FastScroller is visible.
20191      * @return whether to temporarily hide the vertical scrollbar
20192      * @hide
20193      */
isVerticalScrollBarHidden()20194     protected boolean isVerticalScrollBarHidden() {
20195         return false;
20196     }
20197 
20198     /**
20199      * <p>Draw the horizontal scrollbar if
20200      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
20201      *
20202      * @param canvas the canvas on which to draw the scrollbar
20203      * @param scrollBar the scrollbar's drawable
20204      *
20205      * @see #isHorizontalScrollBarEnabled()
20206      * @see #computeHorizontalScrollRange()
20207      * @see #computeHorizontalScrollExtent()
20208      * @see #computeHorizontalScrollOffset()
20209      * @hide
20210      */
20211     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)20212     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
20213             int l, int t, int r, int b) {
20214         scrollBar.setBounds(l, t, r, b);
20215         scrollBar.draw(canvas);
20216     }
20217 
20218     /**
20219      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
20220      * returns true.</p>
20221      *
20222      * @param canvas the canvas on which to draw the scrollbar
20223      * @param scrollBar the scrollbar's drawable
20224      *
20225      * @see #isVerticalScrollBarEnabled()
20226      * @see #computeVerticalScrollRange()
20227      * @see #computeVerticalScrollExtent()
20228      * @see #computeVerticalScrollOffset()
20229      * @hide
20230      */
20231     @UnsupportedAppUsage
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)20232     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
20233             int l, int t, int r, int b) {
20234         scrollBar.setBounds(l, t, r, b);
20235         scrollBar.draw(canvas);
20236     }
20237 
20238     /**
20239      * Implement this to do your drawing.
20240      *
20241      * @param canvas the canvas on which the background will be drawn
20242      */
onDraw(Canvas canvas)20243     protected void onDraw(Canvas canvas) {
20244     }
20245 
20246     /*
20247      * Caller is responsible for calling requestLayout if necessary.
20248      * (This allows addViewInLayout to not request a new layout.)
20249      */
20250     @UnsupportedAppUsage
assignParent(ViewParent parent)20251     void assignParent(ViewParent parent) {
20252         if (mParent == null) {
20253             mParent = parent;
20254         } else if (parent == null) {
20255             mParent = null;
20256         } else {
20257             throw new RuntimeException("view " + this + " being added, but"
20258                     + " it already has a parent");
20259         }
20260     }
20261 
20262     /**
20263      * This is called when the view is attached to a window.  At this point it
20264      * has a Surface and will start drawing.  Note that this function is
20265      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
20266      * however it may be called any time before the first onDraw -- including
20267      * before or after {@link #onMeasure(int, int)}.
20268      *
20269      * @see #onDetachedFromWindow()
20270      */
20271     @CallSuper
onAttachedToWindow()20272     protected void onAttachedToWindow() {
20273         if (mParent != null && (mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
20274             mParent.requestTransparentRegion(this);
20275         }
20276 
20277         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
20278 
20279         jumpDrawablesToCurrentState();
20280 
20281         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
20282         resetSubtreeAccessibilityStateChanged();
20283 
20284         // rebuild, since Outline not maintained while View is detached
20285         rebuildOutline();
20286 
20287         if (isFocused()) {
20288             notifyFocusChangeToImeFocusController(true /* hasFocus */);
20289         }
20290     }
20291 
20292     /**
20293      * Resolve all RTL related properties.
20294      *
20295      * @return true if resolution of RTL properties has been done
20296      *
20297      * @hide
20298      */
resolveRtlPropertiesIfNeeded()20299     public boolean resolveRtlPropertiesIfNeeded() {
20300         if (!needRtlPropertiesResolution()) return false;
20301 
20302         // Order is important here: LayoutDirection MUST be resolved first
20303         if (!isLayoutDirectionResolved()) {
20304             resolveLayoutDirection();
20305             resolveLayoutParams();
20306         }
20307         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
20308         if (!isTextDirectionResolved()) {
20309             resolveTextDirection();
20310         }
20311         if (!isTextAlignmentResolved()) {
20312             resolveTextAlignment();
20313         }
20314         // Should resolve Drawables before Padding because we need the layout direction of the
20315         // Drawable to correctly resolve Padding.
20316         if (!areDrawablesResolved()) {
20317             resolveDrawables();
20318         }
20319         if (!isPaddingResolved()) {
20320             resolvePadding();
20321         }
20322         onRtlPropertiesChanged(getLayoutDirection());
20323         return true;
20324     }
20325 
20326     /**
20327      * Reset resolution of all RTL related properties.
20328      *
20329      * @hide
20330      */
20331     @TestApi
resetRtlProperties()20332     public void resetRtlProperties() {
20333         resetResolvedLayoutDirection();
20334         resetResolvedTextDirection();
20335         resetResolvedTextAlignment();
20336         resetResolvedPadding();
20337         resetResolvedDrawables();
20338     }
20339 
20340     /**
20341      * @see #onScreenStateChanged(int)
20342      */
dispatchScreenStateChanged(int screenState)20343     void dispatchScreenStateChanged(int screenState) {
20344         onScreenStateChanged(screenState);
20345     }
20346 
20347     /**
20348      * This method is called whenever the state of the screen this view is
20349      * attached to changes. A state change will usually occurs when the screen
20350      * turns on or off (whether it happens automatically or the user does it
20351      * manually.)
20352      *
20353      * @param screenState The new state of the screen. Can be either
20354      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
20355      */
onScreenStateChanged(int screenState)20356     public void onScreenStateChanged(int screenState) {
20357     }
20358 
20359     /**
20360      * @see #onMovedToDisplay(int, Configuration)
20361      */
dispatchMovedToDisplay(Display display, Configuration config)20362     void dispatchMovedToDisplay(Display display, Configuration config) {
20363         mAttachInfo.mDisplay = display;
20364         mAttachInfo.mDisplayState = display.getState();
20365         onMovedToDisplay(display.getDisplayId(), config);
20366     }
20367 
20368     /**
20369      * Called by the system when the hosting activity is moved from one display to another without
20370      * recreation. This means that the activity is declared to handle all changes to configuration
20371      * that happened when it was switched to another display, so it wasn't destroyed and created
20372      * again.
20373      *
20374      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
20375      * applied configuration actually changed. It is up to app developer to choose whether to handle
20376      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
20377      * call.
20378      *
20379      * <p>Use this callback to track changes to the displays if some functionality relies on an
20380      * association with some display properties.
20381      *
20382      * @param displayId The id of the display to which the view was moved.
20383      * @param config Configuration of the resources on new display after move.
20384      *
20385      * @see #onConfigurationChanged(Configuration)
20386      * @hide
20387      */
onMovedToDisplay(int displayId, Configuration config)20388     public void onMovedToDisplay(int displayId, Configuration config) {
20389     }
20390 
20391     /**
20392      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
20393      */
20394     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hasRtlSupport()20395     private boolean hasRtlSupport() {
20396         return mContext.getApplicationInfo().hasRtlSupport();
20397     }
20398 
20399     /**
20400      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
20401      * RTL not supported)
20402      */
isRtlCompatibilityMode()20403     private boolean isRtlCompatibilityMode() {
20404         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
20405         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
20406     }
20407 
20408     /**
20409      * @return true if RTL properties need resolution.
20410      *
20411      */
needRtlPropertiesResolution()20412     private boolean needRtlPropertiesResolution() {
20413         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
20414     }
20415 
20416     /**
20417      * Called when any RTL property (layout direction or text direction or text alignment) has
20418      * been changed.
20419      *
20420      * Subclasses need to override this method to take care of cached information that depends on the
20421      * resolved layout direction, or to inform child views that inherit their layout direction.
20422      *
20423      * The default implementation does nothing.
20424      *
20425      * @param layoutDirection the direction of the layout
20426      *
20427      * @see #LAYOUT_DIRECTION_LTR
20428      * @see #LAYOUT_DIRECTION_RTL
20429      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)20430     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
20431     }
20432 
20433     /**
20434      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
20435      * that the parent directionality can and will be resolved before its children.
20436      *
20437      * @return true if resolution has been done, false otherwise.
20438      *
20439      * @hide
20440      */
resolveLayoutDirection()20441     public boolean resolveLayoutDirection() {
20442         // Clear any previous layout direction resolution
20443         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20444 
20445         if (hasRtlSupport()) {
20446             // Set resolved depending on layout direction
20447             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
20448                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
20449                 case LAYOUT_DIRECTION_INHERIT:
20450                     // We cannot resolve yet. LTR is by default and let the resolution happen again
20451                     // later to get the correct resolved value
20452                     if (!canResolveLayoutDirection()) return false;
20453 
20454                     // Parent has not yet resolved, LTR is still the default
20455                     try {
20456                         if (!mParent.isLayoutDirectionResolved()) return false;
20457 
20458                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
20459                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20460                         }
20461                     } catch (AbstractMethodError e) {
20462                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20463                                 " does not fully implement ViewParent", e);
20464                     }
20465                     break;
20466                 case LAYOUT_DIRECTION_RTL:
20467                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20468                     break;
20469                 case LAYOUT_DIRECTION_LOCALE:
20470                     if((LAYOUT_DIRECTION_RTL ==
20471                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
20472                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20473                     }
20474                     break;
20475                 default:
20476                     // Nothing to do, LTR by default
20477             }
20478         }
20479 
20480         // Set to resolved
20481         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
20482         return true;
20483     }
20484 
20485     /**
20486      * Check if layout direction resolution can be done.
20487      *
20488      * @return true if layout direction resolution can be done otherwise return false.
20489      */
canResolveLayoutDirection()20490     public boolean canResolveLayoutDirection() {
20491         switch (getRawLayoutDirection()) {
20492             case LAYOUT_DIRECTION_INHERIT:
20493                 if (mParent != null) {
20494                     try {
20495                         return mParent.canResolveLayoutDirection();
20496                     } catch (AbstractMethodError e) {
20497                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20498                                 " does not fully implement ViewParent", e);
20499                     }
20500                 }
20501                 return false;
20502 
20503             default:
20504                 return true;
20505         }
20506     }
20507 
20508     /**
20509      * Reset the resolved layout direction. Layout direction will be resolved during a call to
20510      * {@link #onMeasure(int, int)}.
20511      *
20512      * @hide
20513      */
20514     @TestApi
resetResolvedLayoutDirection()20515     public void resetResolvedLayoutDirection() {
20516         // Reset the current resolved bits
20517         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20518     }
20519 
20520     /**
20521      * @return true if the layout direction is inherited.
20522      *
20523      * @hide
20524      */
isLayoutDirectionInherited()20525     public boolean isLayoutDirectionInherited() {
20526         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
20527     }
20528 
20529     /**
20530      * @return true if layout direction has been resolved.
20531      */
isLayoutDirectionResolved()20532     public boolean isLayoutDirectionResolved() {
20533         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
20534     }
20535 
20536     /**
20537      * Return if padding has been resolved
20538      *
20539      * @hide
20540      */
20541     @UnsupportedAppUsage
isPaddingResolved()20542     boolean isPaddingResolved() {
20543         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
20544     }
20545 
20546     /**
20547      * Resolves padding depending on layout direction, if applicable, and
20548      * recomputes internal padding values to adjust for scroll bars.
20549      *
20550      * @hide
20551      */
20552     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resolvePadding()20553     public void resolvePadding() {
20554         final int resolvedLayoutDirection = getLayoutDirection();
20555 
20556         if (!isRtlCompatibilityMode()) {
20557             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
20558             // If start / end padding are defined, they will be resolved (hence overriding) to
20559             // left / right or right / left depending on the resolved layout direction.
20560             // If start / end padding are not defined, use the left / right ones.
20561             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
20562                 Rect padding = sThreadLocal.get();
20563                 if (padding == null) {
20564                     padding = new Rect();
20565                     sThreadLocal.set(padding);
20566                 }
20567                 mBackground.getPadding(padding);
20568                 if (!mLeftPaddingDefined) {
20569                     mUserPaddingLeftInitial = padding.left;
20570                 }
20571                 if (!mRightPaddingDefined) {
20572                     mUserPaddingRightInitial = padding.right;
20573                 }
20574             }
20575             switch (resolvedLayoutDirection) {
20576                 case LAYOUT_DIRECTION_RTL:
20577                     if (mUserPaddingStart != UNDEFINED_PADDING) {
20578                         mUserPaddingRight = mUserPaddingStart;
20579                     } else {
20580                         mUserPaddingRight = mUserPaddingRightInitial;
20581                     }
20582                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
20583                         mUserPaddingLeft = mUserPaddingEnd;
20584                     } else {
20585                         mUserPaddingLeft = mUserPaddingLeftInitial;
20586                     }
20587                     break;
20588                 case LAYOUT_DIRECTION_LTR:
20589                 default:
20590                     if (mUserPaddingStart != UNDEFINED_PADDING) {
20591                         mUserPaddingLeft = mUserPaddingStart;
20592                     } else {
20593                         mUserPaddingLeft = mUserPaddingLeftInitial;
20594                     }
20595                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
20596                         mUserPaddingRight = mUserPaddingEnd;
20597                     } else {
20598                         mUserPaddingRight = mUserPaddingRightInitial;
20599                     }
20600             }
20601 
20602             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
20603         }
20604 
20605         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
20606         onRtlPropertiesChanged(resolvedLayoutDirection);
20607 
20608         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
20609     }
20610 
20611     /**
20612      * Reset the resolved layout direction.
20613      *
20614      * @hide
20615      */
20616     @TestApi
resetResolvedPadding()20617     public void resetResolvedPadding() {
20618         resetResolvedPaddingInternal();
20619     }
20620 
20621     /**
20622      * Used when we only want to reset *this* view's padding and not trigger overrides
20623      * in ViewGroup that reset children too.
20624      */
resetResolvedPaddingInternal()20625     void resetResolvedPaddingInternal() {
20626         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
20627     }
20628 
20629     /**
20630      * This is called when the view is detached from a window.  At this point it
20631      * no longer has a surface for drawing.
20632      *
20633      * @see #onAttachedToWindow()
20634      */
20635     @CallSuper
onDetachedFromWindow()20636     protected void onDetachedFromWindow() {
20637     }
20638 
20639     /**
20640      * This is a framework-internal mirror of onDetachedFromWindow() that's called
20641      * after onDetachedFromWindow().
20642      *
20643      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
20644      * The super method should be called at the end of the overridden method to ensure
20645      * subclasses are destroyed first
20646      *
20647      * @hide
20648      */
20649     @CallSuper
20650     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDetachedFromWindowInternal()20651     protected void onDetachedFromWindowInternal() {
20652         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
20653         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
20654         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
20655 
20656         removeUnsetPressCallback();
20657         removeLongPressCallback();
20658         removePerformClickCallback();
20659         clearAccessibilityThrottles();
20660         stopNestedScroll();
20661 
20662         // Anything that started animating right before detach should already
20663         // be in its final state when re-attached.
20664         jumpDrawablesToCurrentState();
20665 
20666         destroyDrawingCache();
20667 
20668         cleanupDraw();
20669         mCurrentAnimation = null;
20670 
20671         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
20672             hideTooltip();
20673         }
20674 
20675         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
20676     }
20677 
cleanupDraw()20678     private void cleanupDraw() {
20679         resetDisplayList();
20680         if (mAttachInfo != null) {
20681             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
20682         }
20683     }
20684 
invalidateInheritedLayoutMode(int layoutModeOfRoot)20685     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
20686     }
20687 
20688     /**
20689      * @return The number of times this view has been attached to a window
20690      */
getWindowAttachCount()20691     protected int getWindowAttachCount() {
20692         return mWindowAttachCount;
20693     }
20694 
20695     /**
20696      * Retrieve a unique token identifying the window this view is attached to.
20697      * @return Return the window's token for use in
20698      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
20699      */
getWindowToken()20700     public IBinder getWindowToken() {
20701         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
20702     }
20703 
20704     /**
20705      * Retrieve the {@link WindowId} for the window this view is
20706      * currently attached to.
20707      */
getWindowId()20708     public WindowId getWindowId() {
20709         AttachInfo ai = mAttachInfo;
20710         if (ai == null) {
20711             return null;
20712         }
20713         if (ai.mWindowId == null) {
20714             try {
20715                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
20716                 if (ai.mIWindowId != null) {
20717                     ai.mWindowId = new WindowId(ai.mIWindowId);
20718                 }
20719             } catch (RemoteException e) {
20720             }
20721         }
20722         return ai.mWindowId;
20723     }
20724 
20725     /**
20726      * Retrieve a unique token identifying the top-level "real" window of
20727      * the window that this view is attached to.  That is, this is like
20728      * {@link #getWindowToken}, except if the window this view in is a panel
20729      * window (attached to another containing window), then the token of
20730      * the containing window is returned instead.
20731      *
20732      * @return Returns the associated window token, either
20733      * {@link #getWindowToken()} or the containing window's token.
20734      */
getApplicationWindowToken()20735     public IBinder getApplicationWindowToken() {
20736         AttachInfo ai = mAttachInfo;
20737         if (ai != null) {
20738             IBinder appWindowToken = ai.mPanelParentWindowToken;
20739             if (appWindowToken == null) {
20740                 appWindowToken = ai.mWindowToken;
20741             }
20742             return appWindowToken;
20743         }
20744         return null;
20745     }
20746 
20747     /**
20748      * Gets the logical display to which the view's window has been attached.
20749      *
20750      * @return The logical display, or null if the view is not currently attached to a window.
20751      */
getDisplay()20752     public Display getDisplay() {
20753         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
20754     }
20755 
20756     /**
20757      * Retrieve private session object this view hierarchy is using to
20758      * communicate with the window manager.
20759      * @return the session object to communicate with the window manager
20760      */
20761     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()20762     /*package*/ IWindowSession getWindowSession() {
20763         return mAttachInfo != null ? mAttachInfo.mSession : null;
20764     }
20765 
20766     /**
20767      * Return the window this view is currently attached to.
20768      * @hide
20769      */
getWindow()20770     protected IWindow getWindow() {
20771         return mAttachInfo != null ? mAttachInfo.mWindow : null;
20772     }
20773 
20774     /**
20775      * Return the visibility value of the least visible component passed.
20776      */
combineVisibility(int vis1, int vis2)20777     int combineVisibility(int vis1, int vis2) {
20778         // This works because VISIBLE < INVISIBLE < GONE.
20779         return Math.max(vis1, vis2);
20780     }
20781 
20782     /**
20783      * @param info the {@link android.view.View.AttachInfo} to associated with
20784      *        this view
20785      */
20786     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)20787     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
20788         mAttachInfo = info;
20789         if (mOverlay != null) {
20790             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
20791         }
20792         mWindowAttachCount++;
20793         // We will need to evaluate the drawable state at least once.
20794         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20795         if (mFloatingTreeObserver != null) {
20796             info.mTreeObserver.merge(mFloatingTreeObserver);
20797             mFloatingTreeObserver = null;
20798         }
20799 
20800         registerPendingFrameMetricsObservers();
20801 
20802         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
20803             mAttachInfo.mScrollContainers.add(this);
20804             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
20805         }
20806         // Transfer all pending runnables.
20807         if (mRunQueue != null) {
20808             mRunQueue.executeActions(info.mHandler);
20809             mRunQueue = null;
20810         }
20811         performCollectViewAttributes(mAttachInfo, visibility);
20812         onAttachedToWindow();
20813 
20814         ListenerInfo li = mListenerInfo;
20815         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20816                 li != null ? li.mOnAttachStateChangeListeners : null;
20817         if (listeners != null && listeners.size() > 0) {
20818             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20819             // perform the dispatching. The iterator is a safe guard against listeners that
20820             // could mutate the list by calling the various add/remove methods. This prevents
20821             // the array from being modified while we iterate it.
20822             for (OnAttachStateChangeListener listener : listeners) {
20823                 listener.onViewAttachedToWindow(this);
20824             }
20825         }
20826 
20827         int vis = info.mWindowVisibility;
20828         if (vis != GONE) {
20829             onWindowVisibilityChanged(vis);
20830             if (isShown()) {
20831                 // Calling onVisibilityAggregated directly here since the subtree will also
20832                 // receive dispatchAttachedToWindow and this same call
20833                 onVisibilityAggregated(vis == VISIBLE);
20834             }
20835         }
20836 
20837         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
20838         // As all views in the subtree will already receive dispatchAttachedToWindow
20839         // traversing the subtree again here is not desired.
20840         onVisibilityChanged(this, visibility);
20841 
20842         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
20843             // If nobody has evaluated the drawable state yet, then do it now.
20844             refreshDrawableState();
20845         }
20846         needGlobalAttributesUpdate(false);
20847 
20848         notifyEnterOrExitForAutoFillIfNeeded(true);
20849         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
20850     }
20851 
20852     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()20853     void dispatchDetachedFromWindow() {
20854         AttachInfo info = mAttachInfo;
20855         if (info != null) {
20856             int vis = info.mWindowVisibility;
20857             if (vis != GONE) {
20858                 onWindowVisibilityChanged(GONE);
20859                 if (isShown()) {
20860                     // Invoking onVisibilityAggregated directly here since the subtree
20861                     // will also receive detached from window
20862                     onVisibilityAggregated(false);
20863                 }
20864             }
20865         }
20866 
20867         onDetachedFromWindow();
20868         onDetachedFromWindowInternal();
20869 
20870         if (info != null) {
20871             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
20872         }
20873 
20874         ListenerInfo li = mListenerInfo;
20875         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20876                 li != null ? li.mOnAttachStateChangeListeners : null;
20877         if (listeners != null && listeners.size() > 0) {
20878             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20879             // perform the dispatching. The iterator is a safe guard against listeners that
20880             // could mutate the list by calling the various add/remove methods. This prevents
20881             // the array from being modified while we iterate it.
20882             for (OnAttachStateChangeListener listener : listeners) {
20883                 listener.onViewDetachedFromWindow(this);
20884             }
20885         }
20886 
20887         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
20888             mAttachInfo.mScrollContainers.remove(this);
20889             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
20890         }
20891 
20892         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
20893 
20894         mAttachInfo = null;
20895         if (mOverlay != null) {
20896             mOverlay.getOverlayView().dispatchDetachedFromWindow();
20897         }
20898 
20899         notifyEnterOrExitForAutoFillIfNeeded(false);
20900     }
20901 
20902     /**
20903      * Cancel any deferred high-level input events that were previously posted to the event queue.
20904      *
20905      * <p>Many views post high-level events such as click handlers to the event queue
20906      * to run deferred in order to preserve a desired user experience - clearing visible
20907      * pressed states before executing, etc. This method will abort any events of this nature
20908      * that are currently in flight.</p>
20909      *
20910      * <p>Custom views that generate their own high-level deferred input events should override
20911      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
20912      *
20913      * <p>This will also cancel pending input events for any child views.</p>
20914      *
20915      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
20916      * This will not impact newer events posted after this call that may occur as a result of
20917      * lower-level input events still waiting in the queue. If you are trying to prevent
20918      * double-submitted  events for the duration of some sort of asynchronous transaction
20919      * you should also take other steps to protect against unexpected double inputs e.g. calling
20920      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
20921      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
20922      */
cancelPendingInputEvents()20923     public final void cancelPendingInputEvents() {
20924         dispatchCancelPendingInputEvents();
20925     }
20926 
20927     /**
20928      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
20929      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
20930      */
dispatchCancelPendingInputEvents()20931     void dispatchCancelPendingInputEvents() {
20932         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
20933         onCancelPendingInputEvents();
20934         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
20935             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
20936                     " did not call through to super.onCancelPendingInputEvents()");
20937         }
20938     }
20939 
20940     /**
20941      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
20942      * a parent view.
20943      *
20944      * <p>This method is responsible for removing any pending high-level input events that were
20945      * posted to the event queue to run later. Custom view classes that post their own deferred
20946      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
20947      * {@link android.os.Handler} should override this method, call
20948      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
20949      * </p>
20950      */
onCancelPendingInputEvents()20951     public void onCancelPendingInputEvents() {
20952         removePerformClickCallback();
20953         cancelLongPress();
20954         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
20955     }
20956 
20957     /**
20958      * Store this view hierarchy's frozen state into the given container.
20959      *
20960      * @param container The SparseArray in which to save the view's state.
20961      *
20962      * @see #restoreHierarchyState(android.util.SparseArray)
20963      * @see #dispatchSaveInstanceState(android.util.SparseArray)
20964      * @see #onSaveInstanceState()
20965      */
saveHierarchyState(SparseArray<Parcelable> container)20966     public void saveHierarchyState(SparseArray<Parcelable> container) {
20967         dispatchSaveInstanceState(container);
20968     }
20969 
20970     /**
20971      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
20972      * this view and its children. May be overridden to modify how freezing happens to a
20973      * view's children; for example, some views may want to not store state for their children.
20974      *
20975      * @param container The SparseArray in which to save the view's state.
20976      *
20977      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20978      * @see #saveHierarchyState(android.util.SparseArray)
20979      * @see #onSaveInstanceState()
20980      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)20981     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
20982         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
20983             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
20984             Parcelable state = onSaveInstanceState();
20985             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
20986                 throw new IllegalStateException(
20987                         "Derived class did not call super.onSaveInstanceState()");
20988             }
20989             if (state != null) {
20990                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
20991                 // + ": " + state);
20992                 container.put(mID, state);
20993             }
20994         }
20995     }
20996 
20997     /**
20998      * Hook allowing a view to generate a representation of its internal state
20999      * that can later be used to create a new instance with that same state.
21000      * This state should only contain information that is not persistent or can
21001      * not be reconstructed later. For example, you will never store your
21002      * current position on screen because that will be computed again when a
21003      * new instance of the view is placed in its view hierarchy.
21004      * <p>
21005      * Some examples of things you may store here: the current cursor position
21006      * in a text view (but usually not the text itself since that is stored in a
21007      * content provider or other persistent storage), the currently selected
21008      * item in a list view.
21009      *
21010      * @return Returns a Parcelable object containing the view's current dynamic
21011      *         state, or null if there is nothing interesting to save.
21012      * @see #onRestoreInstanceState(Parcelable)
21013      * @see #saveHierarchyState(SparseArray)
21014      * @see #dispatchSaveInstanceState(SparseArray)
21015      * @see #setSaveEnabled(boolean)
21016      */
21017     @CallSuper
onSaveInstanceState()21018     @Nullable protected Parcelable onSaveInstanceState() {
21019         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
21020         if (mStartActivityRequestWho != null || isAutofilled()
21021                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
21022             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
21023 
21024             if (mStartActivityRequestWho != null) {
21025                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
21026             }
21027 
21028             if (isAutofilled()) {
21029                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
21030             }
21031 
21032             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
21033                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
21034             }
21035 
21036             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
21037             state.mIsAutofilled = isAutofilled();
21038             state.mHideHighlight = hideAutofillHighlight();
21039             state.mAutofillViewId = mAutofillViewId;
21040             return state;
21041         }
21042         return BaseSavedState.EMPTY_STATE;
21043     }
21044 
21045     /**
21046      * Restore this view hierarchy's frozen state from the given container.
21047      *
21048      * @param container The SparseArray which holds previously frozen states.
21049      *
21050      * @see #saveHierarchyState(android.util.SparseArray)
21051      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
21052      * @see #onRestoreInstanceState(android.os.Parcelable)
21053      */
restoreHierarchyState(SparseArray<Parcelable> container)21054     public void restoreHierarchyState(SparseArray<Parcelable> container) {
21055         dispatchRestoreInstanceState(container);
21056     }
21057 
21058     /**
21059      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
21060      * state for this view and its children. May be overridden to modify how restoring
21061      * happens to a view's children; for example, some views may want to not store state
21062      * for their children.
21063      *
21064      * @param container The SparseArray which holds previously saved state.
21065      *
21066      * @see #dispatchSaveInstanceState(android.util.SparseArray)
21067      * @see #restoreHierarchyState(android.util.SparseArray)
21068      * @see #onRestoreInstanceState(android.os.Parcelable)
21069      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)21070     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
21071         if (mID != NO_ID) {
21072             Parcelable state = container.get(mID);
21073             if (state != null) {
21074                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
21075                 // + ": " + state);
21076                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
21077                 onRestoreInstanceState(state);
21078                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
21079                     throw new IllegalStateException(
21080                             "Derived class did not call super.onRestoreInstanceState()");
21081                 }
21082             }
21083         }
21084     }
21085 
21086     /**
21087      * Hook allowing a view to re-apply a representation of its internal state that had previously
21088      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
21089      * null state.
21090      *
21091      * @param state The frozen state that had previously been returned by
21092      *        {@link #onSaveInstanceState}.
21093      *
21094      * @see #onSaveInstanceState()
21095      * @see #restoreHierarchyState(android.util.SparseArray)
21096      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
21097      */
21098     @CallSuper
onRestoreInstanceState(Parcelable state)21099     protected void onRestoreInstanceState(Parcelable state) {
21100         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
21101         if (state != null && !(state instanceof AbsSavedState)) {
21102             throw new IllegalArgumentException("Wrong state class, expecting View State but "
21103                     + "received " + state.getClass().toString() + " instead. This usually happens "
21104                     + "when two views of different type have the same id in the same hierarchy. "
21105                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
21106                     + "other views do not use the same id.");
21107         }
21108         if (state != null && state instanceof BaseSavedState) {
21109             BaseSavedState baseState = (BaseSavedState) state;
21110 
21111             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
21112                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
21113             }
21114             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
21115                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
21116             }
21117             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
21118                 // It can happen that views have the same view id and the restoration path will not
21119                 // be able to distinguish between them. The autofill id needs to be unique though.
21120                 // Hence prevent the same autofill view id from being restored multiple times.
21121                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
21122 
21123                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
21124                     // Ignore when view already set it through setAutofillId();
21125                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
21126                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
21127                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
21128                                 + " it to " + mAutofillId);
21129                     }
21130                 } else {
21131                     mAutofillViewId = baseState.mAutofillViewId;
21132                     mAutofillId = null; // will be set on demand by getAutofillId()
21133                 }
21134             }
21135         }
21136     }
21137 
21138     /**
21139      * <p>Return the time at which the drawing of the view hierarchy started.</p>
21140      *
21141      * @return the drawing start time in milliseconds
21142      */
getDrawingTime()21143     public long getDrawingTime() {
21144         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
21145     }
21146 
21147     /**
21148      * <p>Enables or disables the duplication of the parent's state into this view. When
21149      * duplication is enabled, this view gets its drawable state from its parent rather
21150      * than from its own internal properties.</p>
21151      *
21152      * <p>Note: in the current implementation, setting this property to true after the
21153      * view was added to a ViewGroup might have no effect at all. This property should
21154      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
21155      *
21156      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
21157      * property is enabled, an exception will be thrown.</p>
21158      *
21159      * <p>Note: if the child view uses and updates additional states which are unknown to the
21160      * parent, these states should not be affected by this method.</p>
21161      *
21162      * @param enabled True to enable duplication of the parent's drawable state, false
21163      *                to disable it.
21164      *
21165      * @see #getDrawableState()
21166      * @see #isDuplicateParentStateEnabled()
21167      */
setDuplicateParentStateEnabled(boolean enabled)21168     public void setDuplicateParentStateEnabled(boolean enabled) {
21169         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
21170     }
21171 
21172     /**
21173      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
21174      *
21175      * @return True if this view's drawable state is duplicated from the parent,
21176      *         false otherwise
21177      *
21178      * @see #getDrawableState()
21179      * @see #setDuplicateParentStateEnabled(boolean)
21180      */
21181     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()21182     public boolean isDuplicateParentStateEnabled() {
21183         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
21184     }
21185 
21186     /**
21187      * <p>Specifies the type of layer backing this view. The layer can be
21188      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21189      * {@link #LAYER_TYPE_HARDWARE}.</p>
21190      *
21191      * <p>A layer is associated with an optional {@link android.graphics.Paint}
21192      * instance that controls how the layer is composed on screen. The following
21193      * properties of the paint are taken into account when composing the layer:</p>
21194      * <ul>
21195      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
21196      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
21197      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
21198      * </ul>
21199      *
21200      * <p>If this view has an alpha value set to < 1.0 by calling
21201      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
21202      * by this view's alpha value.</p>
21203      *
21204      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
21205      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
21206      * for more information on when and how to use layers.</p>
21207      *
21208      * @param layerType The type of layer to use with this view, must be one of
21209      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21210      *        {@link #LAYER_TYPE_HARDWARE}
21211      * @param paint The paint used to compose the layer. This argument is optional
21212      *        and can be null. It is ignored when the layer type is
21213      *        {@link #LAYER_TYPE_NONE}
21214      *
21215      * @see #getLayerType()
21216      * @see #LAYER_TYPE_NONE
21217      * @see #LAYER_TYPE_SOFTWARE
21218      * @see #LAYER_TYPE_HARDWARE
21219      * @see #setAlpha(float)
21220      *
21221      * @attr ref android.R.styleable#View_layerType
21222      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)21223     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
21224         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
21225             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
21226                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
21227         }
21228 
21229         boolean typeChanged = mRenderNode.setLayerType(layerType);
21230 
21231         if (!typeChanged) {
21232             setLayerPaint(paint);
21233             return;
21234         }
21235 
21236         if (layerType != LAYER_TYPE_SOFTWARE) {
21237             // Destroy any previous software drawing cache if present
21238             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
21239             // drawing cache created in View#draw when drawing to a SW canvas.
21240             destroyDrawingCache();
21241         }
21242 
21243         mLayerType = layerType;
21244         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
21245         mRenderNode.setLayerPaint(mLayerPaint);
21246 
21247         // draw() behaves differently if we are on a layer, so we need to
21248         // invalidate() here
21249         invalidateParentCaches();
21250         invalidate(true);
21251     }
21252 
21253     /**
21254      * Configure the {@link android.graphics.RenderEffect} to apply to this View.
21255      * This will apply a visual effect to the results of the View before it is drawn. For example if
21256      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
21257      * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
21258      * when this View is drawn.
21259      * @param renderEffect to be applied to the View. Passing null clears the previously configured
21260      *                     {@link RenderEffect}
21261      */
setRenderEffect(@ullable RenderEffect renderEffect)21262     public void setRenderEffect(@Nullable RenderEffect renderEffect) {
21263         if (mRenderNode.setRenderEffect(renderEffect)) {
21264             invalidateViewProperty(true, true);
21265         }
21266     }
21267 
21268     /**
21269      * Updates the {@link Paint} object used with the current layer (used only if the current
21270      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
21271      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
21272      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
21273      * ensure that the view gets redrawn immediately.
21274      *
21275      * <p>A layer is associated with an optional {@link android.graphics.Paint}
21276      * instance that controls how the layer is composed on screen. The following
21277      * properties of the paint are taken into account when composing the layer:</p>
21278      * <ul>
21279      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
21280      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
21281      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
21282      * </ul>
21283      *
21284      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
21285      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
21286      *
21287      * @param paint The paint used to compose the layer. This argument is optional
21288      *        and can be null. It is ignored when the layer type is
21289      *        {@link #LAYER_TYPE_NONE}
21290      *
21291      * @see #setLayerType(int, android.graphics.Paint)
21292      */
setLayerPaint(@ullable Paint paint)21293     public void setLayerPaint(@Nullable Paint paint) {
21294         int layerType = getLayerType();
21295         if (layerType != LAYER_TYPE_NONE) {
21296             mLayerPaint = paint;
21297             if (layerType == LAYER_TYPE_HARDWARE) {
21298                 if (mRenderNode.setLayerPaint(paint)) {
21299                     invalidateViewProperty(false, false);
21300                 }
21301             } else {
21302                 invalidate();
21303             }
21304         }
21305     }
21306 
21307     /**
21308      * Indicates what type of layer is currently associated with this view. By default
21309      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
21310      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
21311      * for more information on the different types of layers.
21312      *
21313      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21314      *         {@link #LAYER_TYPE_HARDWARE}
21315      *
21316      * @see #setLayerType(int, android.graphics.Paint)
21317      * @see #buildLayer()
21318      * @see #LAYER_TYPE_NONE
21319      * @see #LAYER_TYPE_SOFTWARE
21320      * @see #LAYER_TYPE_HARDWARE
21321      */
21322     @InspectableProperty(enumMapping = {
21323             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
21324             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
21325             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
21326     })
21327     @LayerType
getLayerType()21328     public int getLayerType() {
21329         return mLayerType;
21330     }
21331 
21332     /**
21333      * Forces this view's layer to be created and this view to be rendered
21334      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
21335      * invoking this method will have no effect.
21336      *
21337      * This method can for instance be used to render a view into its layer before
21338      * starting an animation. If this view is complex, rendering into the layer
21339      * before starting the animation will avoid skipping frames.
21340      *
21341      * @throws IllegalStateException If this view is not attached to a window
21342      *
21343      * @see #setLayerType(int, android.graphics.Paint)
21344      */
buildLayer()21345     public void buildLayer() {
21346         if (mLayerType == LAYER_TYPE_NONE) return;
21347 
21348         final AttachInfo attachInfo = mAttachInfo;
21349         if (attachInfo == null) {
21350             throw new IllegalStateException("This view must be attached to a window first");
21351         }
21352 
21353         if (getWidth() == 0 || getHeight() == 0) {
21354             return;
21355         }
21356 
21357         switch (mLayerType) {
21358             case LAYER_TYPE_HARDWARE:
21359                 updateDisplayListIfDirty();
21360                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
21361                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
21362                 }
21363                 break;
21364             case LAYER_TYPE_SOFTWARE:
21365                 buildDrawingCache(true);
21366                 break;
21367         }
21368     }
21369 
21370     /**
21371      * Destroys all hardware rendering resources. This method is invoked
21372      * when the system needs to reclaim resources. Upon execution of this
21373      * method, you should free any OpenGL resources created by the view.
21374      *
21375      * Note: you <strong>must</strong> call
21376      * <code>super.destroyHardwareResources()</code> when overriding
21377      * this method.
21378      *
21379      * @hide
21380      */
21381     @CallSuper
21382     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
destroyHardwareResources()21383     protected void destroyHardwareResources() {
21384         if (mOverlay != null) {
21385             mOverlay.getOverlayView().destroyHardwareResources();
21386         }
21387         if (mGhostView != null) {
21388             mGhostView.destroyHardwareResources();
21389         }
21390     }
21391 
21392     /**
21393      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
21394      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
21395      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
21396      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
21397      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
21398      * null.</p>
21399      *
21400      * <p>Enabling the drawing cache is similar to
21401      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
21402      * acceleration is turned off. When hardware acceleration is turned on, enabling the
21403      * drawing cache has no effect on rendering because the system uses a different mechanism
21404      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
21405      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
21406      * for information on how to enable software and hardware layers.</p>
21407      *
21408      * <p>This API can be used to manually generate
21409      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
21410      * {@link #getDrawingCache()}.</p>
21411      *
21412      * @param enabled true to enable the drawing cache, false otherwise
21413      *
21414      * @see #isDrawingCacheEnabled()
21415      * @see #getDrawingCache()
21416      * @see #buildDrawingCache()
21417      * @see #setLayerType(int, android.graphics.Paint)
21418      *
21419      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21420      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21421      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21422      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21423      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21424      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21425      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21426      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21427      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21428      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21429      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21430      * reports or unit testing the {@link PixelCopy} API is recommended.
21431      */
21432     @Deprecated
setDrawingCacheEnabled(boolean enabled)21433     public void setDrawingCacheEnabled(boolean enabled) {
21434         mCachingFailed = false;
21435         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
21436     }
21437 
21438     /**
21439      * <p>Indicates whether the drawing cache is enabled for this view.</p>
21440      *
21441      * @return true if the drawing cache is enabled
21442      *
21443      * @see #setDrawingCacheEnabled(boolean)
21444      * @see #getDrawingCache()
21445      *
21446      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21447      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21448      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21449      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21450      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21451      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21452      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21453      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21454      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21455      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21456      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21457      * reports or unit testing the {@link PixelCopy} API is recommended.
21458      */
21459     @Deprecated
21460     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()21461     public boolean isDrawingCacheEnabled() {
21462         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
21463     }
21464 
21465     /**
21466      * Debugging utility which recursively outputs the dirty state of a view and its
21467      * descendants.
21468      *
21469      * @hide
21470      */
21471     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)21472     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
21473         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
21474                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
21475                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
21476                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
21477                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
21478         if (clear) {
21479             mPrivateFlags &= clearMask;
21480         }
21481         if (this instanceof ViewGroup) {
21482             ViewGroup parent = (ViewGroup) this;
21483             final int count = parent.getChildCount();
21484             for (int i = 0; i < count; i++) {
21485                 final View child = parent.getChildAt(i);
21486                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
21487             }
21488         }
21489     }
21490 
21491     /**
21492      * This method is used by ViewGroup to cause its children to restore or recreate their
21493      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
21494      * to recreate its own display list, which would happen if it went through the normal
21495      * draw/dispatchDraw mechanisms.
21496      *
21497      * @hide
21498      */
dispatchGetDisplayList()21499     protected void dispatchGetDisplayList() {}
21500 
21501     /**
21502      * A view that is not attached or hardware accelerated cannot create a display list.
21503      * This method checks these conditions and returns the appropriate result.
21504      *
21505      * @return true if view has the ability to create a display list, false otherwise.
21506      *
21507      * @hide
21508      */
canHaveDisplayList()21509     public boolean canHaveDisplayList() {
21510         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
21511     }
21512 
21513     /**
21514      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
21515      * @hide
21516      */
21517     @NonNull
21518     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateDisplayListIfDirty()21519     public RenderNode updateDisplayListIfDirty() {
21520         final RenderNode renderNode = mRenderNode;
21521         if (!canHaveDisplayList()) {
21522             // can't populate RenderNode, don't try
21523             return renderNode;
21524         }
21525 
21526         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
21527                 || !renderNode.hasDisplayList()
21528                 || (mRecreateDisplayList)) {
21529             // Don't need to recreate the display list, just need to tell our
21530             // children to restore/recreate theirs
21531             if (renderNode.hasDisplayList()
21532                     && !mRecreateDisplayList) {
21533                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21534                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21535                 dispatchGetDisplayList();
21536 
21537                 return renderNode; // no work needed
21538             }
21539 
21540             // If we got here, we're recreating it. Mark it as such to ensure that
21541             // we copy in child display lists into ours in drawChild()
21542             mRecreateDisplayList = true;
21543 
21544             int width = mRight - mLeft;
21545             int height = mBottom - mTop;
21546             int layerType = getLayerType();
21547 
21548             // Hacky hack: Reset any stretch effects as those are applied during the draw pass
21549             // instead of being "stateful" like other RenderNode properties
21550             renderNode.clearStretch();
21551 
21552             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
21553 
21554             try {
21555                 if (layerType == LAYER_TYPE_SOFTWARE) {
21556                     buildDrawingCache(true);
21557                     Bitmap cache = getDrawingCache(true);
21558                     if (cache != null) {
21559                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
21560                     }
21561                 } else {
21562                     computeScroll();
21563 
21564                     canvas.translate(-mScrollX, -mScrollY);
21565                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21566                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21567 
21568                     // Fast path for layouts with no backgrounds
21569                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21570                         dispatchDraw(canvas);
21571                         drawAutofilledHighlight(canvas);
21572                         if (mOverlay != null && !mOverlay.isEmpty()) {
21573                             mOverlay.getOverlayView().draw(canvas);
21574                         }
21575                         if (isShowingLayoutBounds()) {
21576                             debugDrawFocus(canvas);
21577                         }
21578                     } else {
21579                         draw(canvas);
21580                     }
21581                 }
21582             } finally {
21583                 renderNode.endRecording();
21584                 setDisplayListProperties(renderNode);
21585             }
21586         } else {
21587             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21588             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21589         }
21590         return renderNode;
21591     }
21592 
21593     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resetDisplayList()21594     private void resetDisplayList() {
21595         mRenderNode.discardDisplayList();
21596         if (mBackgroundRenderNode != null) {
21597             mBackgroundRenderNode.discardDisplayList();
21598         }
21599     }
21600 
21601     /**
21602      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
21603      *
21604      * @return A non-scaled bitmap representing this view or null if cache is disabled.
21605      *
21606      * @see #getDrawingCache(boolean)
21607      *
21608      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21609      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21610      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21611      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21612      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21613      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21614      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21615      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21616      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21617      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21618      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21619      * reports or unit testing the {@link PixelCopy} API is recommended.
21620      */
21621     @Deprecated
getDrawingCache()21622     public Bitmap getDrawingCache() {
21623         return getDrawingCache(false);
21624     }
21625 
21626     /**
21627      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
21628      * is null when caching is disabled. If caching is enabled and the cache is not ready,
21629      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
21630      * draw from the cache when the cache is enabled. To benefit from the cache, you must
21631      * request the drawing cache by calling this method and draw it on screen if the
21632      * returned bitmap is not null.</p>
21633      *
21634      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21635      * this method will create a bitmap of the same size as this view. Because this bitmap
21636      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21637      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21638      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21639      * size than the view. This implies that your application must be able to handle this
21640      * size.</p>
21641      *
21642      * @param autoScale Indicates whether the generated bitmap should be scaled based on
21643      *        the current density of the screen when the application is in compatibility
21644      *        mode.
21645      *
21646      * @return A bitmap representing this view or null if cache is disabled.
21647      *
21648      * @see #setDrawingCacheEnabled(boolean)
21649      * @see #isDrawingCacheEnabled()
21650      * @see #buildDrawingCache(boolean)
21651      * @see #destroyDrawingCache()
21652      *
21653      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21654      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21655      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21656      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21657      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21658      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21659      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21660      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21661      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21662      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21663      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21664      * reports or unit testing the {@link PixelCopy} API is recommended.
21665      */
21666     @Deprecated
getDrawingCache(boolean autoScale)21667     public Bitmap getDrawingCache(boolean autoScale) {
21668         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
21669             return null;
21670         }
21671         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
21672             buildDrawingCache(autoScale);
21673         }
21674         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
21675     }
21676 
21677     /**
21678      * <p>Frees the resources used by the drawing cache. If you call
21679      * {@link #buildDrawingCache()} manually without calling
21680      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21681      * should cleanup the cache with this method afterwards.</p>
21682      *
21683      * @see #setDrawingCacheEnabled(boolean)
21684      * @see #buildDrawingCache()
21685      * @see #getDrawingCache()
21686      *
21687      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21688      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21689      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21690      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21691      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21692      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21693      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21694      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21695      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21696      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21697      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21698      * reports or unit testing the {@link PixelCopy} API is recommended.
21699      */
21700     @Deprecated
destroyDrawingCache()21701     public void destroyDrawingCache() {
21702         if (mDrawingCache != null) {
21703             mDrawingCache.recycle();
21704             mDrawingCache = null;
21705         }
21706         if (mUnscaledDrawingCache != null) {
21707             mUnscaledDrawingCache.recycle();
21708             mUnscaledDrawingCache = null;
21709         }
21710     }
21711 
21712     /**
21713      * Setting a solid background color for the drawing cache's bitmaps will improve
21714      * performance and memory usage. Note, though that this should only be used if this
21715      * view will always be drawn on top of a solid color.
21716      *
21717      * @param color The background color to use for the drawing cache's bitmap
21718      *
21719      * @see #setDrawingCacheEnabled(boolean)
21720      * @see #buildDrawingCache()
21721      * @see #getDrawingCache()
21722      *
21723      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21724      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21725      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21726      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21727      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21728      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21729      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21730      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21731      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21732      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21733      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21734      * reports or unit testing the {@link PixelCopy} API is recommended.
21735      */
21736     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)21737     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
21738         if (color != mDrawingCacheBackgroundColor) {
21739             mDrawingCacheBackgroundColor = color;
21740             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
21741         }
21742     }
21743 
21744     /**
21745      * @see #setDrawingCacheBackgroundColor(int)
21746      *
21747      * @return The background color to used for the drawing cache's bitmap
21748      *
21749      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21750      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21751      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21752      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21753      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21754      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21755      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21756      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21757      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21758      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21759      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21760      * reports or unit testing the {@link PixelCopy} API is recommended.
21761      */
21762     @Deprecated
21763     @ColorInt
getDrawingCacheBackgroundColor()21764     public int getDrawingCacheBackgroundColor() {
21765         return mDrawingCacheBackgroundColor;
21766     }
21767 
21768     /**
21769      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
21770      *
21771      * @see #buildDrawingCache(boolean)
21772      *
21773      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21774      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21775      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21776      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21777      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21778      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21779      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21780      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21781      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21782      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21783      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21784      * reports or unit testing the {@link PixelCopy} API is recommended.
21785      */
21786     @Deprecated
buildDrawingCache()21787     public void buildDrawingCache() {
21788         buildDrawingCache(false);
21789     }
21790 
21791     /**
21792      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
21793      *
21794      * <p>If you call {@link #buildDrawingCache()} manually without calling
21795      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21796      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
21797      *
21798      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21799      * this method will create a bitmap of the same size as this view. Because this bitmap
21800      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21801      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21802      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21803      * size than the view. This implies that your application must be able to handle this
21804      * size.</p>
21805      *
21806      * <p>You should avoid calling this method when hardware acceleration is enabled. If
21807      * you do not need the drawing cache bitmap, calling this method will increase memory
21808      * usage and cause the view to be rendered in software once, thus negatively impacting
21809      * performance.</p>
21810      *
21811      * @see #getDrawingCache()
21812      * @see #destroyDrawingCache()
21813      *
21814      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21815      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21816      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21817      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21818      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21819      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21820      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21821      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21822      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21823      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21824      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21825      * reports or unit testing the {@link PixelCopy} API is recommended.
21826      */
21827     @Deprecated
buildDrawingCache(boolean autoScale)21828     public void buildDrawingCache(boolean autoScale) {
21829         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
21830                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
21831             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
21832                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
21833                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
21834             }
21835             try {
21836                 buildDrawingCacheImpl(autoScale);
21837             } finally {
21838                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
21839             }
21840         }
21841     }
21842 
21843     /**
21844      * private, internal implementation of buildDrawingCache, used to enable tracing
21845      */
buildDrawingCacheImpl(boolean autoScale)21846     private void buildDrawingCacheImpl(boolean autoScale) {
21847         mCachingFailed = false;
21848 
21849         int width = mRight - mLeft;
21850         int height = mBottom - mTop;
21851 
21852         final AttachInfo attachInfo = mAttachInfo;
21853         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
21854 
21855         if (autoScale && scalingRequired) {
21856             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
21857             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
21858         }
21859 
21860         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
21861         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
21862         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
21863 
21864         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
21865         final long drawingCacheSize =
21866                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
21867         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
21868             if (width > 0 && height > 0) {
21869                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
21870                         + " too large to fit into a software layer (or drawing cache), needs "
21871                         + projectedBitmapSize + " bytes, only "
21872                         + drawingCacheSize + " available");
21873             }
21874             destroyDrawingCache();
21875             mCachingFailed = true;
21876             return;
21877         }
21878 
21879         boolean clear = true;
21880         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
21881 
21882         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
21883             Bitmap.Config quality;
21884             if (!opaque) {
21885                 // Never pick ARGB_4444 because it looks awful
21886                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
21887                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
21888                     case DRAWING_CACHE_QUALITY_AUTO:
21889                     case DRAWING_CACHE_QUALITY_LOW:
21890                     case DRAWING_CACHE_QUALITY_HIGH:
21891                     default:
21892                         quality = Bitmap.Config.ARGB_8888;
21893                         break;
21894                 }
21895             } else {
21896                 // Optimization for translucent windows
21897                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
21898                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
21899             }
21900 
21901             // Try to cleanup memory
21902             if (bitmap != null) bitmap.recycle();
21903 
21904             try {
21905                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
21906                         width, height, quality);
21907                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
21908                 if (autoScale) {
21909                     mDrawingCache = bitmap;
21910                 } else {
21911                     mUnscaledDrawingCache = bitmap;
21912                 }
21913                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
21914             } catch (OutOfMemoryError e) {
21915                 // If there is not enough memory to create the bitmap cache, just
21916                 // ignore the issue as bitmap caches are not required to draw the
21917                 // view hierarchy
21918                 if (autoScale) {
21919                     mDrawingCache = null;
21920                 } else {
21921                     mUnscaledDrawingCache = null;
21922                 }
21923                 mCachingFailed = true;
21924                 return;
21925             }
21926 
21927             clear = drawingCacheBackgroundColor != 0;
21928         }
21929 
21930         Canvas canvas;
21931         if (attachInfo != null) {
21932             canvas = attachInfo.mCanvas;
21933             if (canvas == null) {
21934                 canvas = new Canvas();
21935             }
21936             canvas.setBitmap(bitmap);
21937             // Temporarily clobber the cached Canvas in case one of our children
21938             // is also using a drawing cache. Without this, the children would
21939             // steal the canvas by attaching their own bitmap to it and bad, bad
21940             // thing would happen (invisible views, corrupted drawings, etc.)
21941             attachInfo.mCanvas = null;
21942         } else {
21943             // This case should hopefully never or seldom happen
21944             canvas = new Canvas(bitmap);
21945         }
21946 
21947         if (clear) {
21948             bitmap.eraseColor(drawingCacheBackgroundColor);
21949         }
21950 
21951         computeScroll();
21952         final int restoreCount = canvas.save();
21953 
21954         if (autoScale && scalingRequired) {
21955             final float scale = attachInfo.mApplicationScale;
21956             canvas.scale(scale, scale);
21957         }
21958 
21959         canvas.translate(-mScrollX, -mScrollY);
21960 
21961         mPrivateFlags |= PFLAG_DRAWN;
21962         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
21963                 mLayerType != LAYER_TYPE_NONE) {
21964             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
21965         }
21966 
21967         // Fast path for layouts with no backgrounds
21968         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21969             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21970             dispatchDraw(canvas);
21971             drawAutofilledHighlight(canvas);
21972             if (mOverlay != null && !mOverlay.isEmpty()) {
21973                 mOverlay.getOverlayView().draw(canvas);
21974             }
21975         } else {
21976             draw(canvas);
21977         }
21978 
21979         canvas.restoreToCount(restoreCount);
21980         canvas.setBitmap(null);
21981 
21982         if (attachInfo != null) {
21983             // Restore the cached Canvas for our siblings
21984             attachInfo.mCanvas = canvas;
21985         }
21986     }
21987 
21988     /**
21989      * Create a snapshot of the view into a bitmap.  We should probably make
21990      * some form of this public, but should think about the API.
21991      *
21992      * @hide
21993      */
21994     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)21995     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
21996         int width = mRight - mLeft;
21997         int height = mBottom - mTop;
21998 
21999         final AttachInfo attachInfo = mAttachInfo;
22000         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
22001         width = (int) ((width * scale) + 0.5f);
22002         height = (int) ((height * scale) + 0.5f);
22003 
22004         Canvas oldCanvas = null;
22005         try {
22006             Canvas canvas = canvasProvider.getCanvas(this,
22007                     width > 0 ? width : 1, height > 0 ? height : 1);
22008 
22009             if (attachInfo != null) {
22010                 oldCanvas = attachInfo.mCanvas;
22011                 // Temporarily clobber the cached Canvas in case one of our children
22012                 // is also using a drawing cache. Without this, the children would
22013                 // steal the canvas by attaching their own bitmap to it and bad, bad
22014                 // things would happen (invisible views, corrupted drawings, etc.)
22015                 attachInfo.mCanvas = null;
22016             }
22017 
22018             computeScroll();
22019             final int restoreCount = canvas.save();
22020             canvas.scale(scale, scale);
22021             canvas.translate(-mScrollX, -mScrollY);
22022 
22023             // Temporarily remove the dirty mask
22024             int flags = mPrivateFlags;
22025             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22026 
22027             // Fast path for layouts with no backgrounds
22028             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22029                 dispatchDraw(canvas);
22030                 drawAutofilledHighlight(canvas);
22031                 if (mOverlay != null && !mOverlay.isEmpty()) {
22032                     mOverlay.getOverlayView().draw(canvas);
22033                 }
22034             } else {
22035                 draw(canvas);
22036             }
22037 
22038             mPrivateFlags = flags;
22039             canvas.restoreToCount(restoreCount);
22040             return canvasProvider.createBitmap();
22041         } finally {
22042             if (oldCanvas != null) {
22043                 attachInfo.mCanvas = oldCanvas;
22044             }
22045         }
22046     }
22047 
22048     /**
22049      * Indicates whether this View is currently in edit mode. A View is usually
22050      * in edit mode when displayed within a developer tool. For instance, if
22051      * this View is being drawn by a visual user interface builder, this method
22052      * should return true.
22053      *
22054      * Subclasses should check the return value of this method to provide
22055      * different behaviors if their normal behavior might interfere with the
22056      * host environment. For instance: the class spawns a thread in its
22057      * constructor, the drawing code relies on device-specific features, etc.
22058      *
22059      * This method is usually checked in the drawing code of custom widgets.
22060      *
22061      * @return True if this View is in edit mode, false otherwise.
22062      */
isInEditMode()22063     public boolean isInEditMode() {
22064         return false;
22065     }
22066 
22067     /**
22068      * If the View draws content inside its padding and enables fading edges,
22069      * it needs to support padding offsets. Padding offsets are added to the
22070      * fading edges to extend the length of the fade so that it covers pixels
22071      * drawn inside the padding.
22072      *
22073      * Subclasses of this class should override this method if they need
22074      * to draw content inside the padding.
22075      *
22076      * @return True if padding offset must be applied, false otherwise.
22077      *
22078      * @see #getLeftPaddingOffset()
22079      * @see #getRightPaddingOffset()
22080      * @see #getTopPaddingOffset()
22081      * @see #getBottomPaddingOffset()
22082      *
22083      * @since CURRENT
22084      */
isPaddingOffsetRequired()22085     protected boolean isPaddingOffsetRequired() {
22086         return false;
22087     }
22088 
22089     /**
22090      * Amount by which to extend the left fading region. Called only when
22091      * {@link #isPaddingOffsetRequired()} returns true.
22092      *
22093      * @return The left padding offset in pixels.
22094      *
22095      * @see #isPaddingOffsetRequired()
22096      *
22097      * @since CURRENT
22098      */
getLeftPaddingOffset()22099     protected int getLeftPaddingOffset() {
22100         return 0;
22101     }
22102 
22103     /**
22104      * Amount by which to extend the right fading region. Called only when
22105      * {@link #isPaddingOffsetRequired()} returns true.
22106      *
22107      * @return The right padding offset in pixels.
22108      *
22109      * @see #isPaddingOffsetRequired()
22110      *
22111      * @since CURRENT
22112      */
getRightPaddingOffset()22113     protected int getRightPaddingOffset() {
22114         return 0;
22115     }
22116 
22117     /**
22118      * Amount by which to extend the top fading region. Called only when
22119      * {@link #isPaddingOffsetRequired()} returns true.
22120      *
22121      * @return The top padding offset in pixels.
22122      *
22123      * @see #isPaddingOffsetRequired()
22124      *
22125      * @since CURRENT
22126      */
getTopPaddingOffset()22127     protected int getTopPaddingOffset() {
22128         return 0;
22129     }
22130 
22131     /**
22132      * Amount by which to extend the bottom fading region. Called only when
22133      * {@link #isPaddingOffsetRequired()} returns true.
22134      *
22135      * @return The bottom padding offset in pixels.
22136      *
22137      * @see #isPaddingOffsetRequired()
22138      *
22139      * @since CURRENT
22140      */
getBottomPaddingOffset()22141     protected int getBottomPaddingOffset() {
22142         return 0;
22143     }
22144 
22145     /**
22146      * @hide
22147      * @param offsetRequired
22148      */
getFadeTop(boolean offsetRequired)22149     protected int getFadeTop(boolean offsetRequired) {
22150         int top = mPaddingTop;
22151         if (offsetRequired) top += getTopPaddingOffset();
22152         return top;
22153     }
22154 
22155     /**
22156      * @hide
22157      * @param offsetRequired
22158      */
getFadeHeight(boolean offsetRequired)22159     protected int getFadeHeight(boolean offsetRequired) {
22160         int padding = mPaddingTop;
22161         if (offsetRequired) padding += getTopPaddingOffset();
22162         return mBottom - mTop - mPaddingBottom - padding;
22163     }
22164 
22165     /**
22166      * <p>Indicates whether this view is attached to a hardware accelerated
22167      * window or not.</p>
22168      *
22169      * <p>Even if this method returns true, it does not mean that every call
22170      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
22171      * accelerated {@link android.graphics.Canvas}. For instance, if this view
22172      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
22173      * window is hardware accelerated,
22174      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
22175      * return false, and this method will return true.</p>
22176      *
22177      * @return True if the view is attached to a window and the window is
22178      *         hardware accelerated; false in any other case.
22179      */
22180     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()22181     public boolean isHardwareAccelerated() {
22182         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
22183     }
22184 
22185     /**
22186      * Sets a rectangular area on this view to which the view will be clipped
22187      * when it is drawn. Setting the value to null will remove the clip bounds
22188      * and the view will draw normally, using its full bounds.
22189      *
22190      * @param clipBounds The rectangular area, in the local coordinates of
22191      * this view, to which future drawing operations will be clipped.
22192      */
setClipBounds(Rect clipBounds)22193     public void setClipBounds(Rect clipBounds) {
22194         if (clipBounds == mClipBounds
22195                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
22196             return;
22197         }
22198         if (clipBounds != null) {
22199             if (mClipBounds == null) {
22200                 mClipBounds = new Rect(clipBounds);
22201             } else {
22202                 mClipBounds.set(clipBounds);
22203             }
22204         } else {
22205             mClipBounds = null;
22206         }
22207         mRenderNode.setClipRect(mClipBounds);
22208         invalidateViewProperty(false, false);
22209     }
22210 
22211     /**
22212      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
22213      *
22214      * @return A copy of the current clip bounds if clip bounds are set,
22215      * otherwise null.
22216      */
getClipBounds()22217     public Rect getClipBounds() {
22218         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
22219     }
22220 
22221 
22222     /**
22223      * Populates an output rectangle with the clip bounds of the view,
22224      * returning {@code true} if successful or {@code false} if the view's
22225      * clip bounds are {@code null}.
22226      *
22227      * @param outRect rectangle in which to place the clip bounds of the view
22228      * @return {@code true} if successful or {@code false} if the view's
22229      *         clip bounds are {@code null}
22230      */
getClipBounds(Rect outRect)22231     public boolean getClipBounds(Rect outRect) {
22232         if (mClipBounds != null) {
22233             outRect.set(mClipBounds);
22234             return true;
22235         }
22236         return false;
22237     }
22238 
22239     /**
22240      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
22241      * case of an active Animation being run on the view.
22242      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)22243     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
22244             Animation a, boolean scalingRequired) {
22245         Transformation invalidationTransform;
22246         final int flags = parent.mGroupFlags;
22247         final boolean initialized = a.isInitialized();
22248         if (!initialized) {
22249             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
22250             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
22251             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
22252             onAnimationStart();
22253         }
22254 
22255         final Transformation t = parent.getChildTransformation();
22256         boolean more = a.getTransformation(drawingTime, t, 1f);
22257         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
22258             if (parent.mInvalidationTransformation == null) {
22259                 parent.mInvalidationTransformation = new Transformation();
22260             }
22261             invalidationTransform = parent.mInvalidationTransformation;
22262             a.getTransformation(drawingTime, invalidationTransform, 1f);
22263         } else {
22264             invalidationTransform = t;
22265         }
22266 
22267         if (more) {
22268             if (!a.willChangeBounds()) {
22269                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
22270                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
22271                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
22272                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
22273                     // The child need to draw an animation, potentially offscreen, so
22274                     // make sure we do not cancel invalidate requests
22275                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
22276                     parent.invalidate(mLeft, mTop, mRight, mBottom);
22277                 }
22278             } else {
22279                 if (parent.mInvalidateRegion == null) {
22280                     parent.mInvalidateRegion = new RectF();
22281                 }
22282                 final RectF region = parent.mInvalidateRegion;
22283                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
22284                         invalidationTransform);
22285 
22286                 // The child need to draw an animation, potentially offscreen, so
22287                 // make sure we do not cancel invalidate requests
22288                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
22289 
22290                 final int left = mLeft + (int) region.left;
22291                 final int top = mTop + (int) region.top;
22292                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
22293                         top + (int) (region.height() + .5f));
22294             }
22295         }
22296         return more;
22297     }
22298 
22299     /**
22300      * This method is called by getDisplayList() when a display list is recorded for a View.
22301      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
22302      */
setDisplayListProperties(RenderNode renderNode)22303     void setDisplayListProperties(RenderNode renderNode) {
22304         if (renderNode != null) {
22305             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
22306             renderNode.setClipToBounds(mParent instanceof ViewGroup
22307                     && ((ViewGroup) mParent).getClipChildren());
22308 
22309             float alpha = 1;
22310             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
22311                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22312                 ViewGroup parentVG = (ViewGroup) mParent;
22313                 final Transformation t = parentVG.getChildTransformation();
22314                 if (parentVG.getChildStaticTransformation(this, t)) {
22315                     final int transformType = t.getTransformationType();
22316                     if (transformType != Transformation.TYPE_IDENTITY) {
22317                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
22318                             alpha = t.getAlpha();
22319                         }
22320                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
22321                             renderNode.setStaticMatrix(t.getMatrix());
22322                         }
22323                     }
22324                 }
22325             }
22326             if (mTransformationInfo != null) {
22327                 alpha *= getFinalAlpha();
22328                 if (alpha < 1) {
22329                     final int multipliedAlpha = (int) (255 * alpha);
22330                     if (onSetAlpha(multipliedAlpha)) {
22331                         alpha = 1;
22332                     }
22333                 }
22334                 renderNode.setAlpha(alpha);
22335             } else if (alpha < 1) {
22336                 renderNode.setAlpha(alpha);
22337             }
22338         }
22339     }
22340 
22341     /**
22342      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
22343      *
22344      * This is where the View specializes rendering behavior based on layer type,
22345      * and hardware acceleration.
22346      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)22347     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
22348 
22349         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
22350         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
22351          *
22352          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
22353          * HW accelerated, it can't handle drawing RenderNodes.
22354          */
22355         boolean drawingWithRenderNode = mAttachInfo != null
22356                 && mAttachInfo.mHardwareAccelerated
22357                 && hardwareAcceleratedCanvas;
22358 
22359         boolean more = false;
22360         final boolean childHasIdentityMatrix = hasIdentityMatrix();
22361         final int parentFlags = parent.mGroupFlags;
22362 
22363         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
22364             parent.getChildTransformation().clear();
22365             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22366         }
22367 
22368         Transformation transformToApply = null;
22369         boolean concatMatrix = false;
22370         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
22371         final Animation a = getAnimation();
22372         if (a != null) {
22373             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
22374             concatMatrix = a.willChangeTransformationMatrix();
22375             if (concatMatrix) {
22376                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22377             }
22378             transformToApply = parent.getChildTransformation();
22379         } else {
22380             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
22381                 // No longer animating: clear out old animation matrix
22382                 mRenderNode.setAnimationMatrix(null);
22383                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22384             }
22385             if (!drawingWithRenderNode
22386                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22387                 final Transformation t = parent.getChildTransformation();
22388                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
22389                 if (hasTransform) {
22390                     final int transformType = t.getTransformationType();
22391                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
22392                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
22393                 }
22394             }
22395         }
22396 
22397         concatMatrix |= !childHasIdentityMatrix;
22398 
22399         // Sets the flag as early as possible to allow draw() implementations
22400         // to call invalidate() successfully when doing animations
22401         mPrivateFlags |= PFLAG_DRAWN;
22402 
22403         if (!concatMatrix &&
22404                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
22405                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
22406                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
22407                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
22408             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
22409             return more;
22410         }
22411         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
22412 
22413         if (hardwareAcceleratedCanvas) {
22414             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
22415             // retain the flag's value temporarily in the mRecreateDisplayList flag
22416             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
22417             mPrivateFlags &= ~PFLAG_INVALIDATED;
22418         }
22419 
22420         RenderNode renderNode = null;
22421         Bitmap cache = null;
22422         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
22423         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
22424              if (layerType != LAYER_TYPE_NONE) {
22425                  // If not drawing with RenderNode, treat HW layers as SW
22426                  layerType = LAYER_TYPE_SOFTWARE;
22427                  buildDrawingCache(true);
22428             }
22429             cache = getDrawingCache(true);
22430         }
22431 
22432         if (drawingWithRenderNode) {
22433             // Delay getting the display list until animation-driven alpha values are
22434             // set up and possibly passed on to the view
22435             renderNode = updateDisplayListIfDirty();
22436             if (!renderNode.hasDisplayList()) {
22437                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
22438                 // to getDisplayList(), the display list will be marked invalid and we should not
22439                 // try to use it again.
22440                 renderNode = null;
22441                 drawingWithRenderNode = false;
22442             }
22443         }
22444 
22445         int sx = 0;
22446         int sy = 0;
22447         if (!drawingWithRenderNode) {
22448             computeScroll();
22449             sx = mScrollX;
22450             sy = mScrollY;
22451         }
22452 
22453         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
22454         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
22455 
22456         int restoreTo = -1;
22457         if (!drawingWithRenderNode || transformToApply != null) {
22458             restoreTo = canvas.save();
22459         }
22460         if (offsetForScroll) {
22461             canvas.translate(mLeft - sx, mTop - sy);
22462         } else {
22463             if (!drawingWithRenderNode) {
22464                 canvas.translate(mLeft, mTop);
22465             }
22466             if (scalingRequired) {
22467                 if (drawingWithRenderNode) {
22468                     // TODO: Might not need this if we put everything inside the DL
22469                     restoreTo = canvas.save();
22470                 }
22471                 // mAttachInfo cannot be null, otherwise scalingRequired == false
22472                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
22473                 canvas.scale(scale, scale);
22474             }
22475         }
22476 
22477         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
22478         if (transformToApply != null
22479                 || alpha < 1
22480                 || !hasIdentityMatrix()
22481                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
22482             if (transformToApply != null || !childHasIdentityMatrix) {
22483                 int transX = 0;
22484                 int transY = 0;
22485 
22486                 if (offsetForScroll) {
22487                     transX = -sx;
22488                     transY = -sy;
22489                 }
22490 
22491                 if (transformToApply != null) {
22492                     if (concatMatrix) {
22493                         if (drawingWithRenderNode) {
22494                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
22495                         } else {
22496                             // Undo the scroll translation, apply the transformation matrix,
22497                             // then redo the scroll translate to get the correct result.
22498                             canvas.translate(-transX, -transY);
22499                             canvas.concat(transformToApply.getMatrix());
22500                             canvas.translate(transX, transY);
22501                         }
22502                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22503                     }
22504 
22505                     float transformAlpha = transformToApply.getAlpha();
22506                     if (transformAlpha < 1) {
22507                         alpha *= transformAlpha;
22508                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22509                     }
22510                 }
22511 
22512                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
22513                     canvas.translate(-transX, -transY);
22514                     canvas.concat(getMatrix());
22515                     canvas.translate(transX, transY);
22516                 }
22517             }
22518 
22519             // Deal with alpha if it is or used to be <1
22520             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
22521                 if (alpha < 1) {
22522                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
22523                 } else {
22524                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
22525                 }
22526                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22527                 if (!drawingWithDrawingCache) {
22528                     final int multipliedAlpha = (int) (255 * alpha);
22529                     if (!onSetAlpha(multipliedAlpha)) {
22530                         if (drawingWithRenderNode) {
22531                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
22532                         } else if (layerType == LAYER_TYPE_NONE) {
22533                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
22534                                     multipliedAlpha);
22535                         }
22536                     } else {
22537                         // Alpha is handled by the child directly, clobber the layer's alpha
22538                         mPrivateFlags |= PFLAG_ALPHA_SET;
22539                     }
22540                 }
22541             }
22542         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
22543             onSetAlpha(255);
22544             mPrivateFlags &= ~PFLAG_ALPHA_SET;
22545         }
22546 
22547         if (!drawingWithRenderNode) {
22548             // apply clips directly, since RenderNode won't do it for this draw
22549             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
22550                 if (offsetForScroll) {
22551                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
22552                 } else {
22553                     if (!scalingRequired || cache == null) {
22554                         canvas.clipRect(0, 0, getWidth(), getHeight());
22555                     } else {
22556                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
22557                     }
22558                 }
22559             }
22560 
22561             if (mClipBounds != null) {
22562                 // clip bounds ignore scroll
22563                 canvas.clipRect(mClipBounds);
22564             }
22565         }
22566 
22567         if (!drawingWithDrawingCache) {
22568             if (drawingWithRenderNode) {
22569                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22570                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22571             } else {
22572                 // Fast path for layouts with no backgrounds
22573                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22574                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22575                     dispatchDraw(canvas);
22576                 } else {
22577                     draw(canvas);
22578                 }
22579             }
22580         } else if (cache != null) {
22581             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22582             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
22583                 // no layer paint, use temporary paint to draw bitmap
22584                 Paint cachePaint = parent.mCachePaint;
22585                 if (cachePaint == null) {
22586                     cachePaint = new Paint();
22587                     cachePaint.setDither(false);
22588                     parent.mCachePaint = cachePaint;
22589                 }
22590                 cachePaint.setAlpha((int) (alpha * 255));
22591                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
22592             } else {
22593                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
22594                 int layerPaintAlpha = mLayerPaint.getAlpha();
22595                 if (alpha < 1) {
22596                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
22597                 }
22598                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
22599                 if (alpha < 1) {
22600                     mLayerPaint.setAlpha(layerPaintAlpha);
22601                 }
22602             }
22603         }
22604 
22605         if (restoreTo >= 0) {
22606             canvas.restoreToCount(restoreTo);
22607         }
22608 
22609         if (a != null && !more) {
22610             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
22611                 onSetAlpha(255);
22612             }
22613             parent.finishAnimatingView(this, a);
22614         }
22615 
22616         if (more && hardwareAcceleratedCanvas) {
22617             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
22618                 // alpha animations should cause the child to recreate its display list
22619                 invalidate(true);
22620             }
22621         }
22622 
22623         mRecreateDisplayList = false;
22624 
22625         return more;
22626     }
22627 
getDebugPaint()22628     static Paint getDebugPaint() {
22629         if (sDebugPaint == null) {
22630             sDebugPaint = new Paint();
22631             sDebugPaint.setAntiAlias(false);
22632         }
22633         return sDebugPaint;
22634     }
22635 
dipsToPixels(int dips)22636     final int dipsToPixels(int dips) {
22637         float scale = getContext().getResources().getDisplayMetrics().density;
22638         return (int) (dips * scale + 0.5f);
22639     }
22640 
debugDrawFocus(Canvas canvas)22641     final private void debugDrawFocus(Canvas canvas) {
22642         if (isFocused()) {
22643             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
22644             final int l = mScrollX;
22645             final int r = l + mRight - mLeft;
22646             final int t = mScrollY;
22647             final int b = t + mBottom - mTop;
22648 
22649             final Paint paint = getDebugPaint();
22650             paint.setColor(DEBUG_CORNERS_COLOR);
22651 
22652             // Draw squares in corners.
22653             paint.setStyle(Paint.Style.FILL);
22654             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
22655             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
22656             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
22657             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
22658 
22659             // Draw big X across the view.
22660             paint.setStyle(Paint.Style.STROKE);
22661             canvas.drawLine(l, t, r, b, paint);
22662             canvas.drawLine(l, b, r, t, paint);
22663         }
22664     }
22665 
22666     /**
22667      * Manually render this view (and all of its children) to the given Canvas.
22668      * The view must have already done a full layout before this function is
22669      * called.  When implementing a view, implement
22670      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
22671      * If you do need to override this method, call the superclass version.
22672      *
22673      * @param canvas The Canvas to which the View is rendered.
22674      */
22675     @CallSuper
draw(Canvas canvas)22676     public void draw(Canvas canvas) {
22677         final int privateFlags = mPrivateFlags;
22678         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
22679 
22680         /*
22681          * Draw traversal performs several drawing steps which must be executed
22682          * in the appropriate order:
22683          *
22684          *      1. Draw the background
22685          *      2. If necessary, save the canvas' layers to prepare for fading
22686          *      3. Draw view's content
22687          *      4. Draw children
22688          *      5. If necessary, draw the fading edges and restore layers
22689          *      6. Draw decorations (scrollbars for instance)
22690          *      7. If necessary, draw the default focus highlight
22691          */
22692 
22693         // Step 1, draw the background, if needed
22694         int saveCount;
22695 
22696         drawBackground(canvas);
22697 
22698         // skip step 2 & 5 if possible (common case)
22699         final int viewFlags = mViewFlags;
22700         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
22701         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
22702         if (!verticalEdges && !horizontalEdges) {
22703             // Step 3, draw the content
22704             onDraw(canvas);
22705 
22706             // Step 4, draw the children
22707             dispatchDraw(canvas);
22708 
22709             drawAutofilledHighlight(canvas);
22710 
22711             // Overlay is part of the content and draws beneath Foreground
22712             if (mOverlay != null && !mOverlay.isEmpty()) {
22713                 mOverlay.getOverlayView().dispatchDraw(canvas);
22714             }
22715 
22716             // Step 6, draw decorations (foreground, scrollbars)
22717             onDrawForeground(canvas);
22718 
22719             // Step 7, draw the default focus highlight
22720             drawDefaultFocusHighlight(canvas);
22721 
22722             if (isShowingLayoutBounds()) {
22723                 debugDrawFocus(canvas);
22724             }
22725 
22726             // we're done...
22727             return;
22728         }
22729 
22730         /*
22731          * Here we do the full fledged routine...
22732          * (this is an uncommon case where speed matters less,
22733          * this is why we repeat some of the tests that have been
22734          * done above)
22735          */
22736 
22737         boolean drawTop = false;
22738         boolean drawBottom = false;
22739         boolean drawLeft = false;
22740         boolean drawRight = false;
22741 
22742         float topFadeStrength = 0.0f;
22743         float bottomFadeStrength = 0.0f;
22744         float leftFadeStrength = 0.0f;
22745         float rightFadeStrength = 0.0f;
22746 
22747         // Step 2, save the canvas' layers
22748         int paddingLeft = mPaddingLeft;
22749 
22750         final boolean offsetRequired = isPaddingOffsetRequired();
22751         if (offsetRequired) {
22752             paddingLeft += getLeftPaddingOffset();
22753         }
22754 
22755         int left = mScrollX + paddingLeft;
22756         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
22757         int top = mScrollY + getFadeTop(offsetRequired);
22758         int bottom = top + getFadeHeight(offsetRequired);
22759 
22760         if (offsetRequired) {
22761             right += getRightPaddingOffset();
22762             bottom += getBottomPaddingOffset();
22763         }
22764 
22765         final ScrollabilityCache scrollabilityCache = mScrollCache;
22766         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
22767         int length = (int) fadeHeight;
22768 
22769         // clip the fade length if top and bottom fades overlap
22770         // overlapping fades produce odd-looking artifacts
22771         if (verticalEdges && (top + length > bottom - length)) {
22772             length = (bottom - top) / 2;
22773         }
22774 
22775         // also clip horizontal fades if necessary
22776         if (horizontalEdges && (left + length > right - length)) {
22777             length = (right - left) / 2;
22778         }
22779 
22780         if (verticalEdges) {
22781             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
22782             drawTop = topFadeStrength * fadeHeight > 1.0f;
22783             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
22784             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
22785         }
22786 
22787         if (horizontalEdges) {
22788             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
22789             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
22790             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
22791             drawRight = rightFadeStrength * fadeHeight > 1.0f;
22792         }
22793 
22794         saveCount = canvas.getSaveCount();
22795         int topSaveCount = -1;
22796         int bottomSaveCount = -1;
22797         int leftSaveCount = -1;
22798         int rightSaveCount = -1;
22799 
22800         int solidColor = getSolidColor();
22801         if (solidColor == 0) {
22802             if (drawTop) {
22803                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
22804             }
22805 
22806             if (drawBottom) {
22807                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
22808             }
22809 
22810             if (drawLeft) {
22811                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
22812             }
22813 
22814             if (drawRight) {
22815                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
22816             }
22817         } else {
22818             scrollabilityCache.setFadeColor(solidColor);
22819         }
22820 
22821         // Step 3, draw the content
22822         onDraw(canvas);
22823 
22824         // Step 4, draw the children
22825         dispatchDraw(canvas);
22826 
22827         // Step 5, draw the fade effect and restore layers
22828         final Paint p = scrollabilityCache.paint;
22829         final Matrix matrix = scrollabilityCache.matrix;
22830         final Shader fade = scrollabilityCache.shader;
22831 
22832         // must be restored in the reverse order that they were saved
22833         if (drawRight) {
22834             matrix.setScale(1, fadeHeight * rightFadeStrength);
22835             matrix.postRotate(90);
22836             matrix.postTranslate(right, top);
22837             fade.setLocalMatrix(matrix);
22838             p.setShader(fade);
22839             if (solidColor == 0) {
22840                 canvas.restoreUnclippedLayer(rightSaveCount, p);
22841 
22842             } else {
22843                 canvas.drawRect(right - length, top, right, bottom, p);
22844             }
22845         }
22846 
22847         if (drawLeft) {
22848             matrix.setScale(1, fadeHeight * leftFadeStrength);
22849             matrix.postRotate(-90);
22850             matrix.postTranslate(left, top);
22851             fade.setLocalMatrix(matrix);
22852             p.setShader(fade);
22853             if (solidColor == 0) {
22854                 canvas.restoreUnclippedLayer(leftSaveCount, p);
22855             } else {
22856                 canvas.drawRect(left, top, left + length, bottom, p);
22857             }
22858         }
22859 
22860         if (drawBottom) {
22861             matrix.setScale(1, fadeHeight * bottomFadeStrength);
22862             matrix.postRotate(180);
22863             matrix.postTranslate(left, bottom);
22864             fade.setLocalMatrix(matrix);
22865             p.setShader(fade);
22866             if (solidColor == 0) {
22867                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
22868             } else {
22869                 canvas.drawRect(left, bottom - length, right, bottom, p);
22870             }
22871         }
22872 
22873         if (drawTop) {
22874             matrix.setScale(1, fadeHeight * topFadeStrength);
22875             matrix.postTranslate(left, top);
22876             fade.setLocalMatrix(matrix);
22877             p.setShader(fade);
22878             if (solidColor == 0) {
22879                 canvas.restoreUnclippedLayer(topSaveCount, p);
22880             } else {
22881                 canvas.drawRect(left, top, right, top + length, p);
22882             }
22883         }
22884 
22885         canvas.restoreToCount(saveCount);
22886 
22887         drawAutofilledHighlight(canvas);
22888 
22889         // Overlay is part of the content and draws beneath Foreground
22890         if (mOverlay != null && !mOverlay.isEmpty()) {
22891             mOverlay.getOverlayView().dispatchDraw(canvas);
22892         }
22893 
22894         // Step 6, draw decorations (foreground, scrollbars)
22895         onDrawForeground(canvas);
22896 
22897         // Step 7, draw the default focus highlight
22898         drawDefaultFocusHighlight(canvas);
22899 
22900         if (isShowingLayoutBounds()) {
22901             debugDrawFocus(canvas);
22902         }
22903     }
22904 
22905     /**
22906      * Draws the background onto the specified canvas.
22907      *
22908      * @param canvas Canvas on which to draw the background
22909      */
22910     @UnsupportedAppUsage
drawBackground(Canvas canvas)22911     private void drawBackground(Canvas canvas) {
22912         final Drawable background = mBackground;
22913         if (background == null) {
22914             return;
22915         }
22916 
22917         setBackgroundBounds();
22918 
22919         // Attempt to use a display list if requested.
22920         if (canvas.isHardwareAccelerated() && mAttachInfo != null
22921                 && mAttachInfo.mThreadedRenderer != null) {
22922             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
22923 
22924             final RenderNode renderNode = mBackgroundRenderNode;
22925             if (renderNode != null && renderNode.hasDisplayList()) {
22926                 setBackgroundRenderNodeProperties(renderNode);
22927                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22928                 return;
22929             }
22930         }
22931 
22932         final int scrollX = mScrollX;
22933         final int scrollY = mScrollY;
22934         if ((scrollX | scrollY) == 0) {
22935             background.draw(canvas);
22936         } else {
22937             canvas.translate(scrollX, scrollY);
22938             background.draw(canvas);
22939             canvas.translate(-scrollX, -scrollY);
22940         }
22941     }
22942 
22943     /**
22944      * Sets the correct background bounds and rebuilds the outline, if needed.
22945      * <p/>
22946      * This is called by LayoutLib.
22947      */
setBackgroundBounds()22948     void setBackgroundBounds() {
22949         if (mBackgroundSizeChanged && mBackground != null) {
22950             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
22951             mBackgroundSizeChanged = false;
22952             rebuildOutline();
22953         }
22954     }
22955 
setBackgroundRenderNodeProperties(RenderNode renderNode)22956     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
22957         renderNode.setTranslationX(mScrollX);
22958         renderNode.setTranslationY(mScrollY);
22959     }
22960 
22961     /**
22962      * Creates a new display list or updates the existing display list for the
22963      * specified Drawable.
22964      *
22965      * @param drawable Drawable for which to create a display list
22966      * @param renderNode Existing RenderNode, or {@code null}
22967      * @return A valid display list for the specified drawable
22968      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)22969     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
22970         if (renderNode == null) {
22971             renderNode = RenderNode.create(drawable.getClass().getName(),
22972                     new ViewAnimationHostBridge(this));
22973             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
22974         }
22975 
22976         final Rect bounds = drawable.getBounds();
22977         final int width = bounds.width();
22978         final int height = bounds.height();
22979 
22980         // Hacky hack: Reset any stretch effects as those are applied during the draw pass
22981         // instead of being "stateful" like other RenderNode properties
22982         renderNode.clearStretch();
22983 
22984         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
22985 
22986         // Reverse left/top translation done by drawable canvas, which will
22987         // instead be applied by rendernode's LTRB bounds below. This way, the
22988         // drawable's bounds match with its rendernode bounds and its content
22989         // will lie within those bounds in the rendernode tree.
22990         canvas.translate(-bounds.left, -bounds.top);
22991 
22992         try {
22993             drawable.draw(canvas);
22994         } finally {
22995             renderNode.endRecording();
22996         }
22997 
22998         // Set up drawable properties that are view-independent.
22999         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
23000         renderNode.setProjectBackwards(drawable.isProjected());
23001         renderNode.setProjectionReceiver(true);
23002         renderNode.setClipToBounds(false);
23003         return renderNode;
23004     }
23005 
23006     /**
23007      * Returns the overlay for this view, creating it if it does not yet exist.
23008      * Adding drawables to the overlay will cause them to be displayed whenever
23009      * the view itself is redrawn. Objects in the overlay should be actively
23010      * managed: remove them when they should not be displayed anymore. The
23011      * overlay will always have the same size as its host view.
23012      *
23013      * <p>Note: Overlays do not currently work correctly with {@link
23014      * SurfaceView} or {@link TextureView}; contents in overlays for these
23015      * types of views may not display correctly.</p>
23016      *
23017      * @return The ViewOverlay object for this view.
23018      * @see ViewOverlay
23019      */
getOverlay()23020     public ViewOverlay getOverlay() {
23021         if (mOverlay == null) {
23022             mOverlay = new ViewOverlay(mContext, this);
23023         }
23024         return mOverlay;
23025     }
23026 
23027     /**
23028      * Override this if your view is known to always be drawn on top of a solid color background,
23029      * and needs to draw fading edges. Returning a non-zero color enables the view system to
23030      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
23031      * should be set to 0xFF.
23032      *
23033      * @see #setVerticalFadingEdgeEnabled(boolean)
23034      * @see #setHorizontalFadingEdgeEnabled(boolean)
23035      *
23036      * @return The known solid color background for this view, or 0 if the color may vary
23037      */
23038     @ViewDebug.ExportedProperty(category = "drawing")
23039     @InspectableProperty
23040     @ColorInt
getSolidColor()23041     public int getSolidColor() {
23042         return 0;
23043     }
23044 
23045     /**
23046      * Build a human readable string representation of the specified view flags.
23047      *
23048      * @param flags the view flags to convert to a string
23049      * @return a String representing the supplied flags
23050      */
printFlags(int flags)23051     private static String printFlags(int flags) {
23052         String output = "";
23053         int numFlags = 0;
23054         if ((flags & FOCUSABLE) == FOCUSABLE) {
23055             output += "TAKES_FOCUS";
23056             numFlags++;
23057         }
23058 
23059         switch (flags & VISIBILITY_MASK) {
23060         case INVISIBLE:
23061             if (numFlags > 0) {
23062                 output += " ";
23063             }
23064             output += "INVISIBLE";
23065             // USELESS HERE numFlags++;
23066             break;
23067         case GONE:
23068             if (numFlags > 0) {
23069                 output += " ";
23070             }
23071             output += "GONE";
23072             // USELESS HERE numFlags++;
23073             break;
23074         default:
23075             break;
23076         }
23077         return output;
23078     }
23079 
23080     /**
23081      * Build a human readable string representation of the specified private
23082      * view flags.
23083      *
23084      * @param privateFlags the private view flags to convert to a string
23085      * @return a String representing the supplied flags
23086      */
printPrivateFlags(int privateFlags)23087     private static String printPrivateFlags(int privateFlags) {
23088         String output = "";
23089         int numFlags = 0;
23090 
23091         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
23092             output += "WANTS_FOCUS";
23093             numFlags++;
23094         }
23095 
23096         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
23097             if (numFlags > 0) {
23098                 output += " ";
23099             }
23100             output += "FOCUSED";
23101             numFlags++;
23102         }
23103 
23104         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
23105             if (numFlags > 0) {
23106                 output += " ";
23107             }
23108             output += "SELECTED";
23109             numFlags++;
23110         }
23111 
23112         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
23113             if (numFlags > 0) {
23114                 output += " ";
23115             }
23116             output += "IS_ROOT_NAMESPACE";
23117             numFlags++;
23118         }
23119 
23120         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
23121             if (numFlags > 0) {
23122                 output += " ";
23123             }
23124             output += "HAS_BOUNDS";
23125             numFlags++;
23126         }
23127 
23128         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
23129             if (numFlags > 0) {
23130                 output += " ";
23131             }
23132             output += "DRAWN";
23133             // USELESS HERE numFlags++;
23134         }
23135         return output;
23136     }
23137 
23138     /**
23139      * <p>Indicates whether or not this view's layout will be requested during
23140      * the next hierarchy layout pass.</p>
23141      *
23142      * @return true if the layout will be forced during next layout pass
23143      */
isLayoutRequested()23144     public boolean isLayoutRequested() {
23145         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
23146     }
23147 
23148     /**
23149      * Return true if o is a ViewGroup that is laying out using optical bounds.
23150      * @hide
23151      */
isLayoutModeOptical(Object o)23152     public static boolean isLayoutModeOptical(Object o) {
23153         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
23154     }
23155 
setOpticalFrame(int left, int top, int right, int bottom)23156     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
23157         Insets parentInsets = mParent instanceof View ?
23158                 ((View) mParent).getOpticalInsets() : Insets.NONE;
23159         Insets childInsets = getOpticalInsets();
23160         return setFrame(
23161                 left   + parentInsets.left - childInsets.left,
23162                 top    + parentInsets.top  - childInsets.top,
23163                 right  + parentInsets.left + childInsets.right,
23164                 bottom + parentInsets.top  + childInsets.bottom);
23165     }
23166 
23167     /**
23168      * Assign a size and position to a view and all of its
23169      * descendants
23170      *
23171      * <p>This is the second phase of the layout mechanism.
23172      * (The first is measuring). In this phase, each parent calls
23173      * layout on all of its children to position them.
23174      * This is typically done using the child measurements
23175      * that were stored in the measure pass().</p>
23176      *
23177      * <p>Derived classes should not override this method.
23178      * Derived classes with children should override
23179      * onLayout. In that method, they should
23180      * call layout on each of their children.</p>
23181      *
23182      * @param l Left position, relative to parent
23183      * @param t Top position, relative to parent
23184      * @param r Right position, relative to parent
23185      * @param b Bottom position, relative to parent
23186      */
23187     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)23188     public void layout(int l, int t, int r, int b) {
23189         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
23190             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
23191             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
23192         }
23193 
23194         int oldL = mLeft;
23195         int oldT = mTop;
23196         int oldB = mBottom;
23197         int oldR = mRight;
23198 
23199         boolean changed = isLayoutModeOptical(mParent) ?
23200                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
23201 
23202         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
23203             onLayout(changed, l, t, r, b);
23204 
23205             if (shouldDrawRoundScrollbar()) {
23206                 if(mRoundScrollbarRenderer == null) {
23207                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
23208                 }
23209             } else {
23210                 mRoundScrollbarRenderer = null;
23211             }
23212 
23213             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
23214 
23215             ListenerInfo li = mListenerInfo;
23216             if (li != null && li.mOnLayoutChangeListeners != null) {
23217                 ArrayList<OnLayoutChangeListener> listenersCopy =
23218                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
23219                 int numListeners = listenersCopy.size();
23220                 for (int i = 0; i < numListeners; ++i) {
23221                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
23222                 }
23223             }
23224         }
23225 
23226         final boolean wasLayoutValid = isLayoutValid();
23227 
23228         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
23229         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
23230 
23231         if (!wasLayoutValid && isFocused()) {
23232             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
23233             if (canTakeFocus()) {
23234                 // We have a robust focus, so parents should no longer be wanting focus.
23235                 clearParentsWantFocus();
23236             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
23237                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
23238                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
23239                 // and thus the safest action is to clear focus here.
23240                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23241                 clearParentsWantFocus();
23242             } else if (!hasParentWantsFocus()) {
23243                 // original requestFocus was likely on this view directly, so just clear focus
23244                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23245             }
23246             // otherwise, we let parents handle re-assigning focus during their layout passes.
23247         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
23248             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
23249             View focused = findFocus();
23250             if (focused != null) {
23251                 // Try to restore focus as close as possible to our starting focus.
23252                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
23253                     // Give up and clear focus once we've reached the top-most parent which wants
23254                     // focus.
23255                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23256                 }
23257             }
23258         }
23259 
23260         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
23261             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
23262             notifyEnterOrExitForAutoFillIfNeeded(true);
23263         }
23264 
23265         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
23266     }
23267 
hasParentWantsFocus()23268     private boolean hasParentWantsFocus() {
23269         ViewParent parent = mParent;
23270         while (parent instanceof ViewGroup) {
23271             ViewGroup pv = (ViewGroup) parent;
23272             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
23273                 return true;
23274             }
23275             parent = pv.mParent;
23276         }
23277         return false;
23278     }
23279 
23280     /**
23281      * Called from layout when this view should
23282      * assign a size and position to each of its children.
23283      *
23284      * Derived classes with children should override
23285      * this method and call layout on each of
23286      * their children.
23287      * @param changed This is a new size or position for this view
23288      * @param left Left position, relative to parent
23289      * @param top Top position, relative to parent
23290      * @param right Right position, relative to parent
23291      * @param bottom Bottom position, relative to parent
23292      */
onLayout(boolean changed, int left, int top, int right, int bottom)23293     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
23294     }
23295 
23296     /**
23297      * Assign a size and position to this view.
23298      *
23299      * This is called from layout.
23300      *
23301      * @param left Left position, relative to parent
23302      * @param top Top position, relative to parent
23303      * @param right Right position, relative to parent
23304      * @param bottom Bottom position, relative to parent
23305      * @return true if the new size and position are different than the
23306      *         previous ones
23307      * {@hide}
23308      */
23309     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)23310     protected boolean setFrame(int left, int top, int right, int bottom) {
23311         boolean changed = false;
23312 
23313         if (DBG) {
23314             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
23315                     + right + "," + bottom + ")");
23316         }
23317 
23318         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
23319             changed = true;
23320 
23321             // Remember our drawn bit
23322             int drawn = mPrivateFlags & PFLAG_DRAWN;
23323 
23324             int oldWidth = mRight - mLeft;
23325             int oldHeight = mBottom - mTop;
23326             int newWidth = right - left;
23327             int newHeight = bottom - top;
23328             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
23329 
23330             // Invalidate our old position
23331             invalidate(sizeChanged);
23332 
23333             mLeft = left;
23334             mTop = top;
23335             mRight = right;
23336             mBottom = bottom;
23337             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
23338 
23339             mPrivateFlags |= PFLAG_HAS_BOUNDS;
23340 
23341 
23342             if (sizeChanged) {
23343                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
23344             }
23345 
23346             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
23347                 // If we are visible, force the DRAWN bit to on so that
23348                 // this invalidate will go through (at least to our parent).
23349                 // This is because someone may have invalidated this view
23350                 // before this call to setFrame came in, thereby clearing
23351                 // the DRAWN bit.
23352                 mPrivateFlags |= PFLAG_DRAWN;
23353                 invalidate(sizeChanged);
23354                 // parent display list may need to be recreated based on a change in the bounds
23355                 // of any child
23356                 invalidateParentCaches();
23357             }
23358 
23359             // Reset drawn bit to original value (invalidate turns it off)
23360             mPrivateFlags |= drawn;
23361 
23362             mBackgroundSizeChanged = true;
23363             mDefaultFocusHighlightSizeChanged = true;
23364             if (mForegroundInfo != null) {
23365                 mForegroundInfo.mBoundsChanged = true;
23366             }
23367 
23368             notifySubtreeAccessibilityStateChangedIfNeeded();
23369         }
23370         return changed;
23371     }
23372 
23373     /**
23374      * Assign a size and position to this view.
23375      *
23376      * This method is meant to be used in animations only as it applies this position and size
23377      * for the view only temporary and it can be changed back at any time by the layout.
23378      *
23379      * @param left Left position, relative to parent
23380      * @param top Top position, relative to parent
23381      * @param right Right position, relative to parent
23382      * @param bottom Bottom position, relative to parent
23383      *
23384      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
23385      */
setLeftTopRightBottom(int left, int top, int right, int bottom)23386     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
23387         setFrame(left, top, right, bottom);
23388     }
23389 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)23390     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
23391         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
23392         if (mOverlay != null) {
23393             mOverlay.getOverlayView().setRight(newWidth);
23394             mOverlay.getOverlayView().setBottom(newHeight);
23395         }
23396         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
23397         // backtracking" of requestFocus during layout, so don't touch focus here.
23398         if (!sCanFocusZeroSized && isLayoutValid()
23399                 // Don't touch focus if animating
23400                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
23401             if (newWidth <= 0 || newHeight <= 0) {
23402                 if (hasFocus()) {
23403                     clearFocus();
23404                     if (mParent instanceof ViewGroup) {
23405                         ((ViewGroup) mParent).clearFocusedInCluster();
23406                     }
23407                 }
23408                 clearAccessibilityFocus();
23409             } else if (oldWidth <= 0 || oldHeight <= 0) {
23410                 if (mParent != null && canTakeFocus()) {
23411                     mParent.focusableViewAvailable(this);
23412                 }
23413             }
23414         }
23415         rebuildOutline();
23416     }
23417 
23418     /**
23419      * Finalize inflating a view from XML.  This is called as the last phase
23420      * of inflation, after all child views have been added.
23421      *
23422      * <p>Even if the subclass overrides onFinishInflate, they should always be
23423      * sure to call the super method, so that we get called.
23424      */
23425     @CallSuper
onFinishInflate()23426     protected void onFinishInflate() {
23427     }
23428 
23429     /**
23430      * Returns the resources associated with this view.
23431      *
23432      * @return Resources object.
23433      */
getResources()23434     public Resources getResources() {
23435         return mResources;
23436     }
23437 
23438     /**
23439      * Invalidates the specified Drawable.
23440      *
23441      * @param drawable the drawable to invalidate
23442      */
23443     @Override
invalidateDrawable(@onNull Drawable drawable)23444     public void invalidateDrawable(@NonNull Drawable drawable) {
23445         if (verifyDrawable(drawable)) {
23446             final Rect dirty = drawable.getDirtyBounds();
23447             final int scrollX = mScrollX;
23448             final int scrollY = mScrollY;
23449 
23450             invalidate(dirty.left + scrollX, dirty.top + scrollY,
23451                     dirty.right + scrollX, dirty.bottom + scrollY);
23452             rebuildOutline();
23453         }
23454     }
23455 
23456     /**
23457      * Schedules an action on a drawable to occur at a specified time.
23458      *
23459      * @param who the recipient of the action
23460      * @param what the action to run on the drawable
23461      * @param when the time at which the action must occur. Uses the
23462      *        {@link SystemClock#uptimeMillis} timebase.
23463      */
23464     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)23465     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
23466         if (verifyDrawable(who) && what != null) {
23467             final long delay = when - SystemClock.uptimeMillis();
23468             if (mAttachInfo != null) {
23469                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
23470                         Choreographer.CALLBACK_ANIMATION, what, who,
23471                         Choreographer.subtractFrameDelay(delay));
23472             } else {
23473                 // Postpone the runnable until we know
23474                 // on which thread it needs to run.
23475                 getRunQueue().postDelayed(what, delay);
23476             }
23477         }
23478     }
23479 
23480     /**
23481      * Cancels a scheduled action on a drawable.
23482      *
23483      * @param who the recipient of the action
23484      * @param what the action to cancel
23485      */
23486     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)23487     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
23488         if (verifyDrawable(who) && what != null) {
23489             if (mAttachInfo != null) {
23490                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
23491                         Choreographer.CALLBACK_ANIMATION, what, who);
23492             }
23493             getRunQueue().removeCallbacks(what);
23494         }
23495     }
23496 
23497     /**
23498      * Unschedule any events associated with the given Drawable.  This can be
23499      * used when selecting a new Drawable into a view, so that the previous
23500      * one is completely unscheduled.
23501      *
23502      * @param who The Drawable to unschedule.
23503      *
23504      * @see #drawableStateChanged
23505      */
unscheduleDrawable(Drawable who)23506     public void unscheduleDrawable(Drawable who) {
23507         if (mAttachInfo != null && who != null) {
23508             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
23509                     Choreographer.CALLBACK_ANIMATION, null, who);
23510         }
23511     }
23512 
23513     /**
23514      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
23515      * that the View directionality can and will be resolved before its Drawables.
23516      *
23517      * Will call {@link View#onResolveDrawables} when resolution is done.
23518      *
23519      * @hide
23520      */
resolveDrawables()23521     protected void resolveDrawables() {
23522         // Drawables resolution may need to happen before resolving the layout direction (which is
23523         // done only during the measure() call).
23524         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
23525         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
23526         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
23527         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
23528         // direction to be resolved as its resolved value will be the same as its raw value.
23529         if (!isLayoutDirectionResolved() &&
23530                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
23531             return;
23532         }
23533 
23534         final int layoutDirection = isLayoutDirectionResolved() ?
23535                 getLayoutDirection() : getRawLayoutDirection();
23536 
23537         if (mBackground != null) {
23538             mBackground.setLayoutDirection(layoutDirection);
23539         }
23540         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23541             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
23542         }
23543         if (mDefaultFocusHighlight != null) {
23544             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
23545         }
23546         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
23547         onResolveDrawables(layoutDirection);
23548     }
23549 
areDrawablesResolved()23550     boolean areDrawablesResolved() {
23551         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
23552     }
23553 
23554     /**
23555      * Called when layout direction has been resolved.
23556      *
23557      * The default implementation does nothing.
23558      *
23559      * @param layoutDirection The resolved layout direction.
23560      *
23561      * @see #LAYOUT_DIRECTION_LTR
23562      * @see #LAYOUT_DIRECTION_RTL
23563      *
23564      * @hide
23565      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)23566     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
23567     }
23568 
23569     /**
23570      * @hide
23571      */
23572     @TestApi
resetResolvedDrawables()23573     protected void resetResolvedDrawables() {
23574         resetResolvedDrawablesInternal();
23575     }
23576 
resetResolvedDrawablesInternal()23577     void resetResolvedDrawablesInternal() {
23578         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
23579     }
23580 
23581     /**
23582      * If your view subclass is displaying its own Drawable objects, it should
23583      * override this function and return true for any Drawable it is
23584      * displaying.  This allows animations for those drawables to be
23585      * scheduled.
23586      *
23587      * <p>Be sure to call through to the super class when overriding this
23588      * function.
23589      *
23590      * @param who The Drawable to verify.  Return true if it is one you are
23591      *            displaying, else return the result of calling through to the
23592      *            super class.
23593      *
23594      * @return boolean If true then the Drawable is being displayed in the
23595      *         view; else false and it is not allowed to animate.
23596      *
23597      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
23598      * @see #drawableStateChanged()
23599      */
23600     @CallSuper
verifyDrawable(@onNull Drawable who)23601     protected boolean verifyDrawable(@NonNull Drawable who) {
23602         // Avoid verifying the scroll bar drawable so that we don't end up in
23603         // an invalidation loop. This effectively prevents the scroll bar
23604         // drawable from triggering invalidations and scheduling runnables.
23605         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
23606                 || (mDefaultFocusHighlight == who);
23607     }
23608 
23609     /**
23610      * This function is called whenever the state of the view changes in such
23611      * a way that it impacts the state of drawables being shown.
23612      * <p>
23613      * If the View has a StateListAnimator, it will also be called to run necessary state
23614      * change animations.
23615      * <p>
23616      * Be sure to call through to the superclass when overriding this function.
23617      *
23618      * @see Drawable#setState(int[])
23619      */
23620     @CallSuper
drawableStateChanged()23621     protected void drawableStateChanged() {
23622         final int[] state = getDrawableState();
23623         boolean changed = false;
23624 
23625         final Drawable bg = mBackground;
23626         if (bg != null && bg.isStateful()) {
23627             changed |= bg.setState(state);
23628         }
23629 
23630         final Drawable hl = mDefaultFocusHighlight;
23631         if (hl != null && hl.isStateful()) {
23632             changed |= hl.setState(state);
23633         }
23634 
23635         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23636         if (fg != null && fg.isStateful()) {
23637             changed |= fg.setState(state);
23638         }
23639 
23640         if (mScrollCache != null) {
23641             final Drawable scrollBar = mScrollCache.scrollBar;
23642             if (scrollBar != null && scrollBar.isStateful()) {
23643                 changed |= scrollBar.setState(state)
23644                         && mScrollCache.state != ScrollabilityCache.OFF;
23645             }
23646         }
23647 
23648         if (mStateListAnimator != null) {
23649             mStateListAnimator.setState(state);
23650         }
23651 
23652         if (!isAggregatedVisible()) {
23653             // If we're not visible, skip any animated changes
23654             jumpDrawablesToCurrentState();
23655         }
23656 
23657         if (changed) {
23658             invalidate();
23659         }
23660     }
23661 
23662     /**
23663      * This function is called whenever the view hotspot changes and needs to
23664      * be propagated to drawables or child views managed by the view.
23665      * <p>
23666      * Dispatching to child views is handled by
23667      * {@link #dispatchDrawableHotspotChanged(float, float)}.
23668      * <p>
23669      * Be sure to call through to the superclass when overriding this function.
23670      *
23671      * @param x hotspot x coordinate
23672      * @param y hotspot y coordinate
23673      */
23674     @CallSuper
drawableHotspotChanged(float x, float y)23675     public void drawableHotspotChanged(float x, float y) {
23676         if (mBackground != null) {
23677             mBackground.setHotspot(x, y);
23678         }
23679         if (mDefaultFocusHighlight != null) {
23680             mDefaultFocusHighlight.setHotspot(x, y);
23681         }
23682         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23683             mForegroundInfo.mDrawable.setHotspot(x, y);
23684         }
23685 
23686         dispatchDrawableHotspotChanged(x, y);
23687     }
23688 
23689     /**
23690      * Dispatches drawableHotspotChanged to all of this View's children.
23691      *
23692      * @param x hotspot x coordinate
23693      * @param y hotspot y coordinate
23694      * @see #drawableHotspotChanged(float, float)
23695      */
dispatchDrawableHotspotChanged(float x, float y)23696     public void dispatchDrawableHotspotChanged(float x, float y) {
23697     }
23698 
23699     /**
23700      * Call this to force a view to update its drawable state. This will cause
23701      * drawableStateChanged to be called on this view. Views that are interested
23702      * in the new state should call getDrawableState.
23703      *
23704      * @see #drawableStateChanged
23705      * @see #getDrawableState
23706      */
refreshDrawableState()23707     public void refreshDrawableState() {
23708         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
23709         drawableStateChanged();
23710 
23711         ViewParent parent = mParent;
23712         if (parent != null) {
23713             parent.childDrawableStateChanged(this);
23714         }
23715     }
23716 
23717     /**
23718      * Create a default focus highlight if it doesn't exist.
23719      * @return a default focus highlight.
23720      */
getDefaultFocusHighlightDrawable()23721     private Drawable getDefaultFocusHighlightDrawable() {
23722         if (mDefaultFocusHighlightCache == null) {
23723             if (mContext != null) {
23724                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
23725                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
23726                 mDefaultFocusHighlightCache = ta.getDrawable(0);
23727                 ta.recycle();
23728             }
23729         }
23730         return mDefaultFocusHighlightCache;
23731     }
23732 
23733     /**
23734      * Set the current default focus highlight.
23735      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
23736      */
setDefaultFocusHighlight(Drawable highlight)23737     private void setDefaultFocusHighlight(Drawable highlight) {
23738         mDefaultFocusHighlight = highlight;
23739         mDefaultFocusHighlightSizeChanged = true;
23740         if (highlight != null) {
23741             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23742                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23743             }
23744             highlight.setLayoutDirection(getLayoutDirection());
23745             if (highlight.isStateful()) {
23746                 highlight.setState(getDrawableState());
23747             }
23748             if (isAttachedToWindow()) {
23749                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23750             }
23751             // Set callback last, since the view may still be initializing.
23752             highlight.setCallback(this);
23753         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23754                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
23755             mPrivateFlags |= PFLAG_SKIP_DRAW;
23756         }
23757         invalidate();
23758     }
23759 
23760     /**
23761      * Check whether we need to draw a default focus highlight when this view gets focused,
23762      * which requires:
23763      * <ul>
23764      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
23765      *         is not defined.</li>
23766      *     <li>This view is not in touch mode.</li>
23767      *     <li>This view doesn't opt out for a default focus highlight, via
23768      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
23769      *     <li>This view is attached to window.</li>
23770      * </ul>
23771      * @return {@code true} if a default focus highlight is needed.
23772      * @hide
23773      */
23774     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)23775     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
23776         final boolean lackFocusState = (background == null || !background.isStateful()
23777                 || !background.hasFocusStateSpecified())
23778                 && (foreground == null || !foreground.isStateful()
23779                 || !foreground.hasFocusStateSpecified());
23780         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
23781                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
23782     }
23783 
23784     /**
23785      * When this view is focused, switches on/off the default focused highlight.
23786      * <p>
23787      * This always happens when this view is focused, and only at this moment the default focus
23788      * highlight can be visible.
23789      */
switchDefaultFocusHighlight()23790     private void switchDefaultFocusHighlight() {
23791         if (isFocused()) {
23792             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
23793                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
23794             final boolean active = mDefaultFocusHighlight != null;
23795             if (needed && !active) {
23796                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
23797             } else if (!needed && active) {
23798                 // The highlight is no longer needed, so tear it down.
23799                 setDefaultFocusHighlight(null);
23800             }
23801         }
23802     }
23803 
23804     /**
23805      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
23806      * @param canvas the canvas where we're drawing the highlight.
23807      */
drawDefaultFocusHighlight(Canvas canvas)23808     private void drawDefaultFocusHighlight(Canvas canvas) {
23809         if (mDefaultFocusHighlight != null && isFocused()) {
23810             if (mDefaultFocusHighlightSizeChanged) {
23811                 mDefaultFocusHighlightSizeChanged = false;
23812                 final int l = mScrollX;
23813                 final int r = l + mRight - mLeft;
23814                 final int t = mScrollY;
23815                 final int b = t + mBottom - mTop;
23816                 mDefaultFocusHighlight.setBounds(l, t, r, b);
23817             }
23818             mDefaultFocusHighlight.draw(canvas);
23819         }
23820     }
23821 
23822     /**
23823      * Return an array of resource IDs of the drawable states representing the
23824      * current state of the view.
23825      *
23826      * @return The current drawable state
23827      *
23828      * @see Drawable#setState(int[])
23829      * @see #drawableStateChanged()
23830      * @see #onCreateDrawableState(int)
23831      */
getDrawableState()23832     public final int[] getDrawableState() {
23833         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
23834             return mDrawableState;
23835         } else {
23836             mDrawableState = onCreateDrawableState(0);
23837             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
23838             return mDrawableState;
23839         }
23840     }
23841 
23842     /**
23843      * Generate the new {@link android.graphics.drawable.Drawable} state for
23844      * this view. This is called by the view
23845      * system when the cached Drawable state is determined to be invalid.  To
23846      * retrieve the current state, you should use {@link #getDrawableState}.
23847      *
23848      * @param extraSpace if non-zero, this is the number of extra entries you
23849      * would like in the returned array in which you can place your own
23850      * states.
23851      *
23852      * @return Returns an array holding the current {@link Drawable} state of
23853      * the view.
23854      *
23855      * @see #mergeDrawableStates(int[], int[])
23856      */
onCreateDrawableState(int extraSpace)23857     protected int[] onCreateDrawableState(int extraSpace) {
23858         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
23859                 mParent instanceof View) {
23860             return ((View) mParent).onCreateDrawableState(extraSpace);
23861         }
23862 
23863         int[] drawableState;
23864 
23865         int privateFlags = mPrivateFlags;
23866 
23867         int viewStateIndex = 0;
23868         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
23869         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
23870         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
23871         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
23872         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
23873         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
23874         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
23875             // This is set if HW acceleration is requested, even if the current
23876             // process doesn't allow it.  This is just to allow app preview
23877             // windows to better match their app.
23878             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
23879         }
23880         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
23881 
23882         final int privateFlags2 = mPrivateFlags2;
23883         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
23884             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
23885         }
23886         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
23887             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
23888         }
23889 
23890         drawableState = StateSet.get(viewStateIndex);
23891 
23892         //noinspection ConstantIfStatement
23893         if (false) {
23894             Log.i("View", "drawableStateIndex=" + viewStateIndex);
23895             Log.i("View", toString()
23896                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
23897                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
23898                     + " fo=" + hasFocus()
23899                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
23900                     + " wf=" + hasWindowFocus()
23901                     + ": " + Arrays.toString(drawableState));
23902         }
23903 
23904         if (extraSpace == 0) {
23905             return drawableState;
23906         }
23907 
23908         final int[] fullState;
23909         if (drawableState != null) {
23910             fullState = new int[drawableState.length + extraSpace];
23911             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
23912         } else {
23913             fullState = new int[extraSpace];
23914         }
23915 
23916         return fullState;
23917     }
23918 
23919     /**
23920      * Merge your own state values in <var>additionalState</var> into the base
23921      * state values <var>baseState</var> that were returned by
23922      * {@link #onCreateDrawableState(int)}.
23923      *
23924      * @param baseState The base state values returned by
23925      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
23926      * own additional state values.
23927      *
23928      * @param additionalState The additional state values you would like
23929      * added to <var>baseState</var>; this array is not modified.
23930      *
23931      * @return As a convenience, the <var>baseState</var> array you originally
23932      * passed into the function is returned.
23933      *
23934      * @see #onCreateDrawableState(int)
23935      */
mergeDrawableStates(int[] baseState, int[] additionalState)23936     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
23937         final int N = baseState.length;
23938         int i = N - 1;
23939         while (i >= 0 && baseState[i] == 0) {
23940             i--;
23941         }
23942         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
23943         return baseState;
23944     }
23945 
23946     /**
23947      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
23948      * on all Drawable objects associated with this view.
23949      * <p>
23950      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
23951      * attached to this view.
23952      */
23953     @CallSuper
jumpDrawablesToCurrentState()23954     public void jumpDrawablesToCurrentState() {
23955         if (mBackground != null) {
23956             mBackground.jumpToCurrentState();
23957         }
23958         if (mStateListAnimator != null) {
23959             mStateListAnimator.jumpToCurrentState();
23960         }
23961         if (mDefaultFocusHighlight != null) {
23962             mDefaultFocusHighlight.jumpToCurrentState();
23963         }
23964         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23965             mForegroundInfo.mDrawable.jumpToCurrentState();
23966         }
23967     }
23968 
23969     /**
23970      * Sets the background color for this view.
23971      * @param color the color of the background
23972      */
23973     @RemotableViewMethod
setBackgroundColor(@olorInt int color)23974     public void setBackgroundColor(@ColorInt int color) {
23975         if (mBackground instanceof ColorDrawable) {
23976             ((ColorDrawable) mBackground.mutate()).setColor(color);
23977             computeOpaqueFlags();
23978             mBackgroundResource = 0;
23979         } else {
23980             setBackground(new ColorDrawable(color));
23981         }
23982     }
23983 
23984     /**
23985      * Set the background to a given resource. The resource should refer to
23986      * a Drawable object or 0 to remove the background.
23987      * @param resid The identifier of the resource.
23988      *
23989      * @attr ref android.R.styleable#View_background
23990      */
23991     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)23992     public void setBackgroundResource(@DrawableRes int resid) {
23993         if (resid != 0 && resid == mBackgroundResource) {
23994             return;
23995         }
23996 
23997         Drawable d = null;
23998         if (resid != 0) {
23999             d = mContext.getDrawable(resid);
24000         }
24001         setBackground(d);
24002 
24003         mBackgroundResource = resid;
24004     }
24005 
24006     /**
24007      * Set the background to a given Drawable, or remove the background. If the
24008      * background has padding, this View's padding is set to the background's
24009      * padding. However, when a background is removed, this View's padding isn't
24010      * touched. If setting the padding is desired, please use
24011      * {@link #setPadding(int, int, int, int)}.
24012      *
24013      * @param background The Drawable to use as the background, or null to remove the
24014      *        background
24015      */
setBackground(Drawable background)24016     public void setBackground(Drawable background) {
24017         //noinspection deprecation
24018         setBackgroundDrawable(background);
24019     }
24020 
24021     /**
24022      * @deprecated use {@link #setBackground(Drawable)} instead
24023      */
24024     @Deprecated
setBackgroundDrawable(Drawable background)24025     public void setBackgroundDrawable(Drawable background) {
24026         computeOpaqueFlags();
24027 
24028         if (background == mBackground) {
24029             return;
24030         }
24031 
24032         boolean requestLayout = false;
24033 
24034         mBackgroundResource = 0;
24035 
24036         /*
24037          * Regardless of whether we're setting a new background or not, we want
24038          * to clear the previous drawable. setVisible first while we still have the callback set.
24039          */
24040         if (mBackground != null) {
24041             if (isAttachedToWindow()) {
24042                 mBackground.setVisible(false, false);
24043             }
24044             mBackground.setCallback(null);
24045             unscheduleDrawable(mBackground);
24046         }
24047 
24048         if (background != null) {
24049             Rect padding = sThreadLocal.get();
24050             if (padding == null) {
24051                 padding = new Rect();
24052                 sThreadLocal.set(padding);
24053             }
24054             resetResolvedDrawablesInternal();
24055             background.setLayoutDirection(getLayoutDirection());
24056             if (background.getPadding(padding)) {
24057                 resetResolvedPaddingInternal();
24058                 switch (background.getLayoutDirection()) {
24059                     case LAYOUT_DIRECTION_RTL:
24060                         mUserPaddingLeftInitial = padding.right;
24061                         mUserPaddingRightInitial = padding.left;
24062                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
24063                         break;
24064                     case LAYOUT_DIRECTION_LTR:
24065                     default:
24066                         mUserPaddingLeftInitial = padding.left;
24067                         mUserPaddingRightInitial = padding.right;
24068                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
24069                 }
24070                 mLeftPaddingDefined = false;
24071                 mRightPaddingDefined = false;
24072             }
24073 
24074             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
24075             // if it has a different minimum size, we should layout again
24076             if (mBackground == null
24077                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
24078                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
24079                 requestLayout = true;
24080             }
24081 
24082             // Set mBackground before we set this as the callback and start making other
24083             // background drawable state change calls. In particular, the setVisible call below
24084             // can result in drawables attempting to start animations or otherwise invalidate,
24085             // which requires the view set as the callback (us) to recognize the drawable as
24086             // belonging to it as per verifyDrawable.
24087             mBackground = background;
24088             if (background.isStateful()) {
24089                 background.setState(getDrawableState());
24090             }
24091             if (isAttachedToWindow()) {
24092                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24093             }
24094 
24095             applyBackgroundTint();
24096 
24097             // Set callback last, since the view may still be initializing.
24098             background.setCallback(this);
24099 
24100             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24101                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24102                 requestLayout = true;
24103             }
24104         } else {
24105             /* Remove the background */
24106             mBackground = null;
24107             if ((mViewFlags & WILL_NOT_DRAW) != 0
24108                     && (mDefaultFocusHighlight == null)
24109                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
24110                 mPrivateFlags |= PFLAG_SKIP_DRAW;
24111             }
24112 
24113             /*
24114              * When the background is set, we try to apply its padding to this
24115              * View. When the background is removed, we don't touch this View's
24116              * padding. This is noted in the Javadocs. Hence, we don't need to
24117              * requestLayout(), the invalidate() below is sufficient.
24118              */
24119 
24120             // The old background's minimum size could have affected this
24121             // View's layout, so let's requestLayout
24122             requestLayout = true;
24123         }
24124 
24125         computeOpaqueFlags();
24126 
24127         if (requestLayout) {
24128             requestLayout();
24129         }
24130 
24131         mBackgroundSizeChanged = true;
24132         invalidate(true);
24133         invalidateOutline();
24134     }
24135 
24136     /**
24137      * Gets the background drawable
24138      *
24139      * @return The drawable used as the background for this view, if any.
24140      *
24141      * @see #setBackground(Drawable)
24142      *
24143      * @attr ref android.R.styleable#View_background
24144      */
24145     @InspectableProperty
getBackground()24146     public Drawable getBackground() {
24147         return mBackground;
24148     }
24149 
24150     /**
24151      * Applies a tint to the background drawable. Does not modify the current tint
24152      * mode, which is {@link BlendMode#SRC_IN} by default.
24153      * <p>
24154      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
24155      * mutate the drawable and apply the specified tint and tint mode using
24156      * {@link Drawable#setTintList(ColorStateList)}.
24157      *
24158      * @param tint the tint to apply, may be {@code null} to clear tint
24159      *
24160      * @attr ref android.R.styleable#View_backgroundTint
24161      * @see #getBackgroundTintList()
24162      * @see Drawable#setTintList(ColorStateList)
24163      */
24164     @RemotableViewMethod
setBackgroundTintList(@ullable ColorStateList tint)24165     public void setBackgroundTintList(@Nullable ColorStateList tint) {
24166         if (mBackgroundTint == null) {
24167             mBackgroundTint = new TintInfo();
24168         }
24169         mBackgroundTint.mTintList = tint;
24170         mBackgroundTint.mHasTintList = true;
24171 
24172         applyBackgroundTint();
24173     }
24174 
24175     /**
24176      * Return the tint applied to the background drawable, if specified.
24177      *
24178      * @return the tint applied to the background drawable
24179      * @attr ref android.R.styleable#View_backgroundTint
24180      * @see #setBackgroundTintList(ColorStateList)
24181      */
24182     @InspectableProperty(name = "backgroundTint")
24183     @Nullable
getBackgroundTintList()24184     public ColorStateList getBackgroundTintList() {
24185         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
24186     }
24187 
24188     /**
24189      * Specifies the blending mode used to apply the tint specified by
24190      * {@link #setBackgroundTintList(ColorStateList)}} to the background
24191      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
24192      *
24193      * @param tintMode the blending mode used to apply the tint, may be
24194      *                 {@code null} to clear tint
24195      * @attr ref android.R.styleable#View_backgroundTintMode
24196      * @see #getBackgroundTintMode()
24197      * @see Drawable#setTintMode(PorterDuff.Mode)
24198      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)24199     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
24200         BlendMode mode = null;
24201         if (tintMode != null) {
24202             mode = BlendMode.fromValue(tintMode.nativeInt);
24203         }
24204 
24205         setBackgroundTintBlendMode(mode);
24206     }
24207 
24208     /**
24209      * Specifies the blending mode used to apply the tint specified by
24210      * {@link #setBackgroundTintList(ColorStateList)}} to the background
24211      * drawable. The default mode is {@link BlendMode#SRC_IN}.
24212      *
24213      * @param blendMode the blending mode used to apply the tint, may be
24214      *                 {@code null} to clear tint
24215      * @attr ref android.R.styleable#View_backgroundTintMode
24216      * @see #getBackgroundTintMode()
24217      * @see Drawable#setTintBlendMode(BlendMode)
24218      */
24219     @RemotableViewMethod
setBackgroundTintBlendMode(@ullable BlendMode blendMode)24220     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
24221         if (mBackgroundTint == null) {
24222             mBackgroundTint = new TintInfo();
24223         }
24224 
24225         mBackgroundTint.mBlendMode = blendMode;
24226         mBackgroundTint.mHasTintMode = true;
24227 
24228         applyBackgroundTint();
24229     }
24230 
24231     /**
24232      * Return the blending mode used to apply the tint to the background
24233      * drawable, if specified.
24234      *
24235      * @return the blending mode used to apply the tint to the background
24236      *         drawable
24237      * @attr ref android.R.styleable#View_backgroundTintMode
24238      * @see #setBackgroundTintBlendMode(BlendMode)
24239      *
24240      */
24241     @Nullable
24242     @InspectableProperty
getBackgroundTintMode()24243     public PorterDuff.Mode getBackgroundTintMode() {
24244         PorterDuff.Mode porterDuffMode;
24245         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
24246             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
24247         } else {
24248             porterDuffMode = null;
24249         }
24250         return porterDuffMode;
24251     }
24252 
24253     /**
24254      * Return the blending mode used to apply the tint to the background
24255      * drawable, if specified.
24256      *
24257      * @return the blending mode used to apply the tint to the background
24258      *         drawable, null if no blend has previously been configured
24259      * @attr ref android.R.styleable#View_backgroundTintMode
24260      * @see #setBackgroundTintBlendMode(BlendMode)
24261      */
getBackgroundTintBlendMode()24262     public @Nullable BlendMode getBackgroundTintBlendMode() {
24263         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
24264     }
24265 
applyBackgroundTint()24266     private void applyBackgroundTint() {
24267         if (mBackground != null && mBackgroundTint != null) {
24268             final TintInfo tintInfo = mBackgroundTint;
24269             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
24270                 mBackground = mBackground.mutate();
24271 
24272                 if (tintInfo.mHasTintList) {
24273                     mBackground.setTintList(tintInfo.mTintList);
24274                 }
24275 
24276                 if (tintInfo.mHasTintMode) {
24277                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
24278                 }
24279 
24280                 // The drawable (or one of its children) may not have been
24281                 // stateful before applying the tint, so let's try again.
24282                 if (mBackground.isStateful()) {
24283                     mBackground.setState(getDrawableState());
24284                 }
24285             }
24286         }
24287     }
24288 
24289     /**
24290      * Returns the drawable used as the foreground of this View. The
24291      * foreground drawable, if non-null, is always drawn on top of the view's content.
24292      *
24293      * @return a Drawable or null if no foreground was set
24294      *
24295      * @see #onDrawForeground(Canvas)
24296      */
24297     @InspectableProperty
getForeground()24298     public Drawable getForeground() {
24299         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24300     }
24301 
24302     /**
24303      * Supply a Drawable that is to be rendered on top of all of the content in the view.
24304      *
24305      * @param foreground the Drawable to be drawn on top of the children
24306      *
24307      * @attr ref android.R.styleable#View_foreground
24308      */
setForeground(Drawable foreground)24309     public void setForeground(Drawable foreground) {
24310         if (mForegroundInfo == null) {
24311             if (foreground == null) {
24312                 // Nothing to do.
24313                 return;
24314             }
24315             mForegroundInfo = new ForegroundInfo();
24316         }
24317 
24318         if (foreground == mForegroundInfo.mDrawable) {
24319             // Nothing to do
24320             return;
24321         }
24322 
24323         if (mForegroundInfo.mDrawable != null) {
24324             if (isAttachedToWindow()) {
24325                 mForegroundInfo.mDrawable.setVisible(false, false);
24326             }
24327             mForegroundInfo.mDrawable.setCallback(null);
24328             unscheduleDrawable(mForegroundInfo.mDrawable);
24329         }
24330 
24331         mForegroundInfo.mDrawable = foreground;
24332         mForegroundInfo.mBoundsChanged = true;
24333         if (foreground != null) {
24334             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24335                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24336             }
24337             foreground.setLayoutDirection(getLayoutDirection());
24338             if (foreground.isStateful()) {
24339                 foreground.setState(getDrawableState());
24340             }
24341             applyForegroundTint();
24342             if (isAttachedToWindow()) {
24343                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24344             }
24345             // Set callback last, since the view may still be initializing.
24346             foreground.setCallback(this);
24347         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
24348                 && (mDefaultFocusHighlight == null)) {
24349             mPrivateFlags |= PFLAG_SKIP_DRAW;
24350         }
24351         requestLayout();
24352         invalidate();
24353     }
24354 
24355     /**
24356      * Magic bit used to support features of framework-internal window decor implementation details.
24357      * This used to live exclusively in FrameLayout.
24358      *
24359      * @return true if the foreground should draw inside the padding region or false
24360      *         if it should draw inset by the view's padding
24361      * @hide internal use only; only used by FrameLayout and internal screen layouts.
24362      */
isForegroundInsidePadding()24363     public boolean isForegroundInsidePadding() {
24364         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
24365     }
24366 
24367     /**
24368      * Describes how the foreground is positioned.
24369      *
24370      * @return foreground gravity.
24371      *
24372      * @see #setForegroundGravity(int)
24373      *
24374      * @attr ref android.R.styleable#View_foregroundGravity
24375      */
24376     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()24377     public int getForegroundGravity() {
24378         return mForegroundInfo != null ? mForegroundInfo.mGravity
24379                 : Gravity.START | Gravity.TOP;
24380     }
24381 
24382     /**
24383      * Describes how the foreground is positioned. Defaults to START and TOP.
24384      *
24385      * @param gravity see {@link android.view.Gravity}
24386      *
24387      * @see #getForegroundGravity()
24388      *
24389      * @attr ref android.R.styleable#View_foregroundGravity
24390      */
setForegroundGravity(int gravity)24391     public void setForegroundGravity(int gravity) {
24392         if (mForegroundInfo == null) {
24393             mForegroundInfo = new ForegroundInfo();
24394         }
24395 
24396         if (mForegroundInfo.mGravity != gravity) {
24397             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
24398                 gravity |= Gravity.START;
24399             }
24400 
24401             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
24402                 gravity |= Gravity.TOP;
24403             }
24404 
24405             mForegroundInfo.mGravity = gravity;
24406             requestLayout();
24407         }
24408     }
24409 
24410     /**
24411      * Applies a tint to the foreground drawable. Does not modify the current tint
24412      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
24413      * <p>
24414      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
24415      * mutate the drawable and apply the specified tint and tint mode using
24416      * {@link Drawable#setTintList(ColorStateList)}.
24417      *
24418      * @param tint the tint to apply, may be {@code null} to clear tint
24419      *
24420      * @attr ref android.R.styleable#View_foregroundTint
24421      * @see #getForegroundTintList()
24422      * @see Drawable#setTintList(ColorStateList)
24423      */
24424     @RemotableViewMethod
setForegroundTintList(@ullable ColorStateList tint)24425     public void setForegroundTintList(@Nullable ColorStateList tint) {
24426         if (mForegroundInfo == null) {
24427             mForegroundInfo = new ForegroundInfo();
24428         }
24429         if (mForegroundInfo.mTintInfo == null) {
24430             mForegroundInfo.mTintInfo = new TintInfo();
24431         }
24432         mForegroundInfo.mTintInfo.mTintList = tint;
24433         mForegroundInfo.mTintInfo.mHasTintList = true;
24434 
24435         applyForegroundTint();
24436     }
24437 
24438     /**
24439      * Return the tint applied to the foreground drawable, if specified.
24440      *
24441      * @return the tint applied to the foreground drawable
24442      * @attr ref android.R.styleable#View_foregroundTint
24443      * @see #setForegroundTintList(ColorStateList)
24444      */
24445     @InspectableProperty(name = "foregroundTint")
24446     @Nullable
getForegroundTintList()24447     public ColorStateList getForegroundTintList() {
24448         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24449                 ? mForegroundInfo.mTintInfo.mTintList : null;
24450     }
24451 
24452     /**
24453      * Specifies the blending mode used to apply the tint specified by
24454      * {@link #setForegroundTintList(ColorStateList)}} to the background
24455      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
24456      *
24457      * @param tintMode the blending mode used to apply the tint, may be
24458      *                 {@code null} to clear tint
24459      * @attr ref android.R.styleable#View_foregroundTintMode
24460      * @see #getForegroundTintMode()
24461      * @see Drawable#setTintMode(PorterDuff.Mode)
24462      *
24463      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)24464     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
24465         BlendMode mode = null;
24466         if (tintMode != null) {
24467             mode = BlendMode.fromValue(tintMode.nativeInt);
24468         }
24469         setForegroundTintBlendMode(mode);
24470     }
24471 
24472     /**
24473      * Specifies the blending mode used to apply the tint specified by
24474      * {@link #setForegroundTintList(ColorStateList)}} to the background
24475      * drawable. The default mode is {@link BlendMode#SRC_IN}.
24476      *
24477      * @param blendMode the blending mode used to apply the tint, may be
24478      *                 {@code null} to clear tint
24479      * @attr ref android.R.styleable#View_foregroundTintMode
24480      * @see #getForegroundTintMode()
24481      * @see Drawable#setTintBlendMode(BlendMode)
24482      */
24483     @RemotableViewMethod
setForegroundTintBlendMode(@ullable BlendMode blendMode)24484     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
24485         if (mForegroundInfo == null) {
24486             mForegroundInfo = new ForegroundInfo();
24487         }
24488         if (mForegroundInfo.mTintInfo == null) {
24489             mForegroundInfo.mTintInfo = new TintInfo();
24490         }
24491         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
24492         mForegroundInfo.mTintInfo.mHasTintMode = true;
24493 
24494         applyForegroundTint();
24495     }
24496 
24497     /**
24498      * Return the blending mode used to apply the tint to the foreground
24499      * drawable, if specified.
24500      *
24501      * @return the blending mode used to apply the tint to the foreground
24502      *         drawable
24503      * @attr ref android.R.styleable#View_foregroundTintMode
24504      * @see #setForegroundTintMode(PorterDuff.Mode)
24505      */
24506     @InspectableProperty
24507     @Nullable
getForegroundTintMode()24508     public PorterDuff.Mode getForegroundTintMode() {
24509         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24510                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
24511         if (blendMode != null) {
24512             return BlendMode.blendModeToPorterDuffMode(blendMode);
24513         } else {
24514             return null;
24515         }
24516     }
24517 
24518     /**
24519      * Return the blending mode used to apply the tint to the foreground
24520      * drawable, if specified.
24521      *
24522      * @return the blending mode used to apply the tint to the foreground
24523      *         drawable
24524      * @attr ref android.R.styleable#View_foregroundTintMode
24525      * @see #setForegroundTintBlendMode(BlendMode)
24526      *
24527      */
getForegroundTintBlendMode()24528     public @Nullable BlendMode getForegroundTintBlendMode() {
24529         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24530                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
24531     }
24532 
applyForegroundTint()24533     private void applyForegroundTint() {
24534         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
24535                 && mForegroundInfo.mTintInfo != null) {
24536             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
24537             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
24538                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
24539 
24540                 if (tintInfo.mHasTintList) {
24541                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
24542                 }
24543 
24544                 if (tintInfo.mHasTintMode) {
24545                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
24546                 }
24547 
24548                 // The drawable (or one of its children) may not have been
24549                 // stateful before applying the tint, so let's try again.
24550                 if (mForegroundInfo.mDrawable.isStateful()) {
24551                     mForegroundInfo.mDrawable.setState(getDrawableState());
24552                 }
24553             }
24554         }
24555     }
24556 
24557     /**
24558      * Get the drawable to be overlayed when a view is autofilled
24559      *
24560      * @return The drawable
24561      *
24562      * @throws IllegalStateException if the drawable could not be found.
24563      */
getAutofilledDrawable()24564     @Nullable private Drawable getAutofilledDrawable() {
24565         if (mAttachInfo == null) {
24566             return null;
24567         }
24568         // Lazily load the isAutofilled drawable.
24569         if (mAttachInfo.mAutofilledDrawable == null) {
24570             Context rootContext = getRootView().getContext();
24571             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
24572             int attributeResourceId = a.getResourceId(0, 0);
24573             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
24574             a.recycle();
24575         }
24576 
24577         return mAttachInfo.mAutofilledDrawable;
24578     }
24579 
24580     /**
24581      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
24582      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
24583      *
24584      * @param canvas The canvas to draw on
24585      */
drawAutofilledHighlight(@onNull Canvas canvas)24586     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
24587         if (isAutofilled() && !hideAutofillHighlight()) {
24588             Drawable autofilledHighlight = getAutofilledDrawable();
24589 
24590             if (autofilledHighlight != null) {
24591                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
24592                 autofilledHighlight.draw(canvas);
24593             }
24594         }
24595     }
24596 
24597     /**
24598      * Draw any foreground content for this view.
24599      *
24600      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
24601      * drawable or other view-specific decorations. The foreground is drawn on top of the
24602      * primary view content.</p>
24603      *
24604      * @param canvas canvas to draw into
24605      */
onDrawForeground(Canvas canvas)24606     public void onDrawForeground(Canvas canvas) {
24607         onDrawScrollIndicators(canvas);
24608         onDrawScrollBars(canvas);
24609 
24610         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24611         if (foreground != null) {
24612             if (mForegroundInfo.mBoundsChanged) {
24613                 mForegroundInfo.mBoundsChanged = false;
24614                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
24615                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
24616 
24617                 if (mForegroundInfo.mInsidePadding) {
24618                     selfBounds.set(0, 0, getWidth(), getHeight());
24619                 } else {
24620                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
24621                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
24622                 }
24623 
24624                 final int ld = getLayoutDirection();
24625                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
24626                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
24627                 foreground.setBounds(overlayBounds);
24628             }
24629 
24630             foreground.draw(canvas);
24631         }
24632     }
24633 
24634     /**
24635      * Sets the padding. The view may add on the space required to display
24636      * the scrollbars, depending on the style and visibility of the scrollbars.
24637      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
24638      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
24639      * from the values set in this call.
24640      *
24641      * @attr ref android.R.styleable#View_padding
24642      * @attr ref android.R.styleable#View_paddingBottom
24643      * @attr ref android.R.styleable#View_paddingLeft
24644      * @attr ref android.R.styleable#View_paddingRight
24645      * @attr ref android.R.styleable#View_paddingTop
24646      * @param left the left padding in pixels
24647      * @param top the top padding in pixels
24648      * @param right the right padding in pixels
24649      * @param bottom the bottom padding in pixels
24650      */
setPadding(int left, int top, int right, int bottom)24651     public void setPadding(int left, int top, int right, int bottom) {
24652         resetResolvedPaddingInternal();
24653 
24654         mUserPaddingStart = UNDEFINED_PADDING;
24655         mUserPaddingEnd = UNDEFINED_PADDING;
24656 
24657         mUserPaddingLeftInitial = left;
24658         mUserPaddingRightInitial = right;
24659 
24660         mLeftPaddingDefined = true;
24661         mRightPaddingDefined = true;
24662 
24663         internalSetPadding(left, top, right, bottom);
24664     }
24665 
24666     /**
24667      * @hide
24668      */
24669     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)24670     protected void internalSetPadding(int left, int top, int right, int bottom) {
24671         mUserPaddingLeft = left;
24672         mUserPaddingRight = right;
24673         mUserPaddingBottom = bottom;
24674 
24675         final int viewFlags = mViewFlags;
24676         boolean changed = false;
24677 
24678         // Common case is there are no scroll bars.
24679         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
24680             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
24681                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
24682                         ? 0 : getVerticalScrollbarWidth();
24683                 switch (mVerticalScrollbarPosition) {
24684                     case SCROLLBAR_POSITION_DEFAULT:
24685                         if (isLayoutRtl()) {
24686                             left += offset;
24687                         } else {
24688                             right += offset;
24689                         }
24690                         break;
24691                     case SCROLLBAR_POSITION_RIGHT:
24692                         right += offset;
24693                         break;
24694                     case SCROLLBAR_POSITION_LEFT:
24695                         left += offset;
24696                         break;
24697                 }
24698             }
24699             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
24700                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
24701                         ? 0 : getHorizontalScrollbarHeight();
24702             }
24703         }
24704 
24705         if (mPaddingLeft != left) {
24706             changed = true;
24707             mPaddingLeft = left;
24708         }
24709         if (mPaddingTop != top) {
24710             changed = true;
24711             mPaddingTop = top;
24712         }
24713         if (mPaddingRight != right) {
24714             changed = true;
24715             mPaddingRight = right;
24716         }
24717         if (mPaddingBottom != bottom) {
24718             changed = true;
24719             mPaddingBottom = bottom;
24720         }
24721 
24722         if (changed) {
24723             requestLayout();
24724             invalidateOutline();
24725         }
24726     }
24727 
24728     /**
24729      * Sets the relative padding. The view may add on the space required to display
24730      * the scrollbars, depending on the style and visibility of the scrollbars.
24731      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
24732      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
24733      * from the values set in this call.
24734      *
24735      * @attr ref android.R.styleable#View_padding
24736      * @attr ref android.R.styleable#View_paddingBottom
24737      * @attr ref android.R.styleable#View_paddingStart
24738      * @attr ref android.R.styleable#View_paddingEnd
24739      * @attr ref android.R.styleable#View_paddingTop
24740      * @param start the start padding in pixels
24741      * @param top the top padding in pixels
24742      * @param end the end padding in pixels
24743      * @param bottom the bottom padding in pixels
24744      */
setPaddingRelative(int start, int top, int end, int bottom)24745     public void setPaddingRelative(int start, int top, int end, int bottom) {
24746         resetResolvedPaddingInternal();
24747 
24748         mUserPaddingStart = start;
24749         mUserPaddingEnd = end;
24750         mLeftPaddingDefined = true;
24751         mRightPaddingDefined = true;
24752 
24753         switch(getLayoutDirection()) {
24754             case LAYOUT_DIRECTION_RTL:
24755                 mUserPaddingLeftInitial = end;
24756                 mUserPaddingRightInitial = start;
24757                 internalSetPadding(end, top, start, bottom);
24758                 break;
24759             case LAYOUT_DIRECTION_LTR:
24760             default:
24761                 mUserPaddingLeftInitial = start;
24762                 mUserPaddingRightInitial = end;
24763                 internalSetPadding(start, top, end, bottom);
24764         }
24765     }
24766 
24767     /**
24768      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
24769      * resource ID of the source layout.
24770      *
24771      * @return The layout resource id if this view was inflated from XML, otherwise
24772      * {@link Resources#ID_NULL}.
24773      */
24774     @LayoutRes
getSourceLayoutResId()24775     public int getSourceLayoutResId() {
24776         return mSourceLayoutId;
24777     }
24778 
24779     /**
24780      * Returns the top padding of this view.
24781      *
24782      * @return the top padding in pixels
24783      */
24784     @InspectableProperty
getPaddingTop()24785     public int getPaddingTop() {
24786         return mPaddingTop;
24787     }
24788 
24789     /**
24790      * Returns the bottom padding of this view. If there are inset and enabled
24791      * scrollbars, this value may include the space required to display the
24792      * scrollbars as well.
24793      *
24794      * @return the bottom padding in pixels
24795      */
24796     @InspectableProperty
getPaddingBottom()24797     public int getPaddingBottom() {
24798         return mPaddingBottom;
24799     }
24800 
24801     /**
24802      * Returns the left padding of this view. If there are inset and enabled
24803      * scrollbars, this value may include the space required to display the
24804      * scrollbars as well.
24805      *
24806      * @return the left padding in pixels
24807      */
24808     @InspectableProperty
getPaddingLeft()24809     public int getPaddingLeft() {
24810         if (!isPaddingResolved()) {
24811             resolvePadding();
24812         }
24813         return mPaddingLeft;
24814     }
24815 
24816     /**
24817      * Returns the start padding of this view depending on its resolved layout direction.
24818      * If there are inset and enabled scrollbars, this value may include the space
24819      * required to display the scrollbars as well.
24820      *
24821      * @return the start padding in pixels
24822      */
getPaddingStart()24823     public int getPaddingStart() {
24824         if (!isPaddingResolved()) {
24825             resolvePadding();
24826         }
24827         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24828                 mPaddingRight : mPaddingLeft;
24829     }
24830 
24831     /**
24832      * Returns the right padding of this view. If there are inset and enabled
24833      * scrollbars, this value may include the space required to display the
24834      * scrollbars as well.
24835      *
24836      * @return the right padding in pixels
24837      */
24838     @InspectableProperty
getPaddingRight()24839     public int getPaddingRight() {
24840         if (!isPaddingResolved()) {
24841             resolvePadding();
24842         }
24843         return mPaddingRight;
24844     }
24845 
24846     /**
24847      * Returns the end padding of this view depending on its resolved layout direction.
24848      * If there are inset and enabled scrollbars, this value may include the space
24849      * required to display the scrollbars as well.
24850      *
24851      * @return the end padding in pixels
24852      */
getPaddingEnd()24853     public int getPaddingEnd() {
24854         if (!isPaddingResolved()) {
24855             resolvePadding();
24856         }
24857         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24858                 mPaddingLeft : mPaddingRight;
24859     }
24860 
24861     /**
24862      * Return if the padding has been set through relative values
24863      * {@link #setPaddingRelative(int, int, int, int)} or through
24864      * @attr ref android.R.styleable#View_paddingStart or
24865      * @attr ref android.R.styleable#View_paddingEnd
24866      *
24867      * @return true if the padding is relative or false if it is not.
24868      */
isPaddingRelative()24869     public boolean isPaddingRelative() {
24870         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
24871     }
24872 
computeOpticalInsets()24873     Insets computeOpticalInsets() {
24874         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
24875     }
24876 
24877     /**
24878      * @hide
24879      */
24880     @UnsupportedAppUsage
resetPaddingToInitialValues()24881     public void resetPaddingToInitialValues() {
24882         if (isRtlCompatibilityMode()) {
24883             mPaddingLeft = mUserPaddingLeftInitial;
24884             mPaddingRight = mUserPaddingRightInitial;
24885             return;
24886         }
24887         if (isLayoutRtl()) {
24888             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
24889             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
24890         } else {
24891             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
24892             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
24893         }
24894     }
24895 
24896     /**
24897      * @hide
24898      */
getOpticalInsets()24899     public Insets getOpticalInsets() {
24900         if (mLayoutInsets == null) {
24901             mLayoutInsets = computeOpticalInsets();
24902         }
24903         return mLayoutInsets;
24904     }
24905 
24906     /**
24907      * Set this view's optical insets.
24908      *
24909      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
24910      * property. Views that compute their own optical insets should call it as part of measurement.
24911      * This method does not request layout. If you are setting optical insets outside of
24912      * measure/layout itself you will want to call requestLayout() yourself.
24913      * </p>
24914      * @hide
24915      */
setOpticalInsets(Insets insets)24916     public void setOpticalInsets(Insets insets) {
24917         mLayoutInsets = insets;
24918     }
24919 
24920     /**
24921      * Changes the selection state of this view. A view can be selected or not.
24922      * Note that selection is not the same as focus. Views are typically
24923      * selected in the context of an AdapterView like ListView or GridView;
24924      * the selected view is the view that is highlighted.
24925      *
24926      * @param selected true if the view must be selected, false otherwise
24927      */
setSelected(boolean selected)24928     public void setSelected(boolean selected) {
24929         //noinspection DoubleNegation
24930         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
24931             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
24932             if (!selected) resetPressedState();
24933             invalidate(true);
24934             refreshDrawableState();
24935             dispatchSetSelected(selected);
24936             if (selected) {
24937                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
24938             } else {
24939                 notifyViewAccessibilityStateChangedIfNeeded(
24940                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
24941             }
24942         }
24943     }
24944 
24945     /**
24946      * Dispatch setSelected to all of this View's children.
24947      *
24948      * @see #setSelected(boolean)
24949      *
24950      * @param selected The new selected state
24951      */
dispatchSetSelected(boolean selected)24952     protected void dispatchSetSelected(boolean selected) {
24953     }
24954 
24955     /**
24956      * Indicates the selection state of this view.
24957      *
24958      * @return true if the view is selected, false otherwise
24959      */
24960     @ViewDebug.ExportedProperty
24961     @InspectableProperty(hasAttributeId = false)
isSelected()24962     public boolean isSelected() {
24963         return (mPrivateFlags & PFLAG_SELECTED) != 0;
24964     }
24965 
24966     /**
24967      * Changes the activated state of this view. A view can be activated or not.
24968      * Note that activation is not the same as selection.  Selection is
24969      * a transient property, representing the view (hierarchy) the user is
24970      * currently interacting with.  Activation is a longer-term state that the
24971      * user can move views in and out of.  For example, in a list view with
24972      * single or multiple selection enabled, the views in the current selection
24973      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
24974      * here.)  The activated state is propagated down to children of the view it
24975      * is set on.
24976      *
24977      * @param activated true if the view must be activated, false otherwise
24978      */
setActivated(boolean activated)24979     public void setActivated(boolean activated) {
24980         //noinspection DoubleNegation
24981         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
24982             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
24983             invalidate(true);
24984             refreshDrawableState();
24985             dispatchSetActivated(activated);
24986         }
24987     }
24988 
24989     /**
24990      * Dispatch setActivated to all of this View's children.
24991      *
24992      * @see #setActivated(boolean)
24993      *
24994      * @param activated The new activated state
24995      */
dispatchSetActivated(boolean activated)24996     protected void dispatchSetActivated(boolean activated) {
24997     }
24998 
24999     /**
25000      * Indicates the activation state of this view.
25001      *
25002      * @return true if the view is activated, false otherwise
25003      */
25004     @ViewDebug.ExportedProperty
25005     @InspectableProperty(hasAttributeId = false)
isActivated()25006     public boolean isActivated() {
25007         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
25008     }
25009 
25010     /**
25011      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
25012      * observer can be used to get notifications when global events, like
25013      * layout, happen.
25014      *
25015      * The returned ViewTreeObserver observer is not guaranteed to remain
25016      * valid for the lifetime of this View. If the caller of this method keeps
25017      * a long-lived reference to ViewTreeObserver, it should always check for
25018      * the return value of {@link ViewTreeObserver#isAlive()}.
25019      *
25020      * @return The ViewTreeObserver for this view's hierarchy.
25021      */
getViewTreeObserver()25022     public ViewTreeObserver getViewTreeObserver() {
25023         if (mAttachInfo != null) {
25024             return mAttachInfo.mTreeObserver;
25025         }
25026         if (mFloatingTreeObserver == null) {
25027             mFloatingTreeObserver = new ViewTreeObserver(mContext);
25028         }
25029         return mFloatingTreeObserver;
25030     }
25031 
25032     /**
25033      * <p>Finds the topmost view in the current view hierarchy.</p>
25034      *
25035      * @return the topmost view containing this view
25036      */
getRootView()25037     public View getRootView() {
25038         if (mAttachInfo != null) {
25039             final View v = mAttachInfo.mRootView;
25040             if (v != null) {
25041                 return v;
25042             }
25043         }
25044 
25045         View parent = this;
25046 
25047         while (parent.mParent instanceof View) {
25048             parent = (View) parent.mParent;
25049         }
25050 
25051         return parent;
25052     }
25053 
25054     /**
25055      * Transforms a motion event from view-local coordinates to on-screen
25056      * coordinates.
25057      *
25058      * @param ev the view-local motion event
25059      * @return false if the transformation could not be applied
25060      * @hide
25061      */
25062     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toGlobalMotionEvent(MotionEvent ev)25063     public boolean toGlobalMotionEvent(MotionEvent ev) {
25064         final AttachInfo info = mAttachInfo;
25065         if (info == null) {
25066             return false;
25067         }
25068 
25069         final Matrix m = info.mTmpMatrix;
25070         m.set(Matrix.IDENTITY_MATRIX);
25071         transformMatrixToGlobal(m);
25072         ev.transform(m);
25073         return true;
25074     }
25075 
25076     /**
25077      * Transforms a motion event from on-screen coordinates to view-local
25078      * coordinates.
25079      *
25080      * @param ev the on-screen motion event
25081      * @return false if the transformation could not be applied
25082      * @hide
25083      */
25084     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toLocalMotionEvent(MotionEvent ev)25085     public boolean toLocalMotionEvent(MotionEvent ev) {
25086         final AttachInfo info = mAttachInfo;
25087         if (info == null) {
25088             return false;
25089         }
25090 
25091         final Matrix m = info.mTmpMatrix;
25092         m.set(Matrix.IDENTITY_MATRIX);
25093         transformMatrixToLocal(m);
25094         ev.transform(m);
25095         return true;
25096     }
25097 
25098     /**
25099      * Modifies the input matrix such that it maps view-local coordinates to
25100      * on-screen coordinates.
25101      *
25102      * @param matrix input matrix to modify
25103      */
transformMatrixToGlobal(@onNull Matrix matrix)25104     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
25105         final ViewParent parent = mParent;
25106         if (parent instanceof View) {
25107             final View vp = (View) parent;
25108             vp.transformMatrixToGlobal(matrix);
25109             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
25110         } else if (parent instanceof ViewRootImpl) {
25111             final ViewRootImpl vr = (ViewRootImpl) parent;
25112             vr.transformMatrixToGlobal(matrix);
25113             matrix.preTranslate(0, -vr.mCurScrollY);
25114         }
25115 
25116         matrix.preTranslate(mLeft, mTop);
25117 
25118         if (!hasIdentityMatrix()) {
25119             matrix.preConcat(getMatrix());
25120         }
25121     }
25122 
25123     /**
25124      * Modifies the input matrix such that it maps on-screen coordinates to
25125      * view-local coordinates.
25126      *
25127      * @param matrix input matrix to modify
25128      */
transformMatrixToLocal(@onNull Matrix matrix)25129     public void transformMatrixToLocal(@NonNull Matrix matrix) {
25130         final ViewParent parent = mParent;
25131         if (parent instanceof View) {
25132             final View vp = (View) parent;
25133             vp.transformMatrixToLocal(matrix);
25134             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
25135         } else if (parent instanceof ViewRootImpl) {
25136             final ViewRootImpl vr = (ViewRootImpl) parent;
25137             vr.transformMatrixToLocal(matrix);
25138             matrix.postTranslate(0, vr.mCurScrollY);
25139         }
25140 
25141         matrix.postTranslate(-mLeft, -mTop);
25142 
25143         if (!hasIdentityMatrix()) {
25144             matrix.postConcat(getInverseMatrix());
25145         }
25146     }
25147 
25148     /**
25149      * @hide
25150      */
25151     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
25152             @ViewDebug.IntToString(from = 0, to = "x"),
25153             @ViewDebug.IntToString(from = 1, to = "y")
25154     })
25155     @UnsupportedAppUsage
getLocationOnScreen()25156     public int[] getLocationOnScreen() {
25157         int[] location = new int[2];
25158         getLocationOnScreen(location);
25159         return location;
25160     }
25161 
25162     /**
25163      * <p>Computes the coordinates of this view on the screen. The argument
25164      * must be an array of two integers. After the method returns, the array
25165      * contains the x and y location in that order.</p>
25166      *
25167      * @param outLocation an array of two integers in which to hold the coordinates
25168      */
getLocationOnScreen(@ize2) int[] outLocation)25169     public void getLocationOnScreen(@Size(2) int[] outLocation) {
25170         getLocationInWindow(outLocation);
25171 
25172         final AttachInfo info = mAttachInfo;
25173         if (info != null) {
25174             outLocation[0] += info.mWindowLeft;
25175             outLocation[1] += info.mWindowTop;
25176         }
25177     }
25178 
25179     /**
25180      * <p>Computes the coordinates of this view in its window. The argument
25181      * must be an array of two integers. After the method returns, the array
25182      * contains the x and y location in that order.</p>
25183      *
25184      * @param outLocation an array of two integers in which to hold the coordinates
25185      */
getLocationInWindow(@ize2) int[] outLocation)25186     public void getLocationInWindow(@Size(2) int[] outLocation) {
25187         if (outLocation == null || outLocation.length < 2) {
25188             throw new IllegalArgumentException("outLocation must be an array of two integers");
25189         }
25190 
25191         outLocation[0] = 0;
25192         outLocation[1] = 0;
25193 
25194         transformFromViewToWindowSpace(outLocation);
25195     }
25196 
25197     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)25198     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
25199         if (inOutLocation == null || inOutLocation.length < 2) {
25200             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
25201         }
25202 
25203         if (mAttachInfo == null) {
25204             // When the view is not attached to a window, this method does not make sense
25205             inOutLocation[0] = inOutLocation[1] = 0;
25206             return;
25207         }
25208 
25209         float position[] = mAttachInfo.mTmpTransformLocation;
25210         position[0] = inOutLocation[0];
25211         position[1] = inOutLocation[1];
25212 
25213         if (!hasIdentityMatrix()) {
25214             getMatrix().mapPoints(position);
25215         }
25216 
25217         position[0] += mLeft;
25218         position[1] += mTop;
25219 
25220         ViewParent viewParent = mParent;
25221         while (viewParent instanceof View) {
25222             final View view = (View) viewParent;
25223 
25224             position[0] -= view.mScrollX;
25225             position[1] -= view.mScrollY;
25226 
25227             if (!view.hasIdentityMatrix()) {
25228                 view.getMatrix().mapPoints(position);
25229             }
25230 
25231             position[0] += view.mLeft;
25232             position[1] += view.mTop;
25233 
25234             viewParent = view.mParent;
25235          }
25236 
25237         if (viewParent instanceof ViewRootImpl) {
25238             // *cough*
25239             final ViewRootImpl vr = (ViewRootImpl) viewParent;
25240             position[1] -= vr.mCurScrollY;
25241         }
25242 
25243         inOutLocation[0] = Math.round(position[0]);
25244         inOutLocation[1] = Math.round(position[1]);
25245     }
25246 
25247     /**
25248      * @param id the id of the view to be found
25249      * @return the view of the specified id, null if cannot be found
25250      * @hide
25251      */
findViewTraversal(@dRes int id)25252     protected <T extends View> T findViewTraversal(@IdRes int id) {
25253         if (id == mID) {
25254             return (T) this;
25255         }
25256         return null;
25257     }
25258 
25259     /**
25260      * @param tag the tag of the view to be found
25261      * @return the view of specified tag, null if cannot be found
25262      * @hide
25263      */
findViewWithTagTraversal(Object tag)25264     protected <T extends View> T findViewWithTagTraversal(Object tag) {
25265         if (tag != null && tag.equals(mTag)) {
25266             return (T) this;
25267         }
25268         return null;
25269     }
25270 
25271     /**
25272      * @param predicate The predicate to evaluate.
25273      * @param childToSkip If not null, ignores this child during the recursive traversal.
25274      * @return The first view that matches the predicate or null.
25275      * @hide
25276      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)25277     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
25278             View childToSkip) {
25279         if (predicate.test(this)) {
25280             return (T) this;
25281         }
25282         return null;
25283     }
25284 
25285     /**
25286      * Finds the first descendant view with the given ID, the view itself if
25287      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
25288      * (< 0) or there is no matching view in the hierarchy.
25289      * <p>
25290      * <strong>Note:</strong> In most cases -- depending on compiler support --
25291      * the resulting view is automatically cast to the target class type. If
25292      * the target class type is unconstrained, an explicit cast may be
25293      * necessary.
25294      *
25295      * @param id the ID to search for
25296      * @return a view with given ID if found, or {@code null} otherwise
25297      * @see View#requireViewById(int)
25298      */
25299     @Nullable
findViewById(@dRes int id)25300     public final <T extends View> T findViewById(@IdRes int id) {
25301         if (id == NO_ID) {
25302             return null;
25303         }
25304         return findViewTraversal(id);
25305     }
25306 
25307     /**
25308      * Finds the first descendant view with the given ID, the view itself if the ID matches
25309      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
25310      * matching view in the hierarchy.
25311      * <p>
25312      * <strong>Note:</strong> In most cases -- depending on compiler support --
25313      * the resulting view is automatically cast to the target class type. If
25314      * the target class type is unconstrained, an explicit cast may be
25315      * necessary.
25316      *
25317      * @param id the ID to search for
25318      * @return a view with given ID
25319      * @see View#findViewById(int)
25320      */
25321     @NonNull
requireViewById(@dRes int id)25322     public final <T extends View> T requireViewById(@IdRes int id) {
25323         T view = findViewById(id);
25324         if (view == null) {
25325             throw new IllegalArgumentException("ID does not reference a View inside this View");
25326         }
25327         return view;
25328     }
25329 
25330     /**
25331      * Performs the traversal to find a view by its unique and stable accessibility id.
25332      *
25333      * <strong>Note:</strong>This method does not stop at the root namespace
25334      * boundary since the user can touch the screen at an arbitrary location
25335      * potentially crossing the root namespace boundary which will send an
25336      * accessibility event to accessibility services and they should be able
25337      * to obtain the event source. Also accessibility ids are guaranteed to be
25338      * unique in the window.
25339      *
25340      * @param accessibilityId The accessibility id.
25341      * @return The found view.
25342      * @hide
25343      */
findViewByAccessibilityIdTraversal(int accessibilityId)25344     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
25345         if (getAccessibilityViewId() == accessibilityId) {
25346             return (T) this;
25347         }
25348         return null;
25349     }
25350 
25351     /**
25352      * Performs the traversal to find a view by its autofill id.
25353      *
25354      * <strong>Note:</strong>This method does not stop at the root namespace
25355      * boundary.
25356      *
25357      * @param autofillId The autofill id.
25358      * @return The found view.
25359      * @hide
25360      */
findViewByAutofillIdTraversal(int autofillId)25361     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
25362         if (getAutofillViewId() == autofillId) {
25363             return (T) this;
25364         }
25365         return null;
25366     }
25367 
25368     /**
25369      * Look for a child view with the given tag.  If this view has the given
25370      * tag, return this view.
25371      *
25372      * @param tag The tag to search for, using "tag.equals(getTag())".
25373      * @return The View that has the given tag in the hierarchy or null
25374      */
findViewWithTag(Object tag)25375     public final <T extends View> T findViewWithTag(Object tag) {
25376         if (tag == null) {
25377             return null;
25378         }
25379         return findViewWithTagTraversal(tag);
25380     }
25381 
25382     /**
25383      * Look for a child view that matches the specified predicate.
25384      * If this view matches the predicate, return this view.
25385      *
25386      * @param predicate The predicate to evaluate.
25387      * @return The first view that matches the predicate or null.
25388      * @hide
25389      */
findViewByPredicate(Predicate<View> predicate)25390     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
25391         return findViewByPredicateTraversal(predicate, null);
25392     }
25393 
25394     /**
25395      * Look for a child view that matches the specified predicate,
25396      * starting with the specified view and its descendents and then
25397      * recusively searching the ancestors and siblings of that view
25398      * until this view is reached.
25399      *
25400      * This method is useful in cases where the predicate does not match
25401      * a single unique view (perhaps multiple views use the same id)
25402      * and we are trying to find the view that is "closest" in scope to the
25403      * starting view.
25404      *
25405      * @param start The view to start from.
25406      * @param predicate The predicate to evaluate.
25407      * @return The first view that matches the predicate or null.
25408      * @hide
25409      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)25410     public final <T extends View> T findViewByPredicateInsideOut(
25411             View start, Predicate<View> predicate) {
25412         View childToSkip = null;
25413         for (;;) {
25414             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
25415             if (view != null || start == this) {
25416                 return view;
25417             }
25418 
25419             ViewParent parent = start.getParent();
25420             if (parent == null || !(parent instanceof View)) {
25421                 return null;
25422             }
25423 
25424             childToSkip = start;
25425             start = (View) parent;
25426         }
25427     }
25428 
25429     /**
25430      * Sets the identifier for this view. The identifier does not have to be
25431      * unique in this view's hierarchy. The identifier should be a positive
25432      * number.
25433      *
25434      * @see #NO_ID
25435      * @see #getId()
25436      * @see #findViewById(int)
25437      *
25438      * @param id a number used to identify the view
25439      *
25440      * @attr ref android.R.styleable#View_id
25441      */
setId(@dRes int id)25442     public void setId(@IdRes int id) {
25443         mID = id;
25444         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
25445             mID = generateViewId();
25446         }
25447     }
25448 
25449     /**
25450      * {@hide}
25451      *
25452      * @param isRoot true if the view belongs to the root namespace, false
25453      *        otherwise
25454      */
25455     @UnsupportedAppUsage
25456     @TestApi
setIsRootNamespace(boolean isRoot)25457     public void setIsRootNamespace(boolean isRoot) {
25458         if (isRoot) {
25459             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
25460         } else {
25461             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
25462         }
25463     }
25464 
25465     /**
25466      * {@hide}
25467      *
25468      * @return true if the view belongs to the root namespace, false otherwise
25469      */
25470     @UnsupportedAppUsage
isRootNamespace()25471     public boolean isRootNamespace() {
25472         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
25473     }
25474 
25475     /**
25476      * Returns this view's identifier.
25477      *
25478      * @return a positive integer used to identify the view or {@link #NO_ID}
25479      *         if the view has no ID
25480      *
25481      * @see #setId(int)
25482      * @see #findViewById(int)
25483      * @attr ref android.R.styleable#View_id
25484      */
25485     @IdRes
25486     @ViewDebug.CapturedViewProperty
25487     @InspectableProperty
getId()25488     public int getId() {
25489         return mID;
25490     }
25491 
25492     /**
25493      * Get the identifier used for this view by the drawing system.
25494      *
25495      * @see RenderNode#getUniqueId()
25496      * @return A long that uniquely identifies this view's drawing component
25497      */
getUniqueDrawingId()25498     public long getUniqueDrawingId() {
25499         return mRenderNode.getUniqueId();
25500     }
25501 
25502     /**
25503      * Returns this view's tag.
25504      *
25505      * @return the Object stored in this view as a tag, or {@code null} if not
25506      *         set
25507      *
25508      * @see #setTag(Object)
25509      * @see #getTag(int)
25510      */
25511     @ViewDebug.ExportedProperty
25512     @InspectableProperty
getTag()25513     public Object getTag() {
25514         return mTag;
25515     }
25516 
25517     /**
25518      * Sets the tag associated with this view. A tag can be used to mark
25519      * a view in its hierarchy and does not have to be unique within the
25520      * hierarchy. Tags can also be used to store data within a view without
25521      * resorting to another data structure.
25522      *
25523      * @param tag an Object to tag the view with
25524      *
25525      * @see #getTag()
25526      * @see #setTag(int, Object)
25527      */
setTag(final Object tag)25528     public void setTag(final Object tag) {
25529         mTag = tag;
25530     }
25531 
25532     /**
25533      * Returns the tag associated with this view and the specified key.
25534      *
25535      * @param key The key identifying the tag
25536      *
25537      * @return the Object stored in this view as a tag, or {@code null} if not
25538      *         set
25539      *
25540      * @see #setTag(int, Object)
25541      * @see #getTag()
25542      */
getTag(int key)25543     public Object getTag(int key) {
25544         if (mKeyedTags != null) return mKeyedTags.get(key);
25545         return null;
25546     }
25547 
25548     /**
25549      * Sets a tag associated with this view and a key. A tag can be used
25550      * to mark a view in its hierarchy and does not have to be unique within
25551      * the hierarchy. Tags can also be used to store data within a view
25552      * without resorting to another data structure.
25553      *
25554      * The specified key should be an id declared in the resources of the
25555      * application to ensure it is unique (see the <a
25556      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
25557      * Keys identified as belonging to
25558      * the Android framework or not associated with any package will cause
25559      * an {@link IllegalArgumentException} to be thrown.
25560      *
25561      * @param key The key identifying the tag
25562      * @param tag An Object to tag the view with
25563      *
25564      * @throws IllegalArgumentException If they specified key is not valid
25565      *
25566      * @see #setTag(Object)
25567      * @see #getTag(int)
25568      */
setTag(int key, final Object tag)25569     public void setTag(int key, final Object tag) {
25570         // If the package id is 0x00 or 0x01, it's either an undefined package
25571         // or a framework id
25572         if ((key >>> 24) < 2) {
25573             throw new IllegalArgumentException("The key must be an application-specific "
25574                     + "resource id.");
25575         }
25576 
25577         setKeyedTag(key, tag);
25578     }
25579 
25580     /**
25581      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
25582      * framework id.
25583      *
25584      * @hide
25585      */
25586     @UnsupportedAppUsage
setTagInternal(int key, Object tag)25587     public void setTagInternal(int key, Object tag) {
25588         if ((key >>> 24) != 0x1) {
25589             throw new IllegalArgumentException("The key must be a framework-specific "
25590                     + "resource id.");
25591         }
25592 
25593         setKeyedTag(key, tag);
25594     }
25595 
setKeyedTag(int key, Object tag)25596     private void setKeyedTag(int key, Object tag) {
25597         if (mKeyedTags == null) {
25598             mKeyedTags = new SparseArray<Object>(2);
25599         }
25600 
25601         mKeyedTags.put(key, tag);
25602     }
25603 
25604     /**
25605      * Prints information about this view in the log output, with the tag
25606      * {@link #VIEW_LOG_TAG}.
25607      *
25608      * @hide
25609      */
25610     @UnsupportedAppUsage
debug()25611     public void debug() {
25612         debug(0);
25613     }
25614 
25615     /**
25616      * Prints information about this view in the log output, with the tag
25617      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
25618      * indentation defined by the <code>depth</code>.
25619      *
25620      * @param depth the indentation level
25621      *
25622      * @hide
25623      */
25624     @UnsupportedAppUsage
debug(int depth)25625     protected void debug(int depth) {
25626         String output = debugIndent(depth - 1);
25627 
25628         output += "+ " + this;
25629         int id = getId();
25630         if (id != -1) {
25631             output += " (id=" + id + ")";
25632         }
25633         Object tag = getTag();
25634         if (tag != null) {
25635             output += " (tag=" + tag + ")";
25636         }
25637         Log.d(VIEW_LOG_TAG, output);
25638 
25639         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
25640             output = debugIndent(depth) + " FOCUSED";
25641             Log.d(VIEW_LOG_TAG, output);
25642         }
25643 
25644         output = debugIndent(depth);
25645         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
25646                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
25647                 + "} ";
25648         Log.d(VIEW_LOG_TAG, output);
25649 
25650         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
25651                 || mPaddingBottom != 0) {
25652             output = debugIndent(depth);
25653             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
25654                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
25655             Log.d(VIEW_LOG_TAG, output);
25656         }
25657 
25658         output = debugIndent(depth);
25659         output += "mMeasureWidth=" + mMeasuredWidth +
25660                 " mMeasureHeight=" + mMeasuredHeight;
25661         Log.d(VIEW_LOG_TAG, output);
25662 
25663         output = debugIndent(depth);
25664         if (mLayoutParams == null) {
25665             output += "BAD! no layout params";
25666         } else {
25667             output = mLayoutParams.debug(output);
25668         }
25669         Log.d(VIEW_LOG_TAG, output);
25670 
25671         output = debugIndent(depth);
25672         output += "flags={";
25673         output += View.printFlags(mViewFlags);
25674         output += "}";
25675         Log.d(VIEW_LOG_TAG, output);
25676 
25677         output = debugIndent(depth);
25678         output += "privateFlags={";
25679         output += View.printPrivateFlags(mPrivateFlags);
25680         output += "}";
25681         Log.d(VIEW_LOG_TAG, output);
25682     }
25683 
25684     /**
25685      * Creates a string of whitespaces used for indentation.
25686      *
25687      * @param depth the indentation level
25688      * @return a String containing (depth * 2 + 3) * 2 white spaces
25689      *
25690      * @hide
25691      */
debugIndent(int depth)25692     protected static String debugIndent(int depth) {
25693         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
25694         for (int i = 0; i < (depth * 2) + 3; i++) {
25695             spaces.append(' ').append(' ');
25696         }
25697         return spaces.toString();
25698     }
25699 
25700     /**
25701      * <p>Return the offset of the widget's text baseline from the widget's top
25702      * boundary. If this widget does not support baseline alignment, this
25703      * method returns -1. </p>
25704      *
25705      * @return the offset of the baseline within the widget's bounds or -1
25706      *         if baseline alignment is not supported
25707      */
25708     @ViewDebug.ExportedProperty(category = "layout")
25709     @InspectableProperty
getBaseline()25710     public int getBaseline() {
25711         return -1;
25712     }
25713 
25714     /**
25715      * Returns whether the view hierarchy is currently undergoing a layout pass. This
25716      * information is useful to avoid situations such as calling {@link #requestLayout()} during
25717      * a layout pass.
25718      *
25719      * @return whether the view hierarchy is currently undergoing a layout pass
25720      */
isInLayout()25721     public boolean isInLayout() {
25722         ViewRootImpl viewRoot = getViewRootImpl();
25723         return (viewRoot != null && viewRoot.isInLayout());
25724     }
25725 
25726     /**
25727      * Call this when something has changed which has invalidated the
25728      * layout of this view. This will schedule a layout pass of the view
25729      * tree. This should not be called while the view hierarchy is currently in a layout
25730      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
25731      * end of the current layout pass (and then layout will run again) or after the current
25732      * frame is drawn and the next layout occurs.
25733      *
25734      * <p>Subclasses which override this method should call the superclass method to
25735      * handle possible request-during-layout errors correctly.</p>
25736      */
25737     @CallSuper
requestLayout()25738     public void requestLayout() {
25739         if (mMeasureCache != null) mMeasureCache.clear();
25740 
25741         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
25742             // Only trigger request-during-layout logic if this is the view requesting it,
25743             // not the views in its parent hierarchy
25744             ViewRootImpl viewRoot = getViewRootImpl();
25745             if (viewRoot != null && viewRoot.isInLayout()) {
25746                 if (!viewRoot.requestLayoutDuringLayout(this)) {
25747                     return;
25748                 }
25749             }
25750             mAttachInfo.mViewRequestingLayout = this;
25751         }
25752 
25753         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25754         mPrivateFlags |= PFLAG_INVALIDATED;
25755 
25756         if (mParent != null && !mParent.isLayoutRequested()) {
25757             mParent.requestLayout();
25758         }
25759         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
25760             mAttachInfo.mViewRequestingLayout = null;
25761         }
25762     }
25763 
25764     /**
25765      * Forces this view to be laid out during the next layout pass.
25766      * This method does not call requestLayout() or forceLayout()
25767      * on the parent.
25768      */
forceLayout()25769     public void forceLayout() {
25770         if (mMeasureCache != null) mMeasureCache.clear();
25771 
25772         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25773         mPrivateFlags |= PFLAG_INVALIDATED;
25774     }
25775 
25776     /**
25777      * <p>
25778      * This is called to find out how big a view should be. The parent
25779      * supplies constraint information in the width and height parameters.
25780      * </p>
25781      *
25782      * <p>
25783      * The actual measurement work of a view is performed in
25784      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
25785      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
25786      * </p>
25787      *
25788      *
25789      * @param widthMeasureSpec Horizontal space requirements as imposed by the
25790      *        parent
25791      * @param heightMeasureSpec Vertical space requirements as imposed by the
25792      *        parent
25793      *
25794      * @see #onMeasure(int, int)
25795      */
measure(int widthMeasureSpec, int heightMeasureSpec)25796     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
25797         boolean optical = isLayoutModeOptical(this);
25798         if (optical != isLayoutModeOptical(mParent)) {
25799             Insets insets = getOpticalInsets();
25800             int oWidth  = insets.left + insets.right;
25801             int oHeight = insets.top  + insets.bottom;
25802             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
25803             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
25804         }
25805 
25806         // Suppress sign extension for the low bytes
25807         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
25808         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
25809 
25810         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
25811 
25812         // Optimize layout by avoiding an extra EXACTLY pass when the view is
25813         // already measured as the correct size. In API 23 and below, this
25814         // extra pass is required to make LinearLayout re-distribute weight.
25815         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
25816                 || heightMeasureSpec != mOldHeightMeasureSpec;
25817         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
25818                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
25819         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
25820                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
25821         final boolean needsLayout = specChanged
25822                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
25823 
25824         if (forceLayout || needsLayout) {
25825             // first clears the measured dimension flag
25826             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
25827 
25828             resolveRtlPropertiesIfNeeded();
25829 
25830             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
25831             if (cacheIndex < 0 || sIgnoreMeasureCache) {
25832                 // measure ourselves, this should set the measured dimension flag back
25833                 onMeasure(widthMeasureSpec, heightMeasureSpec);
25834                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25835             } else {
25836                 long value = mMeasureCache.valueAt(cacheIndex);
25837                 // Casting a long to int drops the high 32 bits, no mask needed
25838                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
25839                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25840             }
25841 
25842             // flag not set, setMeasuredDimension() was not invoked, we raise
25843             // an exception to warn the developer
25844             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
25845                 throw new IllegalStateException("View with id " + getId() + ": "
25846                         + getClass().getName() + "#onMeasure() did not set the"
25847                         + " measured dimension by calling"
25848                         + " setMeasuredDimension()");
25849             }
25850 
25851             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
25852         }
25853 
25854         mOldWidthMeasureSpec = widthMeasureSpec;
25855         mOldHeightMeasureSpec = heightMeasureSpec;
25856 
25857         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
25858                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
25859     }
25860 
25861     /**
25862      * <p>
25863      * Measure the view and its content to determine the measured width and the
25864      * measured height. This method is invoked by {@link #measure(int, int)} and
25865      * should be overridden by subclasses to provide accurate and efficient
25866      * measurement of their contents.
25867      * </p>
25868      *
25869      * <p>
25870      * <strong>CONTRACT:</strong> When overriding this method, you
25871      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
25872      * measured width and height of this view. Failure to do so will trigger an
25873      * <code>IllegalStateException</code>, thrown by
25874      * {@link #measure(int, int)}. Calling the superclass'
25875      * {@link #onMeasure(int, int)} is a valid use.
25876      * </p>
25877      *
25878      * <p>
25879      * The base class implementation of measure defaults to the background size,
25880      * unless a larger size is allowed by the MeasureSpec. Subclasses should
25881      * override {@link #onMeasure(int, int)} to provide better measurements of
25882      * their content.
25883      * </p>
25884      *
25885      * <p>
25886      * If this method is overridden, it is the subclass's responsibility to make
25887      * sure the measured height and width are at least the view's minimum height
25888      * and width ({@link #getSuggestedMinimumHeight()} and
25889      * {@link #getSuggestedMinimumWidth()}).
25890      * </p>
25891      *
25892      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
25893      *                         The requirements are encoded with
25894      *                         {@link android.view.View.MeasureSpec}.
25895      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
25896      *                         The requirements are encoded with
25897      *                         {@link android.view.View.MeasureSpec}.
25898      *
25899      * @see #getMeasuredWidth()
25900      * @see #getMeasuredHeight()
25901      * @see #setMeasuredDimension(int, int)
25902      * @see #getSuggestedMinimumHeight()
25903      * @see #getSuggestedMinimumWidth()
25904      * @see android.view.View.MeasureSpec#getMode(int)
25905      * @see android.view.View.MeasureSpec#getSize(int)
25906      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)25907     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
25908         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
25909                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
25910     }
25911 
25912     /**
25913      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
25914      * measured width and measured height. Failing to do so will trigger an
25915      * exception at measurement time.</p>
25916      *
25917      * @param measuredWidth The measured width of this view.  May be a complex
25918      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25919      * {@link #MEASURED_STATE_TOO_SMALL}.
25920      * @param measuredHeight The measured height of this view.  May be a complex
25921      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25922      * {@link #MEASURED_STATE_TOO_SMALL}.
25923      */
setMeasuredDimension(int measuredWidth, int measuredHeight)25924     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
25925         boolean optical = isLayoutModeOptical(this);
25926         if (optical != isLayoutModeOptical(mParent)) {
25927             Insets insets = getOpticalInsets();
25928             int opticalWidth  = insets.left + insets.right;
25929             int opticalHeight = insets.top  + insets.bottom;
25930 
25931             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
25932             measuredHeight += optical ? opticalHeight : -opticalHeight;
25933         }
25934         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
25935     }
25936 
25937     /**
25938      * Sets the measured dimension without extra processing for things like optical bounds.
25939      * Useful for reapplying consistent values that have already been cooked with adjustments
25940      * for optical bounds, etc. such as those from the measurement cache.
25941      *
25942      * @param measuredWidth The measured width of this view.  May be a complex
25943      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25944      * {@link #MEASURED_STATE_TOO_SMALL}.
25945      * @param measuredHeight The measured height of this view.  May be a complex
25946      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25947      * {@link #MEASURED_STATE_TOO_SMALL}.
25948      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)25949     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
25950         mMeasuredWidth = measuredWidth;
25951         mMeasuredHeight = measuredHeight;
25952 
25953         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
25954     }
25955 
25956     /**
25957      * Merge two states as returned by {@link #getMeasuredState()}.
25958      * @param curState The current state as returned from a view or the result
25959      * of combining multiple views.
25960      * @param newState The new view state to combine.
25961      * @return Returns a new integer reflecting the combination of the two
25962      * states.
25963      */
combineMeasuredStates(int curState, int newState)25964     public static int combineMeasuredStates(int curState, int newState) {
25965         return curState | newState;
25966     }
25967 
25968     /**
25969      * Version of {@link #resolveSizeAndState(int, int, int)}
25970      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
25971      */
resolveSize(int size, int measureSpec)25972     public static int resolveSize(int size, int measureSpec) {
25973         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
25974     }
25975 
25976     /**
25977      * Utility to reconcile a desired size and state, with constraints imposed
25978      * by a MeasureSpec. Will take the desired size, unless a different size
25979      * is imposed by the constraints. The returned value is a compound integer,
25980      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
25981      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
25982      * resulting size is smaller than the size the view wants to be.
25983      *
25984      * @param size How big the view wants to be.
25985      * @param measureSpec Constraints imposed by the parent.
25986      * @param childMeasuredState Size information bit mask for the view's
25987      *                           children.
25988      * @return Size information bit mask as defined by
25989      *         {@link #MEASURED_SIZE_MASK} and
25990      *         {@link #MEASURED_STATE_TOO_SMALL}.
25991      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)25992     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
25993         final int specMode = MeasureSpec.getMode(measureSpec);
25994         final int specSize = MeasureSpec.getSize(measureSpec);
25995         final int result;
25996         switch (specMode) {
25997             case MeasureSpec.AT_MOST:
25998                 if (specSize < size) {
25999                     result = specSize | MEASURED_STATE_TOO_SMALL;
26000                 } else {
26001                     result = size;
26002                 }
26003                 break;
26004             case MeasureSpec.EXACTLY:
26005                 result = specSize;
26006                 break;
26007             case MeasureSpec.UNSPECIFIED:
26008             default:
26009                 result = size;
26010         }
26011         return result | (childMeasuredState & MEASURED_STATE_MASK);
26012     }
26013 
26014     /**
26015      * Utility to return a default size. Uses the supplied size if the
26016      * MeasureSpec imposed no constraints. Will get larger if allowed
26017      * by the MeasureSpec.
26018      *
26019      * @param size Default size for this view
26020      * @param measureSpec Constraints imposed by the parent
26021      * @return The size this view should be.
26022      */
getDefaultSize(int size, int measureSpec)26023     public static int getDefaultSize(int size, int measureSpec) {
26024         int result = size;
26025         int specMode = MeasureSpec.getMode(measureSpec);
26026         int specSize = MeasureSpec.getSize(measureSpec);
26027 
26028         switch (specMode) {
26029         case MeasureSpec.UNSPECIFIED:
26030             result = size;
26031             break;
26032         case MeasureSpec.AT_MOST:
26033         case MeasureSpec.EXACTLY:
26034             result = specSize;
26035             break;
26036         }
26037         return result;
26038     }
26039 
26040     /**
26041      * Returns the suggested minimum height that the view should use. This
26042      * returns the maximum of the view's minimum height
26043      * and the background's minimum height
26044      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
26045      * <p>
26046      * When being used in {@link #onMeasure(int, int)}, the caller should still
26047      * ensure the returned height is within the requirements of the parent.
26048      *
26049      * @return The suggested minimum height of the view.
26050      */
getSuggestedMinimumHeight()26051     protected int getSuggestedMinimumHeight() {
26052         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
26053 
26054     }
26055 
26056     /**
26057      * Returns the suggested minimum width that the view should use. This
26058      * returns the maximum of the view's minimum width
26059      * and the background's minimum width
26060      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
26061      * <p>
26062      * When being used in {@link #onMeasure(int, int)}, the caller should still
26063      * ensure the returned width is within the requirements of the parent.
26064      *
26065      * @return The suggested minimum width of the view.
26066      */
getSuggestedMinimumWidth()26067     protected int getSuggestedMinimumWidth() {
26068         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
26069     }
26070 
26071     /**
26072      * Returns the minimum height of the view.
26073      *
26074      * @return the minimum height the view will try to be, in pixels
26075      *
26076      * @see #setMinimumHeight(int)
26077      *
26078      * @attr ref android.R.styleable#View_minHeight
26079      */
26080     @InspectableProperty(name = "minHeight")
getMinimumHeight()26081     public int getMinimumHeight() {
26082         return mMinHeight;
26083     }
26084 
26085     /**
26086      * Sets the minimum height of the view. It is not guaranteed the view will
26087      * be able to achieve this minimum height (for example, if its parent layout
26088      * constrains it with less available height).
26089      *
26090      * @param minHeight The minimum height the view will try to be, in pixels
26091      *
26092      * @see #getMinimumHeight()
26093      *
26094      * @attr ref android.R.styleable#View_minHeight
26095      */
26096     @RemotableViewMethod
setMinimumHeight(int minHeight)26097     public void setMinimumHeight(int minHeight) {
26098         mMinHeight = minHeight;
26099         requestLayout();
26100     }
26101 
26102     /**
26103      * Returns the minimum width of the view.
26104      *
26105      * @return the minimum width the view will try to be, in pixels
26106      *
26107      * @see #setMinimumWidth(int)
26108      *
26109      * @attr ref android.R.styleable#View_minWidth
26110      */
26111     @InspectableProperty(name = "minWidth")
getMinimumWidth()26112     public int getMinimumWidth() {
26113         return mMinWidth;
26114     }
26115 
26116     /**
26117      * Sets the minimum width of the view. It is not guaranteed the view will
26118      * be able to achieve this minimum width (for example, if its parent layout
26119      * constrains it with less available width).
26120      *
26121      * @param minWidth The minimum width the view will try to be, in pixels
26122      *
26123      * @see #getMinimumWidth()
26124      *
26125      * @attr ref android.R.styleable#View_minWidth
26126      */
26127     @RemotableViewMethod
setMinimumWidth(int minWidth)26128     public void setMinimumWidth(int minWidth) {
26129         mMinWidth = minWidth;
26130         requestLayout();
26131 
26132     }
26133 
26134     /**
26135      * Get the animation currently associated with this view.
26136      *
26137      * @return The animation that is currently playing or
26138      *         scheduled to play for this view.
26139      */
getAnimation()26140     public Animation getAnimation() {
26141         return mCurrentAnimation;
26142     }
26143 
26144     /**
26145      * Start the specified animation now.
26146      *
26147      * @param animation the animation to start now
26148      */
startAnimation(Animation animation)26149     public void startAnimation(Animation animation) {
26150         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
26151         setAnimation(animation);
26152         invalidateParentCaches();
26153         invalidate(true);
26154     }
26155 
26156     /**
26157      * Cancels any animations for this view.
26158      */
clearAnimation()26159     public void clearAnimation() {
26160         if (mCurrentAnimation != null) {
26161             mCurrentAnimation.detach();
26162         }
26163         mCurrentAnimation = null;
26164         invalidateParentIfNeeded();
26165     }
26166 
26167     /**
26168      * Sets the next animation to play for this view.
26169      * If you want the animation to play immediately, use
26170      * {@link #startAnimation(android.view.animation.Animation)} instead.
26171      * This method provides allows fine-grained
26172      * control over the start time and invalidation, but you
26173      * must make sure that 1) the animation has a start time set, and
26174      * 2) the view's parent (which controls animations on its children)
26175      * will be invalidated when the animation is supposed to
26176      * start.
26177      *
26178      * @param animation The next animation, or null.
26179      */
setAnimation(Animation animation)26180     public void setAnimation(Animation animation) {
26181         mCurrentAnimation = animation;
26182 
26183         if (animation != null) {
26184             // If the screen is off assume the animation start time is now instead of
26185             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
26186             // would cause the animation to start when the screen turns back on
26187             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
26188                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
26189                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
26190             }
26191             animation.reset();
26192         }
26193     }
26194 
26195     /**
26196      * Invoked by a parent ViewGroup to notify the start of the animation
26197      * currently associated with this view. If you override this method,
26198      * always call super.onAnimationStart();
26199      *
26200      * @see #setAnimation(android.view.animation.Animation)
26201      * @see #getAnimation()
26202      */
26203     @CallSuper
onAnimationStart()26204     protected void onAnimationStart() {
26205         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
26206     }
26207 
26208     /**
26209      * Invoked by a parent ViewGroup to notify the end of the animation
26210      * currently associated with this view. If you override this method,
26211      * always call super.onAnimationEnd();
26212      *
26213      * @see #setAnimation(android.view.animation.Animation)
26214      * @see #getAnimation()
26215      */
26216     @CallSuper
onAnimationEnd()26217     protected void onAnimationEnd() {
26218         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
26219     }
26220 
26221     /**
26222      * Invoked if there is a Transform that involves alpha. Subclass that can
26223      * draw themselves with the specified alpha should return true, and then
26224      * respect that alpha when their onDraw() is called. If this returns false
26225      * then the view may be redirected to draw into an offscreen buffer to
26226      * fulfill the request, which will look fine, but may be slower than if the
26227      * subclass handles it internally. The default implementation returns false.
26228      *
26229      * @param alpha The alpha (0..255) to apply to the view's drawing
26230      * @return true if the view can draw with the specified alpha.
26231      */
onSetAlpha(int alpha)26232     protected boolean onSetAlpha(int alpha) {
26233         return false;
26234     }
26235 
26236     /**
26237      * This is used by the ViewRoot to perform an optimization when
26238      * the view hierarchy contains one or several SurfaceView.
26239      * SurfaceView is always considered transparent, but its children are not,
26240      * therefore all View objects remove themselves from the global transparent
26241      * region (passed as a parameter to this function).
26242      *
26243      * @param region The transparent region for this ViewAncestor (window).
26244      *
26245      * @return Returns true if the effective visibility of the view at this
26246      * point is opaque, regardless of the transparent region; returns false
26247      * if it is possible for underlying windows to be seen behind the view.
26248      *
26249      */
gatherTransparentRegion(@ullable Region region)26250     public boolean gatherTransparentRegion(@Nullable Region region) {
26251         final AttachInfo attachInfo = mAttachInfo;
26252         if (region != null && attachInfo != null) {
26253             final int pflags = mPrivateFlags;
26254             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
26255                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
26256                 // remove it from the transparent region.
26257                 final int[] location = attachInfo.mTransparentLocation;
26258                 getLocationInWindow(location);
26259                 // When a view has Z value, then it will be better to leave some area below the view
26260                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
26261                 // the bottom part needs more offset than the left, top and right parts due to the
26262                 // spot light effects.
26263                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
26264                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
26265                         location[0] + mRight - mLeft + shadowOffset,
26266                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
26267             } else {
26268                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
26269                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
26270                     // the background drawable's non-transparent parts from this transparent region.
26271                     applyDrawableToTransparentRegion(mBackground, region);
26272                 }
26273                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
26274                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
26275                     // Similarly, we remove the foreground drawable's non-transparent parts.
26276                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
26277                 }
26278                 if (mDefaultFocusHighlight != null
26279                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
26280                     // Similarly, we remove the default focus highlight's non-transparent parts.
26281                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
26282                 }
26283             }
26284         }
26285         return true;
26286     }
26287 
26288     /**
26289      * Play a sound effect for this view.
26290      *
26291      * <p>The framework will play sound effects for some built in actions, such as
26292      * clicking, but you may wish to play these effects in your widget,
26293      * for instance, for internal navigation.
26294      *
26295      * <p>The sound effect will only be played if sound effects are enabled by the user, and
26296      * {@link #isSoundEffectsEnabled()} is true.
26297      *
26298      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}.
26299      */
playSoundEffect(@oundEffectConstants.SoundEffect int soundConstant)26300     public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
26301         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
26302             return;
26303         }
26304         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
26305     }
26306 
26307     /**
26308      * BZZZTT!!1!
26309      *
26310      * <p>Provide haptic feedback to the user for this view.
26311      *
26312      * <p>The framework will provide haptic feedback for some built in actions,
26313      * such as long presses, but you may wish to provide feedback for your
26314      * own widget.
26315      *
26316      * <p>The feedback will only be performed if
26317      * {@link #isHapticFeedbackEnabled()} is true.
26318      *
26319      * @param feedbackConstant One of the constants defined in
26320      * {@link HapticFeedbackConstants}
26321      */
performHapticFeedback(int feedbackConstant)26322     public boolean performHapticFeedback(int feedbackConstant) {
26323         return performHapticFeedback(feedbackConstant, 0);
26324     }
26325 
26326     /**
26327      * BZZZTT!!1!
26328      *
26329      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
26330      *
26331      * @param feedbackConstant One of the constants defined in
26332      * {@link HapticFeedbackConstants}
26333      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
26334      */
performHapticFeedback(int feedbackConstant, int flags)26335     public boolean performHapticFeedback(int feedbackConstant, int flags) {
26336         if (mAttachInfo == null) {
26337             return false;
26338         }
26339         //noinspection SimplifiableIfStatement
26340         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
26341                 && !isHapticFeedbackEnabled()) {
26342             return false;
26343         }
26344         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
26345                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
26346     }
26347 
26348     /**
26349      * Request that the visibility of the status bar or other screen/window
26350      * decorations be changed.
26351      *
26352      * <p>This method is used to put the over device UI into temporary modes
26353      * where the user's attention is focused more on the application content,
26354      * by dimming or hiding surrounding system affordances.  This is typically
26355      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
26356      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
26357      * to be placed behind the action bar (and with these flags other system
26358      * affordances) so that smooth transitions between hiding and showing them
26359      * can be done.
26360      *
26361      * <p>Two representative examples of the use of system UI visibility is
26362      * implementing a content browsing application (like a magazine reader)
26363      * and a video playing application.
26364      *
26365      * <p>The first code shows a typical implementation of a View in a content
26366      * browsing application.  In this implementation, the application goes
26367      * into a content-oriented mode by hiding the status bar and action bar,
26368      * and putting the navigation elements into lights out mode.  The user can
26369      * then interact with content while in this mode.  Such an application should
26370      * provide an easy way for the user to toggle out of the mode (such as to
26371      * check information in the status bar or access notifications).  In the
26372      * implementation here, this is done simply by tapping on the content.
26373      *
26374      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
26375      *      content}
26376      *
26377      * <p>This second code sample shows a typical implementation of a View
26378      * in a video playing application.  In this situation, while the video is
26379      * playing the application would like to go into a complete full-screen mode,
26380      * to use as much of the display as possible for the video.  When in this state
26381      * the user can not interact with the application; the system intercepts
26382      * touching on the screen to pop the UI out of full screen mode.  See
26383      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
26384      *
26385      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
26386      *      content}
26387      *
26388      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26389      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
26390      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
26391      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
26392      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
26393      *
26394      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26395      * instead.
26396      */
26397     @Deprecated
setSystemUiVisibility(int visibility)26398     public void setSystemUiVisibility(int visibility) {
26399         if (visibility != mSystemUiVisibility) {
26400             mSystemUiVisibility = visibility;
26401             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
26402                 mParent.recomputeViewAttributes(this);
26403             }
26404         }
26405     }
26406 
26407     /**
26408      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
26409      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26410      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
26411      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
26412      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
26413      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
26414      *
26415      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26416      * instead.
26417      */
26418     @Deprecated
getSystemUiVisibility()26419     public int getSystemUiVisibility() {
26420         return mSystemUiVisibility;
26421     }
26422 
26423     /**
26424      * Returns the current system UI visibility that is currently set for
26425      * the entire window.  This is the combination of the
26426      * {@link #setSystemUiVisibility(int)} values supplied by all of the
26427      * views in the window.
26428      *
26429      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26430      * instead.
26431      */
26432     @Deprecated
getWindowSystemUiVisibility()26433     public int getWindowSystemUiVisibility() {
26434         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
26435     }
26436 
26437     /**
26438      * Override to find out when the window's requested system UI visibility
26439      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
26440      * This is different from the callbacks received through
26441      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
26442      * in that this is only telling you about the local request of the window,
26443      * not the actual values applied by the system.
26444      *
26445      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26446      * instead.
26447      */
26448     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)26449     public void onWindowSystemUiVisibilityChanged(int visible) {
26450     }
26451 
26452     /**
26453      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
26454      * the view hierarchy.
26455      *
26456      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26457      * instead.
26458      */
26459     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)26460     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
26461         onWindowSystemUiVisibilityChanged(visible);
26462     }
26463 
26464     /**
26465      * Set a listener to receive callbacks when the visibility of the system bar changes.
26466      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
26467      *
26468      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
26469      * by setting a {@link OnApplyWindowInsetsListener} on this view.
26470      */
26471     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)26472     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
26473         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
26474         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
26475             mParent.recomputeViewAttributes(this);
26476         }
26477     }
26478 
26479     /**
26480      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
26481      * the view hierarchy.
26482      *
26483      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
26484      * by setting a {@link OnApplyWindowInsetsListener} on this view.
26485      */
26486     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)26487     public void dispatchSystemUiVisibilityChanged(int visibility) {
26488         ListenerInfo li = mListenerInfo;
26489         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
26490             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
26491                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
26492         }
26493     }
26494 
updateLocalSystemUiVisibility(int localValue, int localChanges)26495     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
26496         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
26497         if (val != mSystemUiVisibility) {
26498             setSystemUiVisibility(val);
26499             return true;
26500         }
26501         return false;
26502     }
26503 
26504     /** @hide */
26505     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDisabledSystemUiVisibility(int flags)26506     public void setDisabledSystemUiVisibility(int flags) {
26507         if (mAttachInfo != null) {
26508             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
26509                 mAttachInfo.mDisabledSystemUiVisibility = flags;
26510                 if (mParent != null) {
26511                     mParent.recomputeViewAttributes(this);
26512                 }
26513             }
26514         }
26515     }
26516 
26517     /**
26518      * This needs to be a better API before it is exposed. For now, only the root view will get
26519      * notified.
26520      * @hide
26521      */
onSystemBarAppearanceChanged(@indowInsetsController.Appearance int appearance)26522     public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
26523     }
26524 
26525     /**
26526      * Creates an image that the system displays during the drag and drop
26527      * operation. This is called a &quot;drag shadow&quot;. The default implementation
26528      * for a DragShadowBuilder based on a View returns an image that has exactly the same
26529      * appearance as the given View. The default also positions the center of the drag shadow
26530      * directly under the touch point. If no View is provided (the constructor with no parameters
26531      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
26532      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
26533      * default is an invisible drag shadow.
26534      * <p>
26535      * You are not required to use the View you provide to the constructor as the basis of the
26536      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
26537      * anything you want as the drag shadow.
26538      * </p>
26539      * <p>
26540      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
26541      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
26542      *  size and position of the drag shadow. It uses this data to construct a
26543      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
26544      *  so that your application can draw the shadow image in the Canvas.
26545      * </p>
26546      *
26547      * <div class="special reference">
26548      * <h3>Developer Guides</h3>
26549      * <p>For a guide to implementing drag and drop features, read the
26550      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
26551      * </div>
26552      */
26553     public static class DragShadowBuilder {
26554         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
26555         private final WeakReference<View> mView;
26556 
26557         /**
26558          * Constructs a shadow image builder based on a View. By default, the resulting drag
26559          * shadow will have the same appearance and dimensions as the View, with the touch point
26560          * over the center of the View.
26561          * @param view A View. Any View in scope can be used.
26562          */
DragShadowBuilder(View view)26563         public DragShadowBuilder(View view) {
26564             mView = new WeakReference<View>(view);
26565         }
26566 
26567         /**
26568          * Construct a shadow builder object with no associated View.  This
26569          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
26570          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
26571          * to supply the drag shadow's dimensions and appearance without
26572          * reference to any View object.
26573          */
DragShadowBuilder()26574         public DragShadowBuilder() {
26575             mView = new WeakReference<View>(null);
26576         }
26577 
26578         /**
26579          * Returns the View object that had been passed to the
26580          * {@link #DragShadowBuilder(View)}
26581          * constructor.  If that View parameter was {@code null} or if the
26582          * {@link #DragShadowBuilder()}
26583          * constructor was used to instantiate the builder object, this method will return
26584          * null.
26585          *
26586          * @return The View object associate with this builder object.
26587          */
26588         @SuppressWarnings({"JavadocReference"})
getView()26589         final public View getView() {
26590             return mView.get();
26591         }
26592 
26593         /**
26594          * Provides the metrics for the shadow image. These include the dimensions of
26595          * the shadow image, and the point within that shadow that should
26596          * be centered under the touch location while dragging.
26597          * <p>
26598          * The default implementation sets the dimensions of the shadow to be the
26599          * same as the dimensions of the View itself and centers the shadow under
26600          * the touch point.
26601          * </p>
26602          *
26603          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
26604          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
26605          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
26606          * image. Since Android P, the width and height must be positive values.
26607          *
26608          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
26609          * shadow image that should be underneath the touch point during the drag and drop
26610          * operation. Your application must set {@link android.graphics.Point#x} to the
26611          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
26612          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)26613         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
26614             final View view = mView.get();
26615             if (view != null) {
26616                 outShadowSize.set(view.getWidth(), view.getHeight());
26617                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
26618             } else {
26619                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
26620             }
26621         }
26622 
26623         /**
26624          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
26625          * based on the dimensions it received from the
26626          * {@link #onProvideShadowMetrics(Point, Point)} callback.
26627          *
26628          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
26629          */
onDrawShadow(Canvas canvas)26630         public void onDrawShadow(Canvas canvas) {
26631             final View view = mView.get();
26632             if (view != null) {
26633                 view.draw(canvas);
26634             } else {
26635                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
26636             }
26637         }
26638     }
26639 
26640     /**
26641      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
26642      * startDragAndDrop()} for newer platform versions.
26643      */
26644     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)26645     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
26646                                    Object myLocalState, int flags) {
26647         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
26648     }
26649 
26650     /**
26651      * Starts a drag and drop operation. When your application calls this method, it passes a
26652      * {@link android.view.View.DragShadowBuilder} object to the system. The
26653      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
26654      * to get metrics for the drag shadow, and then calls the object's
26655      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
26656      * <p>
26657      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
26658      *  drag events to all the View objects in your application that are currently visible. It does
26659      *  this either by calling the View object's drag listener (an implementation of
26660      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
26661      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
26662      *  Both are passed a {@link android.view.DragEvent} object that has a
26663      *  {@link android.view.DragEvent#getAction()} value of
26664      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
26665      * </p>
26666      * <p>
26667      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
26668      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
26669      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
26670      * to the View the user selected for dragging.
26671      * </p>
26672      * @param data A {@link android.content.ClipData} object pointing to the data to be
26673      * transferred by the drag and drop operation.
26674      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26675      * drag shadow.
26676      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
26677      * drop operation. When dispatching drag events to views in the same activity this object
26678      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
26679      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
26680      * will return null).
26681      * <p>
26682      * myLocalState is a lightweight mechanism for the sending information from the dragged View
26683      * to the target Views. For example, it can contain flags that differentiate between a
26684      * a copy operation and a move operation.
26685      * </p>
26686      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
26687      * flags, or any combination of the following:
26688      *     <ul>
26689      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
26690      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
26691      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
26692      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
26693      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
26694      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
26695      *         <li>{@link #DRAG_FLAG_ACCESSIBILITY_ACTION}</li>
26696      *     </ul>
26697      * @return {@code true} if the method completes successfully, or
26698      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
26699      * do a drag because of another ongoing operation or some other reasons.
26700      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)26701     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
26702             Object myLocalState, int flags) {
26703         if (ViewDebug.DEBUG_DRAG) {
26704             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
26705         }
26706         if (mAttachInfo == null) {
26707             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
26708             return false;
26709         }
26710         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
26711             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
26712             return false;
26713         }
26714 
26715         if (data != null) {
26716             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
26717         }
26718 
26719         Rect bounds = new Rect();
26720         getBoundsOnScreen(bounds, true);
26721 
26722         Point lastTouchPoint = new Point();
26723         mAttachInfo.mViewRootImpl.getLastTouchPoint(lastTouchPoint);
26724         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
26725 
26726         // Skip surface logic since shadows and animation are not required during the a11y drag
26727         final boolean a11yEnabled = AccessibilityManager.getInstance(mContext).isEnabled();
26728         if (a11yEnabled && (flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) != 0) {
26729             try {
26730                 IBinder token = mAttachInfo.mSession.performDrag(
26731                         mAttachInfo.mWindow, flags, null,
26732                         mAttachInfo.mViewRootImpl.getLastTouchSource(),
26733                         0f, 0f, 0f, 0f, data);
26734                 if (ViewDebug.DEBUG_DRAG) {
26735                     Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
26736                 }
26737                 if (token != null) {
26738                     root.setLocalDragState(myLocalState);
26739                     mAttachInfo.mDragToken = token;
26740                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
26741                     setAccessibilityDragStarted(true);
26742                 }
26743                 return token != null;
26744             } catch (Exception e) {
26745                 Log.e(VIEW_LOG_TAG, "Unable to initiate a11y drag", e);
26746                 return false;
26747             }
26748         }
26749 
26750         Point shadowSize = new Point();
26751         Point shadowTouchPoint = new Point();
26752         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
26753 
26754         if ((shadowSize.x < 0) || (shadowSize.y < 0)
26755                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
26756             throw new IllegalStateException("Drag shadow dimensions must not be negative");
26757         }
26758 
26759         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
26760         // does not accept zero size surface.
26761         if (shadowSize.x == 0  || shadowSize.y == 0) {
26762             if (!sAcceptZeroSizeDragShadow) {
26763                 throw new IllegalStateException("Drag shadow dimensions must be positive");
26764             }
26765             shadowSize.x = 1;
26766             shadowSize.y = 1;
26767         }
26768 
26769         if (ViewDebug.DEBUG_DRAG) {
26770             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
26771                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
26772         }
26773 
26774         final SurfaceSession session = new SurfaceSession();
26775         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
26776                 .setName("drag surface")
26777                 .setParent(root.getSurfaceControl())
26778                 .setBufferSize(shadowSize.x, shadowSize.y)
26779                 .setFormat(PixelFormat.TRANSLUCENT)
26780                 .setCallsite("View.startDragAndDrop")
26781                 .build();
26782         final Surface surface = new Surface();
26783         surface.copyFrom(surfaceControl);
26784         IBinder token = null;
26785         try {
26786             final Canvas canvas = isHardwareAccelerated()
26787                     ? surface.lockHardwareCanvas()
26788                     : surface.lockCanvas(null);
26789             try {
26790                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26791                 shadowBuilder.onDrawShadow(canvas);
26792             } finally {
26793                 surface.unlockCanvasAndPost(canvas);
26794             }
26795 
26796             token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
26797                     root.getLastTouchSource(), lastTouchPoint.x, lastTouchPoint.y,
26798                     shadowTouchPoint.x, shadowTouchPoint.y, data);
26799             if (ViewDebug.DEBUG_DRAG) {
26800                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
26801             }
26802             if (token != null) {
26803                 if (mAttachInfo.mDragSurface != null) {
26804                     mAttachInfo.mDragSurface.release();
26805                 }
26806                 mAttachInfo.mDragSurface = surface;
26807                 mAttachInfo.mDragToken = token;
26808                 // Cache the local state object for delivery with DragEvents
26809                 root.setLocalDragState(myLocalState);
26810                 if (a11yEnabled) {
26811                     // Set for AccessibilityEvents
26812                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
26813                 }
26814             }
26815             return token != null;
26816         } catch (Exception e) {
26817             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
26818             return false;
26819         } finally {
26820             if (token == null) {
26821                 surface.destroy();
26822             }
26823             session.kill();
26824         }
26825     }
26826 
setAccessibilityDragStarted(boolean started)26827     void setAccessibilityDragStarted(boolean started) {
26828         int pflags4 = mPrivateFlags4;
26829         if (started) {
26830             pflags4 |= PFLAG4_DRAG_A11Y_STARTED;
26831         } else {
26832             pflags4 &= ~PFLAG4_DRAG_A11Y_STARTED;
26833         }
26834 
26835         if (pflags4 != mPrivateFlags4) {
26836             mPrivateFlags4 = pflags4;
26837             sendWindowContentChangedAccessibilityEvent(CONTENT_CHANGE_TYPE_UNDEFINED);
26838         }
26839     }
26840 
startedSystemDragForAccessibility()26841     private boolean startedSystemDragForAccessibility() {
26842         return (mPrivateFlags4 & PFLAG4_DRAG_A11Y_STARTED) != 0;
26843     }
26844 
26845     /**
26846      * Cancels an ongoing drag and drop operation.
26847      * <p>
26848      * A {@link android.view.DragEvent} object with
26849      * {@link android.view.DragEvent#getAction()} value of
26850      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
26851      * {@link android.view.DragEvent#getResult()} value of {@code false}
26852      * will be sent to every
26853      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
26854      * even if they are not currently visible.
26855      * </p>
26856      * <p>
26857      * This method can be called on any View in the same window as the View on which
26858      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
26859      * was called.
26860      * </p>
26861      */
cancelDragAndDrop()26862     public final void cancelDragAndDrop() {
26863         if (ViewDebug.DEBUG_DRAG) {
26864             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
26865         }
26866         if (mAttachInfo == null) {
26867             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
26868             return;
26869         }
26870         if (mAttachInfo.mDragToken != null) {
26871             try {
26872                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
26873             } catch (Exception e) {
26874                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
26875             }
26876             mAttachInfo.mDragToken = null;
26877         } else {
26878             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
26879         }
26880     }
26881 
26882     /**
26883      * Updates the drag shadow for the ongoing drag and drop operation.
26884      *
26885      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26886      * new drag shadow.
26887      */
updateDragShadow(DragShadowBuilder shadowBuilder)26888     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
26889         if (ViewDebug.DEBUG_DRAG) {
26890             Log.d(VIEW_LOG_TAG, "updateDragShadow");
26891         }
26892         if (mAttachInfo == null) {
26893             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
26894             return;
26895         }
26896         if (mAttachInfo.mDragToken != null) {
26897             try {
26898                 Canvas canvas = isHardwareAccelerated()
26899                         ? mAttachInfo.mDragSurface.lockHardwareCanvas()
26900                         : mAttachInfo.mDragSurface.lockCanvas(null);
26901                 try {
26902                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26903                     shadowBuilder.onDrawShadow(canvas);
26904                 } finally {
26905                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
26906                 }
26907             } catch (Exception e) {
26908                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
26909             }
26910         } else {
26911             Log.e(VIEW_LOG_TAG, "No active drag");
26912         }
26913     }
26914 
26915     /**
26916      * Starts a move from {startX, startY}, the amount of the movement will be the offset
26917      * between {startX, startY} and the new cursor positon.
26918      * @param startX horizontal coordinate where the move started.
26919      * @param startY vertical coordinate where the move started.
26920      * @return whether moving was started successfully.
26921      * @hide
26922      */
startMovingTask(float startX, float startY)26923     public final boolean startMovingTask(float startX, float startY) {
26924         if (ViewDebug.DEBUG_POSITIONING) {
26925             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
26926         }
26927         try {
26928             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
26929         } catch (RemoteException e) {
26930             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
26931         }
26932         return false;
26933     }
26934 
26935     /**
26936      * Finish a window move task.
26937      * @hide
26938      */
finishMovingTask()26939     public void finishMovingTask() {
26940         if (ViewDebug.DEBUG_POSITIONING) {
26941             Log.d(VIEW_LOG_TAG, "finishMovingTask");
26942         }
26943         try {
26944             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
26945         } catch (RemoteException e) {
26946             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
26947         }
26948     }
26949 
26950     /**
26951      * Handles drag events sent by the system following a call to
26952      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
26953      * startDragAndDrop()}.
26954      *<p>
26955      * When the system calls this method, it passes a
26956      * {@link android.view.DragEvent} object. A call to
26957      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
26958      * in DragEvent. The method uses these to determine what is happening in the drag and drop
26959      * operation.
26960      * </p>
26961      * <p>
26962      * The default implementation returns false, except if an {@link OnReceiveContentListener}
26963      * is {@link #setOnReceiveContentListener set} for this view. If an
26964      * {@link OnReceiveContentListener} is set, the default implementation...
26965      * <ul>
26966      * <li>returns true for an
26967      * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
26968      * <li>calls {@link #performReceiveContent} for an
26969      * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event
26970      * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if
26971      * the listener consumed some or all of the content
26972      * </ul>
26973      * </p>
26974      *
26975      * @param event The {@link android.view.DragEvent} sent by the system.
26976      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
26977      * in DragEvent, indicating the type of drag event represented by this object.
26978      * @return {@code true} if the method was successful, otherwise {@code false}.
26979      * <p>
26980      *  The method should return {@code true} in response to an action type of
26981      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
26982      *  operation.
26983      * </p>
26984      * <p>
26985      *  The method should also return {@code true} in response to an action type of
26986      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
26987      *  {@code false} if it didn't.
26988      * </p>
26989      * <p>
26990      *  For all other events, the return value is ignored.
26991      * </p>
26992      */
onDragEvent(DragEvent event)26993     public boolean onDragEvent(DragEvent event) {
26994         if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
26995             return false;
26996         }
26997         // Accept drag events by default if there's an OnReceiveContentListener set.
26998         if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
26999             return true;
27000         }
27001         if (event.getAction() == DragEvent.ACTION_DROP) {
27002             final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
27003             if (permissions != null) {
27004                 permissions.takeTransient();
27005             }
27006             final ContentInfo payload =
27007                     new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
27008                             .setDragAndDropPermissions(permissions)
27009                             .build();
27010             ContentInfo remainingPayload = performReceiveContent(payload);
27011             // Return true unless none of the payload was consumed.
27012             return remainingPayload != payload;
27013         }
27014         return false;
27015     }
27016 
27017     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)27018     boolean dispatchDragEnterExitInPreN(DragEvent event) {
27019         return callDragEventHandler(event);
27020     }
27021 
27022     /**
27023      * Detects if this View is enabled and has a drag event listener.
27024      * If both are true, then it calls the drag event listener with the
27025      * {@link android.view.DragEvent} it received. If the drag event listener returns
27026      * {@code true}, then dispatchDragEvent() returns {@code true}.
27027      * <p>
27028      * For all other cases, the method calls the
27029      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
27030      * method and returns its result.
27031      * </p>
27032      * <p>
27033      * This ensures that a drag event is always consumed, even if the View does not have a drag
27034      * event listener. However, if the View has a listener and the listener returns true, then
27035      * onDragEvent() is not called.
27036      * </p>
27037      */
dispatchDragEvent(DragEvent event)27038     public boolean dispatchDragEvent(DragEvent event) {
27039         event.mEventHandlerWasCalled = true;
27040         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
27041             event.mAction == DragEvent.ACTION_DROP) {
27042             // About to deliver an event with coordinates to this view. Notify that now this view
27043             // has drag focus. This will send exit/enter events as needed.
27044             getViewRootImpl().setDragFocus(this, event);
27045         }
27046         return callDragEventHandler(event);
27047     }
27048 
callDragEventHandler(DragEvent event)27049     final boolean callDragEventHandler(DragEvent event) {
27050         final boolean result;
27051 
27052         ListenerInfo li = mListenerInfo;
27053         //noinspection SimplifiableIfStatement
27054         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
27055                 && li.mOnDragListener.onDrag(this, event)) {
27056             result = true;
27057         } else {
27058             result = onDragEvent(event);
27059         }
27060 
27061         switch (event.mAction) {
27062             case DragEvent.ACTION_DRAG_STARTED: {
27063                 if (result && li != null && li.mOnDragListener != null) {
27064                     sendWindowContentChangedAccessibilityEvent(
27065                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
27066                 }
27067             } break;
27068             case DragEvent.ACTION_DRAG_ENTERED: {
27069                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
27070                 refreshDrawableState();
27071             } break;
27072             case DragEvent.ACTION_DRAG_EXITED: {
27073                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
27074                 refreshDrawableState();
27075             } break;
27076             case DragEvent.ACTION_DROP: {
27077                 if (result && li != null && (li.mOnDragListener != null
27078                         || li.mOnReceiveContentListener != null)) {
27079                     sendWindowContentChangedAccessibilityEvent(
27080                             AccessibilityEvent.CONTENT_CHANGE_TYPE_DRAG_DROPPED);
27081                 }
27082             } break;
27083             case DragEvent.ACTION_DRAG_ENDED: {
27084                 sendWindowContentChangedAccessibilityEvent(
27085                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
27086                 mPrivateFlags2 &= ~View.DRAG_MASK;
27087                 refreshDrawableState();
27088             } break;
27089         }
27090 
27091         return result;
27092     }
27093 
canAcceptDrag()27094     boolean canAcceptDrag() {
27095         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
27096     }
27097 
sendWindowContentChangedAccessibilityEvent(int changeType)27098     void sendWindowContentChangedAccessibilityEvent(int changeType) {
27099         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
27100             AccessibilityEvent event = AccessibilityEvent.obtain();
27101             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
27102             event.setContentChangeTypes(changeType);
27103             sendAccessibilityEventUnchecked(event);
27104         }
27105     }
27106 
27107     /**
27108      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
27109      * it is ever exposed at all.
27110      * @hide
27111      */
27112     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)27113     public void onCloseSystemDialogs(String reason) {
27114     }
27115 
27116     /**
27117      * Given a Drawable whose bounds have been set to draw into this view,
27118      * update a Region being computed for
27119      * {@link #gatherTransparentRegion(android.graphics.Region)} so
27120      * that any non-transparent parts of the Drawable are removed from the
27121      * given transparent region.
27122      *
27123      * @param dr The Drawable whose transparency is to be applied to the region.
27124      * @param region A Region holding the current transparency information,
27125      * where any parts of the region that are set are considered to be
27126      * transparent.  On return, this region will be modified to have the
27127      * transparency information reduced by the corresponding parts of the
27128      * Drawable that are not transparent.
27129      * {@hide}
27130      */
27131     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
applyDrawableToTransparentRegion(Drawable dr, Region region)27132     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
27133         if (DBG) {
27134             Log.i("View", "Getting transparent region for: " + this);
27135         }
27136         final Region r = dr.getTransparentRegion();
27137         final Rect db = dr.getBounds();
27138         final AttachInfo attachInfo = mAttachInfo;
27139         if (r != null && attachInfo != null) {
27140             final int w = getRight()-getLeft();
27141             final int h = getBottom()-getTop();
27142             if (db.left > 0) {
27143                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
27144                 r.op(0, 0, db.left, h, Region.Op.UNION);
27145             }
27146             if (db.right < w) {
27147                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
27148                 r.op(db.right, 0, w, h, Region.Op.UNION);
27149             }
27150             if (db.top > 0) {
27151                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
27152                 r.op(0, 0, w, db.top, Region.Op.UNION);
27153             }
27154             if (db.bottom < h) {
27155                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
27156                 r.op(0, db.bottom, w, h, Region.Op.UNION);
27157             }
27158             final int[] location = attachInfo.mTransparentLocation;
27159             getLocationInWindow(location);
27160             r.translate(location[0], location[1]);
27161             region.op(r, Region.Op.INTERSECT);
27162         } else {
27163             region.op(db, Region.Op.DIFFERENCE);
27164         }
27165     }
27166 
checkForLongClick(long delay, float x, float y, int classification)27167     private void checkForLongClick(long delay, float x, float y, int classification) {
27168         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
27169             mHasPerformedLongPress = false;
27170 
27171             if (mPendingCheckForLongPress == null) {
27172                 mPendingCheckForLongPress = new CheckForLongPress();
27173             }
27174             mPendingCheckForLongPress.setAnchor(x, y);
27175             mPendingCheckForLongPress.rememberWindowAttachCount();
27176             mPendingCheckForLongPress.rememberPressedState();
27177             mPendingCheckForLongPress.setClassification(classification);
27178             postDelayed(mPendingCheckForLongPress, delay);
27179         }
27180     }
27181 
27182     /**
27183      * Inflate a view from an XML resource.  This convenience method wraps the {@link
27184      * LayoutInflater} class, which provides a full range of options for view inflation.
27185      *
27186      * @param context The Context object for your activity or application.
27187      * @param resource The resource ID to inflate
27188      * @param root A view group that will be the parent.  Used to properly inflate the
27189      * layout_* parameters.
27190      * @see LayoutInflater
27191      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)27192     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
27193         LayoutInflater factory = LayoutInflater.from(context);
27194         return factory.inflate(resource, root);
27195     }
27196 
27197     /**
27198      * Scroll the view with standard behavior for scrolling beyond the normal
27199      * content boundaries. Views that call this method should override
27200      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
27201      * results of an over-scroll operation.
27202      *
27203      * Views can use this method to handle any touch or fling-based scrolling.
27204      *
27205      * @param deltaX Change in X in pixels
27206      * @param deltaY Change in Y in pixels
27207      * @param scrollX Current X scroll value in pixels before applying deltaX
27208      * @param scrollY Current Y scroll value in pixels before applying deltaY
27209      * @param scrollRangeX Maximum content scroll range along the X axis
27210      * @param scrollRangeY Maximum content scroll range along the Y axis
27211      * @param maxOverScrollX Number of pixels to overscroll by in either direction
27212      *          along the X axis.
27213      * @param maxOverScrollY Number of pixels to overscroll by in either direction
27214      *          along the Y axis.
27215      * @param isTouchEvent true if this scroll operation is the result of a touch event.
27216      * @return true if scrolling was clamped to an over-scroll boundary along either
27217      *          axis, false otherwise.
27218      */
27219     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)27220     protected boolean overScrollBy(int deltaX, int deltaY,
27221             int scrollX, int scrollY,
27222             int scrollRangeX, int scrollRangeY,
27223             int maxOverScrollX, int maxOverScrollY,
27224             boolean isTouchEvent) {
27225         final int overScrollMode = mOverScrollMode;
27226         final boolean canScrollHorizontal =
27227                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
27228         final boolean canScrollVertical =
27229                 computeVerticalScrollRange() > computeVerticalScrollExtent();
27230         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
27231                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
27232         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
27233                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
27234 
27235         int newScrollX = scrollX + deltaX;
27236         if (!overScrollHorizontal) {
27237             maxOverScrollX = 0;
27238         }
27239 
27240         int newScrollY = scrollY + deltaY;
27241         if (!overScrollVertical) {
27242             maxOverScrollY = 0;
27243         }
27244 
27245         // Clamp values if at the limits and record
27246         final int left = -maxOverScrollX;
27247         final int right = maxOverScrollX + scrollRangeX;
27248         final int top = -maxOverScrollY;
27249         final int bottom = maxOverScrollY + scrollRangeY;
27250 
27251         boolean clampedX = false;
27252         if (newScrollX > right) {
27253             newScrollX = right;
27254             clampedX = true;
27255         } else if (newScrollX < left) {
27256             newScrollX = left;
27257             clampedX = true;
27258         }
27259 
27260         boolean clampedY = false;
27261         if (newScrollY > bottom) {
27262             newScrollY = bottom;
27263             clampedY = true;
27264         } else if (newScrollY < top) {
27265             newScrollY = top;
27266             clampedY = true;
27267         }
27268 
27269         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
27270 
27271         return clampedX || clampedY;
27272     }
27273 
27274     /**
27275      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
27276      * respond to the results of an over-scroll operation.
27277      *
27278      * @param scrollX New X scroll value in pixels
27279      * @param scrollY New Y scroll value in pixels
27280      * @param clampedX True if scrollX was clamped to an over-scroll boundary
27281      * @param clampedY True if scrollY was clamped to an over-scroll boundary
27282      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)27283     protected void onOverScrolled(int scrollX, int scrollY,
27284             boolean clampedX, boolean clampedY) {
27285         // Intentionally empty.
27286     }
27287 
27288     /**
27289      * Returns the over-scroll mode for this view. The result will be
27290      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
27291      * (allow over-scrolling only if the view content is larger than the container),
27292      * or {@link #OVER_SCROLL_NEVER}.
27293      *
27294      * @return This view's over-scroll mode.
27295      */
27296     @InspectableProperty(enumMapping = {
27297             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
27298             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
27299             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
27300     })
getOverScrollMode()27301     public int getOverScrollMode() {
27302         return mOverScrollMode;
27303     }
27304 
27305     /**
27306      * Set the over-scroll mode for this view. Valid over-scroll modes are
27307      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
27308      * (allow over-scrolling only if the view content is larger than the container),
27309      * or {@link #OVER_SCROLL_NEVER}.
27310      *
27311      * Setting the over-scroll mode of a view will have an effect only if the
27312      * view is capable of scrolling.
27313      *
27314      * @param overScrollMode The new over-scroll mode for this view.
27315      */
setOverScrollMode(int overScrollMode)27316     public void setOverScrollMode(int overScrollMode) {
27317         if (overScrollMode != OVER_SCROLL_ALWAYS &&
27318                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
27319                 overScrollMode != OVER_SCROLL_NEVER) {
27320             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
27321         }
27322         mOverScrollMode = overScrollMode;
27323     }
27324 
27325     /**
27326      * Enable or disable nested scrolling for this view.
27327      *
27328      * <p>If this property is set to true the view will be permitted to initiate nested
27329      * scrolling operations with a compatible parent view in the current hierarchy. If this
27330      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
27331      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
27332      * the nested scroll.</p>
27333      *
27334      * @param enabled true to enable nested scrolling, false to disable
27335      *
27336      * @see #isNestedScrollingEnabled()
27337      */
setNestedScrollingEnabled(boolean enabled)27338     public void setNestedScrollingEnabled(boolean enabled) {
27339         if (enabled) {
27340             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
27341         } else {
27342             stopNestedScroll();
27343             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
27344         }
27345     }
27346 
27347     /**
27348      * Returns true if nested scrolling is enabled for this view.
27349      *
27350      * <p>If nested scrolling is enabled and this View class implementation supports it,
27351      * this view will act as a nested scrolling child view when applicable, forwarding data
27352      * about the scroll operation in progress to a compatible and cooperating nested scrolling
27353      * parent.</p>
27354      *
27355      * @return true if nested scrolling is enabled
27356      *
27357      * @see #setNestedScrollingEnabled(boolean)
27358      */
27359     @InspectableProperty
isNestedScrollingEnabled()27360     public boolean isNestedScrollingEnabled() {
27361         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
27362                 PFLAG3_NESTED_SCROLLING_ENABLED;
27363     }
27364 
27365     /**
27366      * Begin a nestable scroll operation along the given axes.
27367      *
27368      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
27369      *
27370      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
27371      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
27372      * In the case of touch scrolling the nested scroll will be terminated automatically in
27373      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
27374      * In the event of programmatic scrolling the caller must explicitly call
27375      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
27376      *
27377      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
27378      * If it returns false the caller may ignore the rest of this contract until the next scroll.
27379      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
27380      *
27381      * <p>At each incremental step of the scroll the caller should invoke
27382      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
27383      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
27384      * parent at least partially consumed the scroll and the caller should adjust the amount it
27385      * scrolls by.</p>
27386      *
27387      * <p>After applying the remainder of the scroll delta the caller should invoke
27388      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
27389      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
27390      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
27391      * </p>
27392      *
27393      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
27394      *             {@link #SCROLL_AXIS_VERTICAL}.
27395      * @return true if a cooperative parent was found and nested scrolling has been enabled for
27396      *         the current gesture.
27397      *
27398      * @see #stopNestedScroll()
27399      * @see #dispatchNestedPreScroll(int, int, int[], int[])
27400      * @see #dispatchNestedScroll(int, int, int, int, int[])
27401      */
startNestedScroll(int axes)27402     public boolean startNestedScroll(int axes) {
27403         if (hasNestedScrollingParent()) {
27404             // Already in progress
27405             return true;
27406         }
27407         if (isNestedScrollingEnabled()) {
27408             ViewParent p = getParent();
27409             View child = this;
27410             while (p != null) {
27411                 try {
27412                     if (p.onStartNestedScroll(child, this, axes)) {
27413                         mNestedScrollingParent = p;
27414                         p.onNestedScrollAccepted(child, this, axes);
27415                         return true;
27416                     }
27417                 } catch (AbstractMethodError e) {
27418                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
27419                             "method onStartNestedScroll", e);
27420                     // Allow the search upward to continue
27421                 }
27422                 if (p instanceof View) {
27423                     child = (View) p;
27424                 }
27425                 p = p.getParent();
27426             }
27427         }
27428         return false;
27429     }
27430 
27431     /**
27432      * Stop a nested scroll in progress.
27433      *
27434      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
27435      *
27436      * @see #startNestedScroll(int)
27437      */
stopNestedScroll()27438     public void stopNestedScroll() {
27439         if (mNestedScrollingParent != null) {
27440             mNestedScrollingParent.onStopNestedScroll(this);
27441             mNestedScrollingParent = null;
27442         }
27443     }
27444 
27445     /**
27446      * Returns true if this view has a nested scrolling parent.
27447      *
27448      * <p>The presence of a nested scrolling parent indicates that this view has initiated
27449      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
27450      *
27451      * @return whether this view has a nested scrolling parent
27452      */
hasNestedScrollingParent()27453     public boolean hasNestedScrollingParent() {
27454         return mNestedScrollingParent != null;
27455     }
27456 
27457     /**
27458      * Dispatch one step of a nested scroll in progress.
27459      *
27460      * <p>Implementations of views that support nested scrolling should call this to report
27461      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
27462      * is not currently in progress or nested scrolling is not
27463      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
27464      *
27465      * <p>Compatible View implementations should also call
27466      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
27467      * consuming a component of the scroll event themselves.</p>
27468      *
27469      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
27470      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
27471      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
27472      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
27473      * @param offsetInWindow Optional. If not null, on return this will contain the offset
27474      *                       in local view coordinates of this view from before this operation
27475      *                       to after it completes. View implementations may use this to adjust
27476      *                       expected input coordinate tracking.
27477      * @return true if the event was dispatched, false if it could not be dispatched.
27478      * @see #dispatchNestedPreScroll(int, int, int[], int[])
27479      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)27480     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
27481             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
27482         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27483             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
27484                 int startX = 0;
27485                 int startY = 0;
27486                 if (offsetInWindow != null) {
27487                     getLocationInWindow(offsetInWindow);
27488                     startX = offsetInWindow[0];
27489                     startY = offsetInWindow[1];
27490                 }
27491 
27492                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
27493                         dxUnconsumed, dyUnconsumed);
27494 
27495                 if (offsetInWindow != null) {
27496                     getLocationInWindow(offsetInWindow);
27497                     offsetInWindow[0] -= startX;
27498                     offsetInWindow[1] -= startY;
27499                 }
27500                 return true;
27501             } else if (offsetInWindow != null) {
27502                 // No motion, no dispatch. Keep offsetInWindow up to date.
27503                 offsetInWindow[0] = 0;
27504                 offsetInWindow[1] = 0;
27505             }
27506         }
27507         return false;
27508     }
27509 
27510     /**
27511      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
27512      *
27513      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
27514      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
27515      * scrolling operation to consume some or all of the scroll operation before the child view
27516      * consumes it.</p>
27517      *
27518      * @param dx Horizontal scroll distance in pixels
27519      * @param dy Vertical scroll distance in pixels
27520      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
27521      *                 and consumed[1] the consumed dy.
27522      * @param offsetInWindow Optional. If not null, on return this will contain the offset
27523      *                       in local view coordinates of this view from before this operation
27524      *                       to after it completes. View implementations may use this to adjust
27525      *                       expected input coordinate tracking.
27526      * @return true if the parent consumed some or all of the scroll delta
27527      * @see #dispatchNestedScroll(int, int, int, int, int[])
27528      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)27529     public boolean dispatchNestedPreScroll(int dx, int dy,
27530             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
27531         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27532             if (dx != 0 || dy != 0) {
27533                 int startX = 0;
27534                 int startY = 0;
27535                 if (offsetInWindow != null) {
27536                     getLocationInWindow(offsetInWindow);
27537                     startX = offsetInWindow[0];
27538                     startY = offsetInWindow[1];
27539                 }
27540 
27541                 if (consumed == null) {
27542                     if (mTempNestedScrollConsumed == null) {
27543                         mTempNestedScrollConsumed = new int[2];
27544                     }
27545                     consumed = mTempNestedScrollConsumed;
27546                 }
27547                 consumed[0] = 0;
27548                 consumed[1] = 0;
27549                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
27550 
27551                 if (offsetInWindow != null) {
27552                     getLocationInWindow(offsetInWindow);
27553                     offsetInWindow[0] -= startX;
27554                     offsetInWindow[1] -= startY;
27555                 }
27556                 return consumed[0] != 0 || consumed[1] != 0;
27557             } else if (offsetInWindow != null) {
27558                 offsetInWindow[0] = 0;
27559                 offsetInWindow[1] = 0;
27560             }
27561         }
27562         return false;
27563     }
27564 
27565     /**
27566      * Dispatch a fling to a nested scrolling parent.
27567      *
27568      * <p>This method should be used to indicate that a nested scrolling child has detected
27569      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
27570      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
27571      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
27572      * along a scrollable axis.</p>
27573      *
27574      * <p>If a nested scrolling child view would normally fling but it is at the edge of
27575      * its own content, it can use this method to delegate the fling to its nested scrolling
27576      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
27577      *
27578      * @param velocityX Horizontal fling velocity in pixels per second
27579      * @param velocityY Vertical fling velocity in pixels per second
27580      * @param consumed true if the child consumed the fling, false otherwise
27581      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
27582      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)27583     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
27584         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27585             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
27586         }
27587         return false;
27588     }
27589 
27590     /**
27591      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
27592      *
27593      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
27594      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
27595      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
27596      * before the child view consumes it. If this method returns <code>true</code>, a nested
27597      * parent view consumed the fling and this view should not scroll as a result.</p>
27598      *
27599      * <p>For a better user experience, only one view in a nested scrolling chain should consume
27600      * the fling at a time. If a parent view consumed the fling this method will return false.
27601      * Custom view implementations should account for this in two ways:</p>
27602      *
27603      * <ul>
27604      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
27605      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
27606      *     position regardless.</li>
27607      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
27608      *     even to settle back to a valid idle position.</li>
27609      * </ul>
27610      *
27611      * <p>Views should also not offer fling velocities to nested parent views along an axis
27612      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
27613      * should not offer a horizontal fling velocity to its parents since scrolling along that
27614      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
27615      *
27616      * @param velocityX Horizontal fling velocity in pixels per second
27617      * @param velocityY Vertical fling velocity in pixels per second
27618      * @return true if a nested scrolling parent consumed the fling
27619      */
dispatchNestedPreFling(float velocityX, float velocityY)27620     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
27621         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27622             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
27623         }
27624         return false;
27625     }
27626 
27627     /**
27628      * Gets a scale factor that determines the distance the view should scroll
27629      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
27630      * @return The vertical scroll scale factor.
27631      * @hide
27632      */
27633     @UnsupportedAppUsage
getVerticalScrollFactor()27634     protected float getVerticalScrollFactor() {
27635         if (mVerticalScrollFactor == 0) {
27636             TypedValue outValue = new TypedValue();
27637             if (!mContext.getTheme().resolveAttribute(
27638                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
27639                 throw new IllegalStateException(
27640                         "Expected theme to define listPreferredItemHeight.");
27641             }
27642             mVerticalScrollFactor = outValue.getDimension(
27643                     mContext.getResources().getDisplayMetrics());
27644         }
27645         return mVerticalScrollFactor;
27646     }
27647 
27648     /**
27649      * Gets a scale factor that determines the distance the view should scroll
27650      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
27651      * @return The horizontal scroll scale factor.
27652      * @hide
27653      */
27654     @UnsupportedAppUsage
getHorizontalScrollFactor()27655     protected float getHorizontalScrollFactor() {
27656         // TODO: Should use something else.
27657         return getVerticalScrollFactor();
27658     }
27659 
27660     /**
27661      * Return the value specifying the text direction or policy that was set with
27662      * {@link #setTextDirection(int)}.
27663      *
27664      * @return the defined text direction. It can be one of:
27665      *
27666      * {@link #TEXT_DIRECTION_INHERIT},
27667      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27668      * {@link #TEXT_DIRECTION_ANY_RTL},
27669      * {@link #TEXT_DIRECTION_LTR},
27670      * {@link #TEXT_DIRECTION_RTL},
27671      * {@link #TEXT_DIRECTION_LOCALE},
27672      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27673      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
27674      *
27675      * @attr ref android.R.styleable#View_textDirection
27676      *
27677      * @hide
27678      */
27679     @ViewDebug.ExportedProperty(category = "text", mapping = {
27680             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
27681             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
27682             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
27683             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
27684             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
27685             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
27686             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
27687             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
27688     })
27689     @InspectableProperty(hasAttributeId = false, enumMapping = {
27690             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
27691             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
27692             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
27693             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
27694             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
27695             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
27696             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
27697             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
27698     })
27699     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextDirection()27700     public int getRawTextDirection() {
27701         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
27702     }
27703 
27704     /**
27705      * Set the text direction.
27706      *
27707      * @param textDirection the direction to set. Should be one of:
27708      *
27709      * {@link #TEXT_DIRECTION_INHERIT},
27710      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27711      * {@link #TEXT_DIRECTION_ANY_RTL},
27712      * {@link #TEXT_DIRECTION_LTR},
27713      * {@link #TEXT_DIRECTION_RTL},
27714      * {@link #TEXT_DIRECTION_LOCALE}
27715      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27716      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
27717      *
27718      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
27719      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
27720      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
27721      *
27722      * @attr ref android.R.styleable#View_textDirection
27723      */
setTextDirection(int textDirection)27724     public void setTextDirection(int textDirection) {
27725         if (getRawTextDirection() != textDirection) {
27726             // Reset the current text direction and the resolved one
27727             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
27728             resetResolvedTextDirection();
27729             // Set the new text direction
27730             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
27731             // Do resolution
27732             resolveTextDirection();
27733             // Notify change
27734             onRtlPropertiesChanged(getLayoutDirection());
27735             // Refresh
27736             requestLayout();
27737             invalidate(true);
27738         }
27739     }
27740 
27741     /**
27742      * Return the resolved text direction.
27743      *
27744      * @return the resolved text direction. Returns one of:
27745      *
27746      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27747      * {@link #TEXT_DIRECTION_ANY_RTL},
27748      * {@link #TEXT_DIRECTION_LTR},
27749      * {@link #TEXT_DIRECTION_RTL},
27750      * {@link #TEXT_DIRECTION_LOCALE},
27751      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27752      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
27753      *
27754      * @attr ref android.R.styleable#View_textDirection
27755      */
27756     @ViewDebug.ExportedProperty(category = "text", mapping = {
27757             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
27758             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
27759             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
27760             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
27761             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
27762             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
27763             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
27764             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
27765     })
27766     @InspectableProperty(hasAttributeId = false, enumMapping = {
27767             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
27768             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
27769             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
27770             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
27771             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
27772             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
27773             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
27774     })
getTextDirection()27775     public int getTextDirection() {
27776         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
27777     }
27778 
27779     /**
27780      * Resolve the text direction.
27781      *
27782      * @return true if resolution has been done, false otherwise.
27783      *
27784      * @hide
27785      */
resolveTextDirection()27786     public boolean resolveTextDirection() {
27787         // Reset any previous text direction resolution
27788         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27789 
27790         if (hasRtlSupport()) {
27791             // Set resolved text direction flag depending on text direction flag
27792             final int textDirection = getRawTextDirection();
27793             switch(textDirection) {
27794                 case TEXT_DIRECTION_INHERIT:
27795                     if (!canResolveTextDirection()) {
27796                         // We cannot do the resolution if there is no parent, so use the default one
27797                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27798                         // Resolution will need to happen again later
27799                         return false;
27800                     }
27801 
27802                     // Parent has not yet resolved, so we still return the default
27803                     try {
27804                         if (!mParent.isTextDirectionResolved()) {
27805                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27806                             // Resolution will need to happen again later
27807                             return false;
27808                         }
27809                     } catch (AbstractMethodError e) {
27810                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27811                                 " does not fully implement ViewParent", e);
27812                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
27813                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27814                         return true;
27815                     }
27816 
27817                     // Set current resolved direction to the same value as the parent's one
27818                     int parentResolvedDirection;
27819                     try {
27820                         parentResolvedDirection = mParent.getTextDirection();
27821                     } catch (AbstractMethodError e) {
27822                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27823                                 " does not fully implement ViewParent", e);
27824                         parentResolvedDirection = TEXT_DIRECTION_LTR;
27825                     }
27826                     switch (parentResolvedDirection) {
27827                         case TEXT_DIRECTION_FIRST_STRONG:
27828                         case TEXT_DIRECTION_ANY_RTL:
27829                         case TEXT_DIRECTION_LTR:
27830                         case TEXT_DIRECTION_RTL:
27831                         case TEXT_DIRECTION_LOCALE:
27832                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
27833                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
27834                             mPrivateFlags2 |=
27835                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
27836                             break;
27837                         default:
27838                             // Default resolved direction is "first strong" heuristic
27839                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27840                     }
27841                     break;
27842                 case TEXT_DIRECTION_FIRST_STRONG:
27843                 case TEXT_DIRECTION_ANY_RTL:
27844                 case TEXT_DIRECTION_LTR:
27845                 case TEXT_DIRECTION_RTL:
27846                 case TEXT_DIRECTION_LOCALE:
27847                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
27848                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
27849                     // Resolved direction is the same as text direction
27850                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
27851                     break;
27852                 default:
27853                     // Default resolved direction is "first strong" heuristic
27854                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27855             }
27856         } else {
27857             // Default resolved direction is "first strong" heuristic
27858             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27859         }
27860 
27861         // Set to resolved
27862         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
27863         return true;
27864     }
27865 
27866     /**
27867      * Check if text direction resolution can be done.
27868      *
27869      * @return true if text direction resolution can be done otherwise return false.
27870      */
canResolveTextDirection()27871     public boolean canResolveTextDirection() {
27872         switch (getRawTextDirection()) {
27873             case TEXT_DIRECTION_INHERIT:
27874                 if (mParent != null) {
27875                     try {
27876                         return mParent.canResolveTextDirection();
27877                     } catch (AbstractMethodError e) {
27878                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27879                                 " does not fully implement ViewParent", e);
27880                     }
27881                 }
27882                 return false;
27883 
27884             default:
27885                 return true;
27886         }
27887     }
27888 
27889     /**
27890      * Reset resolved text direction. Text direction will be resolved during a call to
27891      * {@link #onMeasure(int, int)}.
27892      *
27893      * @hide
27894      */
27895     @TestApi
resetResolvedTextDirection()27896     public void resetResolvedTextDirection() {
27897         // Reset any previous text direction resolution
27898         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27899         // Set to default value
27900         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27901     }
27902 
27903     /**
27904      * @return true if text direction is inherited.
27905      *
27906      * @hide
27907      */
isTextDirectionInherited()27908     public boolean isTextDirectionInherited() {
27909         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
27910     }
27911 
27912     /**
27913      * @return true if text direction is resolved.
27914      */
isTextDirectionResolved()27915     public boolean isTextDirectionResolved() {
27916         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
27917     }
27918 
27919     /**
27920      * Return the value specifying the text alignment or policy that was set with
27921      * {@link #setTextAlignment(int)}.
27922      *
27923      * @return the defined text alignment. It can be one of:
27924      *
27925      * {@link #TEXT_ALIGNMENT_INHERIT},
27926      * {@link #TEXT_ALIGNMENT_GRAVITY},
27927      * {@link #TEXT_ALIGNMENT_CENTER},
27928      * {@link #TEXT_ALIGNMENT_TEXT_START},
27929      * {@link #TEXT_ALIGNMENT_TEXT_END},
27930      * {@link #TEXT_ALIGNMENT_VIEW_START},
27931      * {@link #TEXT_ALIGNMENT_VIEW_END}
27932      *
27933      * @attr ref android.R.styleable#View_textAlignment
27934      *
27935      * @hide
27936      */
27937     @ViewDebug.ExportedProperty(category = "text", mapping = {
27938             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27939             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27940             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27941             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27942             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27943             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27944             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27945     })
27946     @InspectableProperty(hasAttributeId = false, enumMapping = {
27947             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
27948             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27949             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27950             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27951             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27952             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27953             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27954     })
27955     @TextAlignment
27956     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextAlignment()27957     public int getRawTextAlignment() {
27958         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
27959     }
27960 
27961     /**
27962      * Set the text alignment.
27963      *
27964      * @param textAlignment The text alignment to set. Should be one of
27965      *
27966      * {@link #TEXT_ALIGNMENT_INHERIT},
27967      * {@link #TEXT_ALIGNMENT_GRAVITY},
27968      * {@link #TEXT_ALIGNMENT_CENTER},
27969      * {@link #TEXT_ALIGNMENT_TEXT_START},
27970      * {@link #TEXT_ALIGNMENT_TEXT_END},
27971      * {@link #TEXT_ALIGNMENT_VIEW_START},
27972      * {@link #TEXT_ALIGNMENT_VIEW_END}
27973      *
27974      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
27975      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
27976      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
27977      *
27978      * @attr ref android.R.styleable#View_textAlignment
27979      */
setTextAlignment(@extAlignment int textAlignment)27980     public void setTextAlignment(@TextAlignment int textAlignment) {
27981         if (textAlignment != getRawTextAlignment()) {
27982             // Reset the current and resolved text alignment
27983             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
27984             resetResolvedTextAlignment();
27985             // Set the new text alignment
27986             mPrivateFlags2 |=
27987                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
27988             // Do resolution
27989             resolveTextAlignment();
27990             // Notify change
27991             onRtlPropertiesChanged(getLayoutDirection());
27992             // Refresh
27993             requestLayout();
27994             invalidate(true);
27995         }
27996     }
27997 
27998     /**
27999      * Return the resolved text alignment.
28000      *
28001      * @return the resolved text alignment. Returns one of:
28002      *
28003      * {@link #TEXT_ALIGNMENT_GRAVITY},
28004      * {@link #TEXT_ALIGNMENT_CENTER},
28005      * {@link #TEXT_ALIGNMENT_TEXT_START},
28006      * {@link #TEXT_ALIGNMENT_TEXT_END},
28007      * {@link #TEXT_ALIGNMENT_VIEW_START},
28008      * {@link #TEXT_ALIGNMENT_VIEW_END}
28009      *
28010      * @attr ref android.R.styleable#View_textAlignment
28011      */
28012     @ViewDebug.ExportedProperty(category = "text", mapping = {
28013             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
28014             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
28015             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
28016             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
28017             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
28018             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
28019             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
28020     })
28021     @InspectableProperty(enumMapping = {
28022             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
28023             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
28024             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
28025             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
28026             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
28027             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
28028     })
28029     @TextAlignment
getTextAlignment()28030     public int getTextAlignment() {
28031         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
28032                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
28033     }
28034 
28035     /**
28036      * Resolve the text alignment.
28037      *
28038      * @return true if resolution has been done, false otherwise.
28039      *
28040      * @hide
28041      */
resolveTextAlignment()28042     public boolean resolveTextAlignment() {
28043         // Reset any previous text alignment resolution
28044         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
28045 
28046         if (hasRtlSupport()) {
28047             // Set resolved text alignment flag depending on text alignment flag
28048             final int textAlignment = getRawTextAlignment();
28049             switch (textAlignment) {
28050                 case TEXT_ALIGNMENT_INHERIT:
28051                     // Check if we can resolve the text alignment
28052                     if (!canResolveTextAlignment()) {
28053                         // We cannot do the resolution if there is no parent so use the default
28054                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28055                         // Resolution will need to happen again later
28056                         return false;
28057                     }
28058 
28059                     // Parent has not yet resolved, so we still return the default
28060                     try {
28061                         if (!mParent.isTextAlignmentResolved()) {
28062                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28063                             // Resolution will need to happen again later
28064                             return false;
28065                         }
28066                     } catch (AbstractMethodError e) {
28067                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28068                                 " does not fully implement ViewParent", e);
28069                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
28070                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28071                         return true;
28072                     }
28073 
28074                     int parentResolvedTextAlignment;
28075                     try {
28076                         parentResolvedTextAlignment = mParent.getTextAlignment();
28077                     } catch (AbstractMethodError e) {
28078                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28079                                 " does not fully implement ViewParent", e);
28080                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
28081                     }
28082                     switch (parentResolvedTextAlignment) {
28083                         case TEXT_ALIGNMENT_GRAVITY:
28084                         case TEXT_ALIGNMENT_TEXT_START:
28085                         case TEXT_ALIGNMENT_TEXT_END:
28086                         case TEXT_ALIGNMENT_CENTER:
28087                         case TEXT_ALIGNMENT_VIEW_START:
28088                         case TEXT_ALIGNMENT_VIEW_END:
28089                             // Resolved text alignment is the same as the parent resolved
28090                             // text alignment
28091                             mPrivateFlags2 |=
28092                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
28093                             break;
28094                         default:
28095                             // Use default resolved text alignment
28096                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28097                     }
28098                     break;
28099                 case TEXT_ALIGNMENT_GRAVITY:
28100                 case TEXT_ALIGNMENT_TEXT_START:
28101                 case TEXT_ALIGNMENT_TEXT_END:
28102                 case TEXT_ALIGNMENT_CENTER:
28103                 case TEXT_ALIGNMENT_VIEW_START:
28104                 case TEXT_ALIGNMENT_VIEW_END:
28105                     // Resolved text alignment is the same as text alignment
28106                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
28107                     break;
28108                 default:
28109                     // Use default resolved text alignment
28110                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28111             }
28112         } else {
28113             // Use default resolved text alignment
28114             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28115         }
28116 
28117         // Set the resolved
28118         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
28119         return true;
28120     }
28121 
28122     /**
28123      * Check if text alignment resolution can be done.
28124      *
28125      * @return true if text alignment resolution can be done otherwise return false.
28126      */
canResolveTextAlignment()28127     public boolean canResolveTextAlignment() {
28128         switch (getRawTextAlignment()) {
28129             case TEXT_DIRECTION_INHERIT:
28130                 if (mParent != null) {
28131                     try {
28132                         return mParent.canResolveTextAlignment();
28133                     } catch (AbstractMethodError e) {
28134                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28135                                 " does not fully implement ViewParent", e);
28136                     }
28137                 }
28138                 return false;
28139 
28140             default:
28141                 return true;
28142         }
28143     }
28144 
28145     /**
28146      * Reset resolved text alignment. Text alignment will be resolved during a call to
28147      * {@link #onMeasure(int, int)}.
28148      *
28149      * @hide
28150      */
28151     @TestApi
resetResolvedTextAlignment()28152     public void resetResolvedTextAlignment() {
28153         // Reset any previous text alignment resolution
28154         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
28155         // Set to default
28156         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28157     }
28158 
28159     /**
28160      * @return true if text alignment is inherited.
28161      *
28162      * @hide
28163      */
isTextAlignmentInherited()28164     public boolean isTextAlignmentInherited() {
28165         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
28166     }
28167 
28168     /**
28169      * @return true if text alignment is resolved.
28170      */
isTextAlignmentResolved()28171     public boolean isTextAlignmentResolved() {
28172         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
28173     }
28174 
28175     /**
28176      * Generate a value suitable for use in {@link #setId(int)}.
28177      * This value will not collide with ID values generated at build time by aapt for R.id.
28178      *
28179      * @return a generated ID value
28180      */
generateViewId()28181     public static int generateViewId() {
28182         for (;;) {
28183             final int result = sNextGeneratedId.get();
28184             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
28185             int newValue = result + 1;
28186             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
28187             if (sNextGeneratedId.compareAndSet(result, newValue)) {
28188                 return result;
28189             }
28190         }
28191     }
28192 
isViewIdGenerated(int id)28193     private static boolean isViewIdGenerated(int id) {
28194         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
28195     }
28196 
28197     /**
28198      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
28199      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
28200      *                           a normal View or a ViewGroup with
28201      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
28202      * @hide
28203      */
captureTransitioningViews(List<View> transitioningViews)28204     public void captureTransitioningViews(List<View> transitioningViews) {
28205         if (getVisibility() == View.VISIBLE) {
28206             transitioningViews.add(this);
28207         }
28208     }
28209 
28210     /**
28211      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
28212      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
28213      * @hide
28214      */
findNamedViews(Map<String, View> namedElements)28215     public void findNamedViews(Map<String, View> namedElements) {
28216         if (getVisibility() == VISIBLE || mGhostView != null) {
28217             String transitionName = getTransitionName();
28218             if (transitionName != null) {
28219                 namedElements.put(transitionName, this);
28220             }
28221         }
28222     }
28223 
28224     /**
28225      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
28226      * The default implementation does not care the location or event types, but some subclasses
28227      * may use it (such as WebViews).
28228      * @param event The MotionEvent from a mouse
28229      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
28230      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
28231      * @see PointerIcon
28232      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)28233     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
28234         final float x = event.getX(pointerIndex);
28235         final float y = event.getY(pointerIndex);
28236         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
28237             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
28238         }
28239         return mPointerIcon;
28240     }
28241 
28242     /**
28243      * Set the pointer icon for the current view.
28244      * Passing {@code null} will restore the pointer icon to its default value.
28245      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
28246      */
setPointerIcon(PointerIcon pointerIcon)28247     public void setPointerIcon(PointerIcon pointerIcon) {
28248         mPointerIcon = pointerIcon;
28249         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
28250             return;
28251         }
28252         try {
28253             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
28254         } catch (RemoteException e) {
28255         }
28256     }
28257 
28258     /**
28259      * Gets the pointer icon for the current view.
28260      */
28261     @InspectableProperty
getPointerIcon()28262     public PointerIcon getPointerIcon() {
28263         return mPointerIcon;
28264     }
28265 
28266     /**
28267      * Checks pointer capture status.
28268      *
28269      * @return true if the view has pointer capture.
28270      * @see #requestPointerCapture()
28271      * @see #hasPointerCapture()
28272      */
hasPointerCapture()28273     public boolean hasPointerCapture() {
28274         final ViewRootImpl viewRootImpl = getViewRootImpl();
28275         if (viewRootImpl == null) {
28276             return false;
28277         }
28278         return viewRootImpl.hasPointerCapture();
28279     }
28280 
28281     /**
28282      * Requests pointer capture mode.
28283      * <p>
28284      * When the window has pointer capture, the mouse pointer icon will disappear and will not
28285      * change its position. Enabling pointer capture will change the behavior of input devices in
28286      * the following ways:
28287      * <ul>
28288      *     <li>Events from a mouse will be delivered with the source
28289      *     {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
28290      *     available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
28291      *
28292      *     <li>Events from a touchpad will be delivered with the source
28293      *     {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
28294      *     on the touchpad will be available through {@link MotionEvent#getX(int)} and
28295      *     {@link MotionEvent#getY(int)}, and their relative movements are stored in
28296      *     {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li>
28297      *
28298      *     <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
28299      * </ul>
28300      * <p>
28301      * Events captured through pointer capture will be dispatched to
28302      * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
28303      * {@link OnCapturedPointerListener} is set, and otherwise to
28304      * {@link #onCapturedPointerEvent(MotionEvent)}.
28305      * <p>
28306      * If the window already has pointer capture, this call does nothing.
28307      * <p>
28308      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
28309      * automatically when the window loses focus.
28310      *
28311      * @see #releasePointerCapture()
28312      * @see #hasPointerCapture()
28313      * @see #onPointerCaptureChange(boolean)
28314      */
requestPointerCapture()28315     public void requestPointerCapture() {
28316         final ViewRootImpl viewRootImpl = getViewRootImpl();
28317         if (viewRootImpl != null) {
28318             viewRootImpl.requestPointerCapture(true);
28319         }
28320     }
28321 
28322 
28323     /**
28324      * Releases the pointer capture.
28325      * <p>
28326      * If the window does not have pointer capture, this call will do nothing.
28327      * @see #requestPointerCapture()
28328      * @see #hasPointerCapture()
28329      * @see #onPointerCaptureChange(boolean)
28330      */
releasePointerCapture()28331     public void releasePointerCapture() {
28332         final ViewRootImpl viewRootImpl = getViewRootImpl();
28333         if (viewRootImpl != null) {
28334             viewRootImpl.requestPointerCapture(false);
28335         }
28336     }
28337 
28338     /**
28339      * Called when the window has just acquired or lost pointer capture.
28340      *
28341      * @param hasCapture True if the view now has pointerCapture, false otherwise.
28342      */
28343     @CallSuper
onPointerCaptureChange(boolean hasCapture)28344     public void onPointerCaptureChange(boolean hasCapture) {
28345     }
28346 
28347     /**
28348      * @see #onPointerCaptureChange
28349      */
dispatchPointerCaptureChanged(boolean hasCapture)28350     public void dispatchPointerCaptureChanged(boolean hasCapture) {
28351         onPointerCaptureChange(hasCapture);
28352     }
28353 
28354     /**
28355      * Implement this method to handle captured pointer events
28356      *
28357      * @param event The captured pointer event.
28358      * @return True if the event was handled, false otherwise.
28359      * @see #requestPointerCapture()
28360      */
onCapturedPointerEvent(MotionEvent event)28361     public boolean onCapturedPointerEvent(MotionEvent event) {
28362         return false;
28363     }
28364 
28365     /**
28366      * Interface definition for a callback to be invoked when a captured pointer event
28367      * is being dispatched this view. The callback will be invoked before the event is
28368      * given to the view.
28369      */
28370     public interface OnCapturedPointerListener {
28371         /**
28372          * Called when a captured pointer event is dispatched to a view.
28373          * @param view The view this event has been dispatched to.
28374          * @param event The captured event.
28375          * @return True if the listener has consumed the event, false otherwise.
28376          */
onCapturedPointer(View view, MotionEvent event)28377         boolean onCapturedPointer(View view, MotionEvent event);
28378     }
28379 
28380     /**
28381      * Set a listener to receive callbacks when the pointer capture state of a view changes.
28382      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
28383      */
setOnCapturedPointerListener(OnCapturedPointerListener l)28384     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
28385         getListenerInfo().mOnCapturedPointerListener = l;
28386     }
28387 
28388     // Properties
28389     //
28390     /**
28391      * A Property wrapper around the <code>alpha</code> functionality handled by the
28392      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
28393      */
28394     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
28395         @Override
28396         public void setValue(View object, float value) {
28397             object.setAlpha(value);
28398         }
28399 
28400         @Override
28401         public Float get(View object) {
28402             return object.getAlpha();
28403         }
28404     };
28405 
28406     /**
28407      * A Property wrapper around the <code>translationX</code> functionality handled by the
28408      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
28409      */
28410     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
28411         @Override
28412         public void setValue(View object, float value) {
28413             object.setTranslationX(value);
28414         }
28415 
28416                 @Override
28417         public Float get(View object) {
28418             return object.getTranslationX();
28419         }
28420     };
28421 
28422     /**
28423      * A Property wrapper around the <code>translationY</code> functionality handled by the
28424      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
28425      */
28426     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
28427         @Override
28428         public void setValue(View object, float value) {
28429             object.setTranslationY(value);
28430         }
28431 
28432         @Override
28433         public Float get(View object) {
28434             return object.getTranslationY();
28435         }
28436     };
28437 
28438     /**
28439      * A Property wrapper around the <code>translationZ</code> functionality handled by the
28440      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
28441      */
28442     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
28443         @Override
28444         public void setValue(View object, float value) {
28445             object.setTranslationZ(value);
28446         }
28447 
28448         @Override
28449         public Float get(View object) {
28450             return object.getTranslationZ();
28451         }
28452     };
28453 
28454     /**
28455      * A Property wrapper around the <code>x</code> functionality handled by the
28456      * {@link View#setX(float)} and {@link View#getX()} methods.
28457      */
28458     public static final Property<View, Float> X = new FloatProperty<View>("x") {
28459         @Override
28460         public void setValue(View object, float value) {
28461             object.setX(value);
28462         }
28463 
28464         @Override
28465         public Float get(View object) {
28466             return object.getX();
28467         }
28468     };
28469 
28470     /**
28471      * A Property wrapper around the <code>y</code> functionality handled by the
28472      * {@link View#setY(float)} and {@link View#getY()} methods.
28473      */
28474     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
28475         @Override
28476         public void setValue(View object, float value) {
28477             object.setY(value);
28478         }
28479 
28480         @Override
28481         public Float get(View object) {
28482             return object.getY();
28483         }
28484     };
28485 
28486     /**
28487      * A Property wrapper around the <code>z</code> functionality handled by the
28488      * {@link View#setZ(float)} and {@link View#getZ()} methods.
28489      */
28490     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
28491         @Override
28492         public void setValue(View object, float value) {
28493             object.setZ(value);
28494         }
28495 
28496         @Override
28497         public Float get(View object) {
28498             return object.getZ();
28499         }
28500     };
28501 
28502     /**
28503      * A Property wrapper around the <code>rotation</code> functionality handled by the
28504      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
28505      */
28506     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
28507         @Override
28508         public void setValue(View object, float value) {
28509             object.setRotation(value);
28510         }
28511 
28512         @Override
28513         public Float get(View object) {
28514             return object.getRotation();
28515         }
28516     };
28517 
28518     /**
28519      * A Property wrapper around the <code>rotationX</code> functionality handled by the
28520      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
28521      */
28522     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
28523         @Override
28524         public void setValue(View object, float value) {
28525             object.setRotationX(value);
28526         }
28527 
28528         @Override
28529         public Float get(View object) {
28530             return object.getRotationX();
28531         }
28532     };
28533 
28534     /**
28535      * A Property wrapper around the <code>rotationY</code> functionality handled by the
28536      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
28537      */
28538     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
28539         @Override
28540         public void setValue(View object, float value) {
28541             object.setRotationY(value);
28542         }
28543 
28544         @Override
28545         public Float get(View object) {
28546             return object.getRotationY();
28547         }
28548     };
28549 
28550     /**
28551      * A Property wrapper around the <code>scaleX</code> functionality handled by the
28552      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
28553      */
28554     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
28555         @Override
28556         public void setValue(View object, float value) {
28557             object.setScaleX(value);
28558         }
28559 
28560         @Override
28561         public Float get(View object) {
28562             return object.getScaleX();
28563         }
28564     };
28565 
28566     /**
28567      * A Property wrapper around the <code>scaleY</code> functionality handled by the
28568      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
28569      */
28570     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
28571         @Override
28572         public void setValue(View object, float value) {
28573             object.setScaleY(value);
28574         }
28575 
28576         @Override
28577         public Float get(View object) {
28578             return object.getScaleY();
28579         }
28580     };
28581 
28582     /**
28583      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
28584      * Each MeasureSpec represents a requirement for either the width or the height.
28585      * A MeasureSpec is comprised of a size and a mode. There are three possible
28586      * modes:
28587      * <dl>
28588      * <dt>UNSPECIFIED</dt>
28589      * <dd>
28590      * The parent has not imposed any constraint on the child. It can be whatever size
28591      * it wants.
28592      * </dd>
28593      *
28594      * <dt>EXACTLY</dt>
28595      * <dd>
28596      * The parent has determined an exact size for the child. The child is going to be
28597      * given those bounds regardless of how big it wants to be.
28598      * </dd>
28599      *
28600      * <dt>AT_MOST</dt>
28601      * <dd>
28602      * The child can be as large as it wants up to the specified size.
28603      * </dd>
28604      * </dl>
28605      *
28606      * MeasureSpecs are implemented as ints to reduce object allocation. This class
28607      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
28608      */
28609     public static class MeasureSpec {
28610         private static final int MODE_SHIFT = 30;
28611         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
28612 
28613         /** @hide */
28614         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
28615         @Retention(RetentionPolicy.SOURCE)
28616         public @interface MeasureSpecMode {}
28617 
28618         /**
28619          * Measure specification mode: The parent has not imposed any constraint
28620          * on the child. It can be whatever size it wants.
28621          */
28622         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
28623 
28624         /**
28625          * Measure specification mode: The parent has determined an exact size
28626          * for the child. The child is going to be given those bounds regardless
28627          * of how big it wants to be.
28628          */
28629         public static final int EXACTLY     = 1 << MODE_SHIFT;
28630 
28631         /**
28632          * Measure specification mode: The child can be as large as it wants up
28633          * to the specified size.
28634          */
28635         public static final int AT_MOST     = 2 << MODE_SHIFT;
28636 
28637         /**
28638          * Creates a measure specification based on the supplied size and mode.
28639          *
28640          * The mode must always be one of the following:
28641          * <ul>
28642          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
28643          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
28644          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
28645          * </ul>
28646          *
28647          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
28648          * implementation was such that the order of arguments did not matter
28649          * and overflow in either value could impact the resulting MeasureSpec.
28650          * {@link android.widget.RelativeLayout} was affected by this bug.
28651          * Apps targeting API levels greater than 17 will get the fixed, more strict
28652          * behavior.</p>
28653          *
28654          * @param size the size of the measure specification
28655          * @param mode the mode of the measure specification
28656          * @return the measure specification based on size and mode
28657          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)28658         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
28659                                           @MeasureSpecMode int mode) {
28660             if (sUseBrokenMakeMeasureSpec) {
28661                 return size + mode;
28662             } else {
28663                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
28664             }
28665         }
28666 
28667         /**
28668          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
28669          * will automatically get a size of 0. Older apps expect this.
28670          *
28671          * @hide internal use only for compatibility with system widgets and older apps
28672          */
28673         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)28674         public static int makeSafeMeasureSpec(int size, int mode) {
28675             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
28676                 return 0;
28677             }
28678             return makeMeasureSpec(size, mode);
28679         }
28680 
28681         /**
28682          * Extracts the mode from the supplied measure specification.
28683          *
28684          * @param measureSpec the measure specification to extract the mode from
28685          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
28686          *         {@link android.view.View.MeasureSpec#AT_MOST} or
28687          *         {@link android.view.View.MeasureSpec#EXACTLY}
28688          */
28689         @MeasureSpecMode
getMode(int measureSpec)28690         public static int getMode(int measureSpec) {
28691             //noinspection ResourceType
28692             return (measureSpec & MODE_MASK);
28693         }
28694 
28695         /**
28696          * Extracts the size from the supplied measure specification.
28697          *
28698          * @param measureSpec the measure specification to extract the size from
28699          * @return the size in pixels defined in the supplied measure specification
28700          */
getSize(int measureSpec)28701         public static int getSize(int measureSpec) {
28702             return (measureSpec & ~MODE_MASK);
28703         }
28704 
adjust(int measureSpec, int delta)28705         static int adjust(int measureSpec, int delta) {
28706             final int mode = getMode(measureSpec);
28707             int size = getSize(measureSpec);
28708             if (mode == UNSPECIFIED) {
28709                 // No need to adjust size for UNSPECIFIED mode.
28710                 return makeMeasureSpec(size, UNSPECIFIED);
28711             }
28712             size += delta;
28713             if (size < 0) {
28714                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
28715                         ") spec: " + toString(measureSpec) + " delta: " + delta);
28716                 size = 0;
28717             }
28718             return makeMeasureSpec(size, mode);
28719         }
28720 
28721         /**
28722          * Returns a String representation of the specified measure
28723          * specification.
28724          *
28725          * @param measureSpec the measure specification to convert to a String
28726          * @return a String with the following format: "MeasureSpec: MODE SIZE"
28727          */
toString(int measureSpec)28728         public static String toString(int measureSpec) {
28729             int mode = getMode(measureSpec);
28730             int size = getSize(measureSpec);
28731 
28732             StringBuilder sb = new StringBuilder("MeasureSpec: ");
28733 
28734             if (mode == UNSPECIFIED)
28735                 sb.append("UNSPECIFIED ");
28736             else if (mode == EXACTLY)
28737                 sb.append("EXACTLY ");
28738             else if (mode == AT_MOST)
28739                 sb.append("AT_MOST ");
28740             else
28741                 sb.append(mode).append(" ");
28742 
28743             sb.append(size);
28744             return sb.toString();
28745         }
28746     }
28747 
28748     private final class CheckForLongPress implements Runnable {
28749         private int mOriginalWindowAttachCount;
28750         private float mX;
28751         private float mY;
28752         private boolean mOriginalPressedState;
28753         /**
28754          * The classification of the long click being checked: one of the
28755          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
28756          */
28757         private int mClassification;
28758 
28759         @UnsupportedAppUsage
CheckForLongPress()28760         private CheckForLongPress() {
28761         }
28762 
28763         @Override
run()28764         public void run() {
28765             if ((mOriginalPressedState == isPressed()) && (mParent != null)
28766                     && mOriginalWindowAttachCount == mWindowAttachCount) {
28767                 recordGestureClassification(mClassification);
28768                 if (performLongClick(mX, mY)) {
28769                     mHasPerformedLongPress = true;
28770                 }
28771             }
28772         }
28773 
setAnchor(float x, float y)28774         public void setAnchor(float x, float y) {
28775             mX = x;
28776             mY = y;
28777         }
28778 
rememberWindowAttachCount()28779         public void rememberWindowAttachCount() {
28780             mOriginalWindowAttachCount = mWindowAttachCount;
28781         }
28782 
rememberPressedState()28783         public void rememberPressedState() {
28784             mOriginalPressedState = isPressed();
28785         }
28786 
setClassification(int classification)28787         public void setClassification(int classification) {
28788             mClassification = classification;
28789         }
28790     }
28791 
28792     private final class CheckForTap implements Runnable {
28793         public float x;
28794         public float y;
28795 
28796         @Override
run()28797         public void run() {
28798             mPrivateFlags &= ~PFLAG_PREPRESSED;
28799             setPressed(true, x, y);
28800             final long delay =
28801                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
28802             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
28803         }
28804     }
28805 
28806     private final class PerformClick implements Runnable {
28807         @Override
run()28808         public void run() {
28809             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
28810             performClickInternal();
28811         }
28812     }
28813 
28814     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)28815     private void recordGestureClassification(int classification) {
28816         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
28817             return;
28818         }
28819         // To avoid negatively impacting View performance, the latency and displacement metrics
28820         // are omitted.
28821         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
28822                 classification);
28823     }
28824 
28825     /**
28826      * This method returns a ViewPropertyAnimator object, which can be used to animate
28827      * specific properties on this View.
28828      *
28829      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
28830      */
animate()28831     public ViewPropertyAnimator animate() {
28832         if (mAnimator == null) {
28833             mAnimator = new ViewPropertyAnimator(this);
28834         }
28835         return mAnimator;
28836     }
28837 
28838     /**
28839      * Sets the name of the View to be used to identify Views in Transitions.
28840      * Names should be unique in the View hierarchy.
28841      *
28842      * @param transitionName The name of the View to uniquely identify it for Transitions.
28843      */
setTransitionName(String transitionName)28844     public final void setTransitionName(String transitionName) {
28845         mTransitionName = transitionName;
28846     }
28847 
28848     /**
28849      * Returns the name of the View to be used to identify Views in Transitions.
28850      * Names should be unique in the View hierarchy.
28851      *
28852      * <p>This returns null if the View has not been given a name.</p>
28853      *
28854      * @return The name used of the View to be used to identify Views in Transitions or null
28855      * if no name has been given.
28856      */
28857     @ViewDebug.ExportedProperty
28858     @InspectableProperty
getTransitionName()28859     public String getTransitionName() {
28860         return mTransitionName;
28861     }
28862 
28863     /**
28864      * @hide
28865      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)28866     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
28867         // Do nothing.
28868     }
28869 
28870     /**
28871      * Interface definition for a callback to be invoked when a hardware key event is
28872      * dispatched to this view. The callback will be invoked before the key event is
28873      * given to the view. This is only useful for hardware keyboards; a software input
28874      * method has no obligation to trigger this listener.
28875      */
28876     public interface OnKeyListener {
28877         /**
28878          * Called when a hardware key is dispatched to a view. This allows listeners to
28879          * get a chance to respond before the target view.
28880          * <p>Key presses in software keyboards will generally NOT trigger this method,
28881          * although some may elect to do so in some situations. Do not assume a
28882          * software input method has to be key-based; even if it is, it may use key presses
28883          * in a different way than you expect, so there is no way to reliably catch soft
28884          * input key presses.
28885          *
28886          * @param v The view the key has been dispatched to.
28887          * @param keyCode The code for the physical key that was pressed
28888          * @param event The KeyEvent object containing full information about
28889          *        the event.
28890          * @return True if the listener has consumed the event, false otherwise.
28891          */
onKey(View v, int keyCode, KeyEvent event)28892         boolean onKey(View v, int keyCode, KeyEvent event);
28893     }
28894 
28895     /**
28896      * Interface definition for a callback to be invoked when a hardware key event hasn't
28897      * been handled by the view hierarchy.
28898      */
28899     public interface OnUnhandledKeyEventListener {
28900         /**
28901          * Called when a hardware key is dispatched to a view after being unhandled during normal
28902          * {@link KeyEvent} dispatch.
28903          *
28904          * @param v The view the key has been dispatched to.
28905          * @param event The KeyEvent object containing information about the event.
28906          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
28907          */
onUnhandledKeyEvent(View v, KeyEvent event)28908         boolean onUnhandledKeyEvent(View v, KeyEvent event);
28909     }
28910 
28911     /**
28912      * Interface definition for a callback to be invoked when a touch event is
28913      * dispatched to this view. The callback will be invoked before the touch
28914      * event is given to the view.
28915      */
28916     public interface OnTouchListener {
28917         /**
28918          * Called when a touch event is dispatched to a view. This allows listeners to
28919          * get a chance to respond before the target view.
28920          *
28921          * @param v The view the touch event has been dispatched to.
28922          * @param event The MotionEvent object containing full information about
28923          *        the event.
28924          * @return True if the listener has consumed the event, false otherwise.
28925          */
onTouch(View v, MotionEvent event)28926         boolean onTouch(View v, MotionEvent event);
28927     }
28928 
28929     /**
28930      * Interface definition for a callback to be invoked when a hover event is
28931      * dispatched to this view. The callback will be invoked before the hover
28932      * event is given to the view.
28933      */
28934     public interface OnHoverListener {
28935         /**
28936          * Called when a hover event is dispatched to a view. This allows listeners to
28937          * get a chance to respond before the target view.
28938          *
28939          * @param v The view the hover event has been dispatched to.
28940          * @param event The MotionEvent object containing full information about
28941          *        the event.
28942          * @return True if the listener has consumed the event, false otherwise.
28943          */
onHover(View v, MotionEvent event)28944         boolean onHover(View v, MotionEvent event);
28945     }
28946 
28947     /**
28948      * Interface definition for a callback to be invoked when a generic motion event is
28949      * dispatched to this view. The callback will be invoked before the generic motion
28950      * event is given to the view.
28951      */
28952     public interface OnGenericMotionListener {
28953         /**
28954          * Called when a generic motion event is dispatched to a view. This allows listeners to
28955          * get a chance to respond before the target view.
28956          *
28957          * @param v The view the generic motion event has been dispatched to.
28958          * @param event The MotionEvent object containing full information about
28959          *        the event.
28960          * @return True if the listener has consumed the event, false otherwise.
28961          */
onGenericMotion(View v, MotionEvent event)28962         boolean onGenericMotion(View v, MotionEvent event);
28963     }
28964 
28965     /**
28966      * Interface definition for a callback to be invoked when a view has been clicked and held.
28967      */
28968     public interface OnLongClickListener {
28969         /**
28970          * Called when a view has been clicked and held.
28971          *
28972          * @param v The view that was clicked and held.
28973          *
28974          * @return true if the callback consumed the long click, false otherwise.
28975          */
onLongClick(View v)28976         boolean onLongClick(View v);
28977     }
28978 
28979     /**
28980      * Interface definition for a callback to be invoked when a drag is being dispatched
28981      * to this view.  The callback will be invoked before the hosting view's own
28982      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
28983      * onDrag(event) behavior, it should return 'false' from this callback.
28984      *
28985      * <div class="special reference">
28986      * <h3>Developer Guides</h3>
28987      * <p>For a guide to implementing drag and drop features, read the
28988      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
28989      * </div>
28990      */
28991     public interface OnDragListener {
28992         /**
28993          * Called when a drag event is dispatched to a view. This allows listeners
28994          * to get a chance to override base View behavior.
28995          *
28996          * @param v The View that received the drag event.
28997          * @param event The {@link android.view.DragEvent} object for the drag event.
28998          * @return {@code true} if the drag event was handled successfully, or {@code false}
28999          * if the drag event was not handled. Note that {@code false} will trigger the View
29000          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
29001          */
onDrag(View v, DragEvent event)29002         boolean onDrag(View v, DragEvent event);
29003     }
29004 
29005     /**
29006      * Interface definition for a callback to be invoked when the focus state of
29007      * a view changed.
29008      */
29009     public interface OnFocusChangeListener {
29010         /**
29011          * Called when the focus state of a view has changed.
29012          *
29013          * @param v The view whose state has changed.
29014          * @param hasFocus The new focus state of v.
29015          */
onFocusChange(View v, boolean hasFocus)29016         void onFocusChange(View v, boolean hasFocus);
29017     }
29018 
29019     /**
29020      * Interface definition for a callback to be invoked when a view is clicked.
29021      */
29022     public interface OnClickListener {
29023         /**
29024          * Called when a view has been clicked.
29025          *
29026          * @param v The view that was clicked.
29027          */
onClick(View v)29028         void onClick(View v);
29029     }
29030 
29031     /**
29032      * Interface definition for a callback to be invoked when a view is context clicked.
29033      */
29034     public interface OnContextClickListener {
29035         /**
29036          * Called when a view is context clicked.
29037          *
29038          * @param v The view that has been context clicked.
29039          * @return true if the callback consumed the context click, false otherwise.
29040          */
onContextClick(View v)29041         boolean onContextClick(View v);
29042     }
29043 
29044     /**
29045      * Interface definition for a callback to be invoked when the context menu
29046      * for this view is being built.
29047      */
29048     public interface OnCreateContextMenuListener {
29049         /**
29050          * Called when the context menu for this view is being built. It is not
29051          * safe to hold onto the menu after this method returns.
29052          *
29053          * @param menu The context menu that is being built
29054          * @param v The view for which the context menu is being built
29055          * @param menuInfo Extra information about the item for which the
29056          *            context menu should be shown. This information will vary
29057          *            depending on the class of v.
29058          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)29059         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
29060     }
29061 
29062     /**
29063      * Interface definition for a callback to be invoked when the status bar changes
29064      * visibility.  This reports <strong>global</strong> changes to the system UI
29065      * state, not what the application is requesting.
29066      *
29067      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
29068      *
29069      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
29070      * by setting a {@link OnApplyWindowInsetsListener} on this view.
29071      */
29072     @Deprecated
29073     public interface OnSystemUiVisibilityChangeListener {
29074         /**
29075          * Called when the status bar changes visibility because of a call to
29076          * {@link View#setSystemUiVisibility(int)}.
29077          *
29078          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
29079          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
29080          * This tells you the <strong>global</strong> state of these UI visibility
29081          * flags, not what your app is currently applying.
29082          */
onSystemUiVisibilityChange(int visibility)29083         public void onSystemUiVisibilityChange(int visibility);
29084     }
29085 
29086     /**
29087      * Interface definition for a callback to be invoked when this view is attached
29088      * or detached from its window.
29089      */
29090     public interface OnAttachStateChangeListener {
29091         /**
29092          * Called when the view is attached to a window.
29093          * @param v The view that was attached
29094          */
onViewAttachedToWindow(View v)29095         public void onViewAttachedToWindow(View v);
29096         /**
29097          * Called when the view is detached from a window.
29098          * @param v The view that was detached
29099          */
onViewDetachedFromWindow(View v)29100         public void onViewDetachedFromWindow(View v);
29101     }
29102 
29103     /**
29104      * Listener for applying window insets on a view in a custom way.
29105      *
29106      * <p>Apps may choose to implement this interface if they want to apply custom policy
29107      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
29108      * is set, its
29109      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
29110      * method will be called instead of the View's own
29111      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
29112      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
29113      * the View's normal behavior as part of its own.</p>
29114      */
29115     public interface OnApplyWindowInsetsListener {
29116         /**
29117          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
29118          * on a View, this listener method will be called instead of the view's own
29119          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
29120          *
29121          * @param v The view applying window insets
29122          * @param insets The insets to apply
29123          * @return The insets supplied, minus any insets that were consumed
29124          */
onApplyWindowInsets(View v, WindowInsets insets)29125         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
29126     }
29127 
29128     private final class UnsetPressedState implements Runnable {
29129         @Override
run()29130         public void run() {
29131             setPressed(false);
29132         }
29133     }
29134 
29135     /**
29136      * When a view becomes invisible checks if autofill considers the view invisible too. This
29137      * happens after the regular removal operation to make sure the operation is finished by the
29138      * time this is called.
29139      */
29140     private static class VisibilityChangeForAutofillHandler extends Handler {
29141         private final AutofillManager mAfm;
29142         private final View mView;
29143 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)29144         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
29145                 @NonNull View view) {
29146             mAfm = afm;
29147             mView = view;
29148         }
29149 
29150         @Override
handleMessage(Message msg)29151         public void handleMessage(Message msg) {
29152             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
29153         }
29154     }
29155 
29156     /**
29157      * Base class for derived classes that want to save and restore their own
29158      * state in {@link android.view.View#onSaveInstanceState()}.
29159      */
29160     public static class BaseSavedState extends AbsSavedState {
29161         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
29162         static final int IS_AUTOFILLED = 0b10;
29163         static final int AUTOFILL_ID = 0b100;
29164 
29165         // Flags that describe what data in this state is valid
29166         int mSavedData;
29167         String mStartActivityRequestWhoSaved;
29168         boolean mIsAutofilled;
29169         boolean mHideHighlight;
29170         int mAutofillViewId;
29171 
29172         /**
29173          * Constructor used when reading from a parcel. Reads the state of the superclass.
29174          *
29175          * @param source parcel to read from
29176          */
BaseSavedState(Parcel source)29177         public BaseSavedState(Parcel source) {
29178             this(source, null);
29179         }
29180 
29181         /**
29182          * Constructor used when reading from a parcel using a given class loader.
29183          * Reads the state of the superclass.
29184          *
29185          * @param source parcel to read from
29186          * @param loader ClassLoader to use for reading
29187          */
BaseSavedState(Parcel source, ClassLoader loader)29188         public BaseSavedState(Parcel source, ClassLoader loader) {
29189             super(source, loader);
29190             mSavedData = source.readInt();
29191             mStartActivityRequestWhoSaved = source.readString();
29192             mIsAutofilled = source.readBoolean();
29193             mHideHighlight = source.readBoolean();
29194             mAutofillViewId = source.readInt();
29195         }
29196 
29197         /**
29198          * Constructor called by derived classes when creating their SavedState objects
29199          *
29200          * @param superState The state of the superclass of this view
29201          */
BaseSavedState(Parcelable superState)29202         public BaseSavedState(Parcelable superState) {
29203             super(superState);
29204         }
29205 
29206         @Override
writeToParcel(Parcel out, int flags)29207         public void writeToParcel(Parcel out, int flags) {
29208             super.writeToParcel(out, flags);
29209 
29210             out.writeInt(mSavedData);
29211             out.writeString(mStartActivityRequestWhoSaved);
29212             out.writeBoolean(mIsAutofilled);
29213             out.writeBoolean(mHideHighlight);
29214             out.writeInt(mAutofillViewId);
29215         }
29216 
29217         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
29218                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
29219             @Override
29220             public BaseSavedState createFromParcel(Parcel in) {
29221                 return new BaseSavedState(in);
29222             }
29223 
29224             @Override
29225             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
29226                 return new BaseSavedState(in, loader);
29227             }
29228 
29229             @Override
29230             public BaseSavedState[] newArray(int size) {
29231                 return new BaseSavedState[size];
29232             }
29233         };
29234     }
29235 
29236     /**
29237      * A set of information given to a view when it is attached to its parent
29238      * window.
29239      */
29240     final static class AttachInfo {
29241 
29242         interface Callbacks {
playSoundEffect(int effectId)29243             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)29244             boolean performHapticFeedback(int effectId, boolean always);
29245         }
29246 
29247         /**
29248          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
29249          * to a Handler. This class contains the target (View) to invalidate and
29250          * the coordinates of the dirty rectangle.
29251          *
29252          * For performance purposes, this class also implements a pool of up to
29253          * POOL_LIMIT objects that get reused. This reduces memory allocations
29254          * whenever possible.
29255          */
29256         static class InvalidateInfo {
29257 
29258             @UnsupportedAppUsage
InvalidateInfo()29259             InvalidateInfo() {
29260             }
29261 
29262             private static final int POOL_LIMIT = 10;
29263 
29264             private static final SynchronizedPool<InvalidateInfo> sPool =
29265                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
29266 
29267             @UnsupportedAppUsage
29268             View target;
29269 
29270             @UnsupportedAppUsage
29271             int left;
29272             @UnsupportedAppUsage
29273             int top;
29274             @UnsupportedAppUsage
29275             int right;
29276             @UnsupportedAppUsage
29277             int bottom;
29278 
obtain()29279             public static InvalidateInfo obtain() {
29280                 InvalidateInfo instance = sPool.acquire();
29281                 return (instance != null) ? instance : new InvalidateInfo();
29282             }
29283 
recycle()29284             public void recycle() {
29285                 target = null;
29286                 sPool.release(this);
29287             }
29288         }
29289 
29290         @UnsupportedAppUsage
29291         final IWindowSession mSession;
29292 
29293         @UnsupportedAppUsage
29294         final IWindow mWindow;
29295 
29296         final IBinder mWindowToken;
29297 
29298         Display mDisplay;
29299 
29300         final Callbacks mRootCallbacks;
29301 
29302         IWindowId mIWindowId;
29303         WindowId mWindowId;
29304 
29305         /**
29306          * The top view of the hierarchy.
29307          */
29308         View mRootView;
29309 
29310         IBinder mPanelParentWindowToken;
29311 
29312         boolean mHardwareAccelerated;
29313         boolean mHardwareAccelerationRequested;
29314         ThreadedRenderer mThreadedRenderer;
29315         List<RenderNode> mPendingAnimatingRenderNodes;
29316 
29317         /**
29318          * The state of the display to which the window is attached, as reported
29319          * by {@link Display#getState()}.  Note that the display state constants
29320          * declared by {@link Display} do not exactly line up with the screen state
29321          * constants declared by {@link View} (there are more display states than
29322          * screen states).
29323          */
29324         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
29325         int mDisplayState = Display.STATE_UNKNOWN;
29326 
29327         /**
29328          * Scale factor used by the compatibility mode
29329          */
29330         @UnsupportedAppUsage
29331         float mApplicationScale;
29332 
29333         /**
29334          * Indicates whether the application is in compatibility mode
29335          */
29336         @UnsupportedAppUsage
29337         boolean mScalingRequired;
29338 
29339         /**
29340          * Left position of this view's window
29341          */
29342         int mWindowLeft;
29343 
29344         /**
29345          * Top position of this view's window
29346          */
29347         int mWindowTop;
29348 
29349         /**
29350          * Indicates whether views need to use 32-bit drawing caches
29351          */
29352         boolean mUse32BitDrawingCache;
29353 
29354         /**
29355          * For windows that are full-screen but using insets to layout inside
29356          * of the screen decorations, these are the current insets for the
29357          * content of the window.
29358          */
29359         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
29360                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
29361         final Rect mContentInsets = new Rect();
29362 
29363         /**
29364          * For windows that are full-screen but using insets to layout inside
29365          * of the screen decorations, these are the current insets for the
29366          * actual visible parts of the window.
29367          */
29368         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
29369                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
29370         final Rect mVisibleInsets = new Rect();
29371 
29372         /**
29373          * For windows that are full-screen but using insets to layout inside
29374          * of the screen decorations, these are the current insets for the
29375          * stable system windows.
29376          */
29377         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
29378                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
29379         final Rect mStableInsets = new Rect();
29380 
29381         /**
29382          * Current caption insets to the display coordinate.
29383          */
29384         final Rect mCaptionInsets = new Rect();
29385 
29386         /**
29387          * In multi-window we force show the system bars. Because we don't want that the surface
29388          * size changes in this mode, we instead have a flag whether the system bars sizes should
29389          * always be consumed, so the app is treated like there are no virtual system bars at all.
29390          */
29391         boolean mAlwaysConsumeSystemBars;
29392 
29393         /**
29394          * The internal insets given by this window.  This value is
29395          * supplied by the client (through
29396          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
29397          * be given to the window manager when changed to be used in laying
29398          * out windows behind it.
29399          */
29400         @UnsupportedAppUsage
29401         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
29402                 = new ViewTreeObserver.InternalInsetsInfo();
29403 
29404         /**
29405          * Set to true when mGivenInternalInsets is non-empty.
29406          */
29407         boolean mHasNonEmptyGivenInternalInsets;
29408 
29409         /**
29410          * All views in the window's hierarchy that serve as scroll containers,
29411          * used to determine if the window can be resized or must be panned
29412          * to adjust for a soft input area.
29413          */
29414         @UnsupportedAppUsage
29415         final ArrayList<View> mScrollContainers = new ArrayList<View>();
29416 
29417         @UnsupportedAppUsage
29418         final KeyEvent.DispatcherState mKeyDispatchState
29419                 = new KeyEvent.DispatcherState();
29420 
29421         /**
29422          * Indicates whether the view's window currently has the focus.
29423          */
29424         @UnsupportedAppUsage
29425         boolean mHasWindowFocus;
29426 
29427         /**
29428          * The current visibility of the window.
29429          */
29430         int mWindowVisibility;
29431 
29432         /**
29433          * Indicates the time at which drawing started to occur.
29434          */
29435         @UnsupportedAppUsage
29436         long mDrawingTime;
29437 
29438         /**
29439          * Indicates whether the view's window is currently in touch mode.
29440          */
29441         @UnsupportedAppUsage
29442         boolean mInTouchMode;
29443 
29444         /**
29445          * Indicates whether the view has requested unbuffered input dispatching for the current
29446          * event stream.
29447          */
29448         boolean mUnbufferedDispatchRequested;
29449 
29450         /**
29451          * Indicates that ViewAncestor should trigger a global layout change
29452          * the next time it performs a traversal
29453          */
29454         @UnsupportedAppUsage
29455         boolean mRecomputeGlobalAttributes;
29456 
29457         /**
29458          * Always report new attributes at next traversal.
29459          */
29460         boolean mForceReportNewAttributes;
29461 
29462         /**
29463          * Set during a traveral if any views want to keep the screen on.
29464          */
29465         @UnsupportedAppUsage
29466         boolean mKeepScreenOn;
29467 
29468         /**
29469          * Set during a traveral if the light center needs to be updated.
29470          */
29471         boolean mNeedsUpdateLightCenter;
29472 
29473         /**
29474          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
29475          */
29476         int mSystemUiVisibility;
29477 
29478         /**
29479          * Hack to force certain system UI visibility flags to be cleared.
29480          */
29481         int mDisabledSystemUiVisibility;
29482 
29483         /**
29484          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
29485          * attached.
29486          */
29487         boolean mHasSystemUiListeners;
29488 
29489         /**
29490          * Set if the visibility of any views has changed.
29491          */
29492         @UnsupportedAppUsage
29493         boolean mViewVisibilityChanged;
29494 
29495         /**
29496          * Set to true if a view has been scrolled.
29497          */
29498         @UnsupportedAppUsage
29499         boolean mViewScrollChanged;
29500 
29501         /**
29502          * Set to true if a pointer event is currently being handled.
29503          */
29504         boolean mHandlingPointerEvent;
29505 
29506         /**
29507          * The offset of this view's window when it's on an embedded display that is re-parented
29508          * to another window.
29509          */
29510         final Point mLocationInParentDisplay = new Point();
29511 
29512         /**
29513          * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is
29514          * embedded within a SurfaceView.
29515          */
29516         Matrix mScreenMatrixInEmbeddedHierarchy;
29517 
29518         /**
29519          * Global to the view hierarchy used as a temporary for dealing with
29520          * x/y points in the transparent region computations.
29521          */
29522         final int[] mTransparentLocation = new int[2];
29523 
29524         /**
29525          * Global to the view hierarchy used as a temporary for dealing with
29526          * x/y points in the ViewGroup.invalidateChild implementation.
29527          */
29528         final int[] mInvalidateChildLocation = new int[2];
29529 
29530         /**
29531          * Global to the view hierarchy used as a temporary for dealing with
29532          * computing absolute on-screen location.
29533          */
29534         final int[] mTmpLocation = new int[2];
29535 
29536         /**
29537          * Global to the view hierarchy used as a temporary for dealing with
29538          * x/y location when view is transformed.
29539          */
29540         final float[] mTmpTransformLocation = new float[2];
29541 
29542         /**
29543          * The view tree observer used to dispatch global events like
29544          * layout, pre-draw, touch mode change, etc.
29545          */
29546         @UnsupportedAppUsage
29547         final ViewTreeObserver mTreeObserver;
29548 
29549         /**
29550          * A Canvas used by the view hierarchy to perform bitmap caching.
29551          */
29552         Canvas mCanvas;
29553 
29554         /**
29555          * The view root impl.
29556          */
29557         final ViewRootImpl mViewRootImpl;
29558 
29559         /**
29560          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
29561          * handler can be used to pump events in the UI events queue.
29562          */
29563         @UnsupportedAppUsage
29564         final Handler mHandler;
29565 
29566         /**
29567          * Temporary for use in computing invalidate rectangles while
29568          * calling up the hierarchy.
29569          */
29570         final Rect mTmpInvalRect = new Rect();
29571 
29572         /**
29573          * Temporary for use in computing hit areas with transformed views
29574          */
29575         final RectF mTmpTransformRect = new RectF();
29576 
29577         /**
29578          * Temporary for use in computing hit areas with transformed views
29579          */
29580         final RectF mTmpTransformRect1 = new RectF();
29581 
29582         /**
29583          * Temporary list of rectanges.
29584          */
29585         final List<RectF> mTmpRectList = new ArrayList<>();
29586 
29587         /**
29588          * Temporary for use in transforming invalidation rect
29589          */
29590         final Matrix mTmpMatrix = new Matrix();
29591 
29592         /**
29593          * Temporary for use in transforming invalidation rect
29594          */
29595         final Transformation mTmpTransformation = new Transformation();
29596 
29597         /**
29598          * Temporary for use in querying outlines from OutlineProviders
29599          */
29600         final Outline mTmpOutline = new Outline();
29601 
29602         /**
29603          * Temporary list for use in collecting focusable descendents of a view.
29604          */
29605         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
29606 
29607         /**
29608          * The id of the window for accessibility purposes.
29609          */
29610         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
29611 
29612         /**
29613          * Flags related to accessibility processing.
29614          *
29615          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
29616          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
29617          */
29618         int mAccessibilityFetchFlags;
29619 
29620         /**
29621          * The drawable for highlighting accessibility focus.
29622          */
29623         Drawable mAccessibilityFocusDrawable;
29624 
29625         /**
29626          * The drawable for highlighting autofilled views.
29627          *
29628          * @see #isAutofilled()
29629          */
29630         Drawable mAutofilledDrawable;
29631 
29632         /**
29633          * Show where the margins, bounds and layout bounds are for each view.
29634          */
29635         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
29636 
29637         /**
29638          * Point used to compute visible regions.
29639          */
29640         final Point mPoint = new Point();
29641 
29642         /**
29643          * Used to track which View originated a requestLayout() call, used when
29644          * requestLayout() is called during layout.
29645          */
29646         View mViewRequestingLayout;
29647 
29648         /**
29649          * Used to track the identity of the current drag operation.
29650          */
29651         IBinder mDragToken;
29652 
29653         /**
29654          * The drag shadow surface for the current drag operation.
29655          */
29656         public Surface mDragSurface;
29657 
29658 
29659         /**
29660          * The view that currently has a tooltip displayed.
29661          */
29662         View mTooltipHost;
29663 
29664         /**
29665          * The initial structure has been reported so the view is ready to report updates.
29666          */
29667         boolean mReadyForContentCaptureUpdates;
29668 
29669         /**
29670          * Map(keyed by session) of content capture events that need to be notified after the view
29671          * hierarchy is traversed: value is either the view itself for appearead events, or its
29672          * autofill id for disappeared.
29673          */
29674         SparseArray<ArrayList<Object>> mContentCaptureEvents;
29675 
29676         /**
29677          * Cached reference to the {@link ContentCaptureManager}.
29678          */
29679         ContentCaptureManager mContentCaptureManager;
29680 
29681         /**
29682          * Listener used to fit content on window level.
29683          */
29684         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
29685 
29686         /**
29687          * The leash token of this view's parent when it's in an embedded hierarchy that is
29688          * re-parented to another window.
29689          */
29690         IBinder mLeashedParentToken;
29691 
29692         /**
29693          * The accessibility view id of this view's parent when it's in an embedded
29694          * hierarchy that is re-parented to another window.
29695          */
29696         int mLeashedParentAccessibilityViewId;
29697 
29698         /**
29699          *
29700          */
29701         ScrollCaptureInternal mScrollCaptureInternal;
29702 
29703         /**
29704          * Creates a new set of attachment information with the specified
29705          * events handler and thread.
29706          *
29707          * @param handler the events handler the view must use
29708          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)29709         AttachInfo(IWindowSession session, IWindow window, Display display,
29710                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
29711                 Context context) {
29712             mSession = session;
29713             mWindow = window;
29714             mWindowToken = window.asBinder();
29715             mDisplay = display;
29716             mViewRootImpl = viewRootImpl;
29717             mHandler = handler;
29718             mRootCallbacks = effectPlayer;
29719             mTreeObserver = new ViewTreeObserver(context);
29720         }
29721 
29722         @Nullable
getContentCaptureManager(@onNull Context context)29723         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
29724             if (mContentCaptureManager != null) {
29725                 return mContentCaptureManager;
29726             }
29727             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
29728             return mContentCaptureManager;
29729         }
29730 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)29731         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
29732             if (mContentCaptureManager == null) {
29733                 return;
29734             }
29735 
29736             ArrayList<Object> events = ensureEvents(
29737                         mContentCaptureManager.getMainContentCaptureSession());
29738             events.add(insets);
29739         }
29740 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)29741         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
29742                 @NonNull View view, boolean appeared) {
29743             ArrayList<Object> events = ensureEvents(session);
29744             events.add(appeared ? view : view.getAutofillId());
29745         }
29746 
29747         @NonNull
ensureEvents(@onNull ContentCaptureSession session)29748         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
29749             if (mContentCaptureEvents == null) {
29750                 // Most of the time there will be just one session, so intial capacity is 1
29751                 mContentCaptureEvents = new SparseArray<>(1);
29752             }
29753             int sessionId = session.getId();
29754             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
29755             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
29756             if (events == null) {
29757                 events = new ArrayList<>();
29758                 mContentCaptureEvents.put(sessionId, events);
29759             }
29760 
29761             return events;
29762         }
29763 
29764         @Nullable
getScrollCaptureInternal()29765         ScrollCaptureInternal getScrollCaptureInternal() {
29766             if (mScrollCaptureInternal != null) {
29767                 mScrollCaptureInternal = new ScrollCaptureInternal();
29768             }
29769             return mScrollCaptureInternal;
29770         }
29771 
getRootSurfaceControl()29772         AttachedSurfaceControl getRootSurfaceControl() {
29773             return mViewRootImpl;
29774         }
29775 
dump(String prefix, PrintWriter writer)29776         public void dump(String prefix, PrintWriter writer) {
29777             String innerPrefix = prefix + "  ";
29778             writer.println(prefix + "AttachInfo:");
29779             writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
29780             writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
29781             writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
29782             writer.println(innerPrefix + "mUnbufferedDispatchRequested="
29783                     + mUnbufferedDispatchRequested);
29784         }
29785     }
29786 
29787     /**
29788      * <p>ScrollabilityCache holds various fields used by a View when scrolling
29789      * is supported. This avoids keeping too many unused fields in most
29790      * instances of View.</p>
29791      */
29792     private static class ScrollabilityCache implements Runnable {
29793 
29794         /**
29795          * Scrollbars are not visible
29796          */
29797         public static final int OFF = 0;
29798 
29799         /**
29800          * Scrollbars are visible
29801          */
29802         public static final int ON = 1;
29803 
29804         /**
29805          * Scrollbars are fading away
29806          */
29807         public static final int FADING = 2;
29808 
29809         public boolean fadeScrollBars;
29810 
29811         public int fadingEdgeLength;
29812         public int scrollBarDefaultDelayBeforeFade;
29813         public int scrollBarFadeDuration;
29814 
29815         public int scrollBarSize;
29816         public int scrollBarMinTouchTarget;
29817         @UnsupportedAppUsage
29818         public ScrollBarDrawable scrollBar;
29819         public float[] interpolatorValues;
29820         @UnsupportedAppUsage
29821         public View host;
29822 
29823         public final Paint paint;
29824         public final Matrix matrix;
29825         public Shader shader;
29826 
29827         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
29828 
29829         private static final float[] OPAQUE = { 255 };
29830         private static final float[] TRANSPARENT = { 0.0f };
29831 
29832         /**
29833          * When fading should start. This time moves into the future every time
29834          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
29835          */
29836         public long fadeStartTime;
29837 
29838 
29839         /**
29840          * The current state of the scrollbars: ON, OFF, or FADING
29841          */
29842         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
29843         public int state = OFF;
29844 
29845         private int mLastColor;
29846 
29847         public final Rect mScrollBarBounds = new Rect();
29848         public final Rect mScrollBarTouchBounds = new Rect();
29849 
29850         public static final int NOT_DRAGGING = 0;
29851         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
29852         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
29853         public int mScrollBarDraggingState = NOT_DRAGGING;
29854 
29855         public float mScrollBarDraggingPos = 0;
29856 
ScrollabilityCache(ViewConfiguration configuration, View host)29857         public ScrollabilityCache(ViewConfiguration configuration, View host) {
29858             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
29859             scrollBarSize = configuration.getScaledScrollBarSize();
29860             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
29861             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
29862             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
29863 
29864             paint = new Paint();
29865             matrix = new Matrix();
29866             // use use a height of 1, and then wack the matrix each time we
29867             // actually use it.
29868             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
29869             paint.setShader(shader);
29870             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
29871 
29872             this.host = host;
29873         }
29874 
setFadeColor(int color)29875         public void setFadeColor(int color) {
29876             if (color != mLastColor) {
29877                 mLastColor = color;
29878 
29879                 if (color != 0) {
29880                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
29881                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
29882                     paint.setShader(shader);
29883                     // Restore the default transfer mode (src_over)
29884                     paint.setXfermode(null);
29885                 } else {
29886                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
29887                     paint.setShader(shader);
29888                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
29889                 }
29890             }
29891         }
29892 
run()29893         public void run() {
29894             long now = AnimationUtils.currentAnimationTimeMillis();
29895             if (now >= fadeStartTime) {
29896 
29897                 // the animation fades the scrollbars out by changing
29898                 // the opacity (alpha) from fully opaque to fully
29899                 // transparent
29900                 int nextFrame = (int) now;
29901                 int framesCount = 0;
29902 
29903                 Interpolator interpolator = scrollBarInterpolator;
29904 
29905                 // Start opaque
29906                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
29907 
29908                 // End transparent
29909                 nextFrame += scrollBarFadeDuration;
29910                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
29911 
29912                 state = FADING;
29913 
29914                 // Kick off the fade animation
29915                 host.invalidate(true);
29916             }
29917         }
29918     }
29919 
29920     private class SendAccessibilityEventThrottle implements Runnable {
29921         public volatile boolean mIsPending;
29922         private AccessibilityEvent mAccessibilityEvent;
29923 
post(AccessibilityEvent accessibilityEvent)29924         public void post(AccessibilityEvent accessibilityEvent) {
29925             updateWithAccessibilityEvent(accessibilityEvent);
29926             if (!mIsPending) {
29927                 mIsPending = true;
29928                 postDelayed(this,
29929                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
29930             }
29931         }
29932 
29933         @Override
run()29934         public void run() {
29935             if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
29936                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
29937             }
29938             reset();
29939         }
29940 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)29941         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
29942             mAccessibilityEvent = accessibilityEvent;
29943         }
29944 
reset()29945         public void reset() {
29946             mIsPending = false;
29947             mAccessibilityEvent = null;
29948         }
29949 
29950     }
29951 
29952     /**
29953      * Resuable callback for sending
29954      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
29955      */
29956     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
29957         public int mDeltaX;
29958         public int mDeltaY;
29959 
29960         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)29961         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
29962             super.updateWithAccessibilityEvent(accessibilityEvent);
29963             mDeltaX += accessibilityEvent.getScrollDeltaX();
29964             mDeltaY += accessibilityEvent.getScrollDeltaY();
29965             accessibilityEvent.setScrollDeltaX(mDeltaX);
29966             accessibilityEvent.setScrollDeltaY(mDeltaY);
29967         }
29968 
29969         @Override
reset()29970         public void reset() {
29971             super.reset();
29972             mDeltaX = 0;
29973             mDeltaY = 0;
29974         }
29975     }
29976     /**
29977      * Remove the pending callback for sending a throttled accessibility event.
29978      */
29979     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)29980     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
29981         if (callback == null || !callback.mIsPending) return;
29982         removeCallbacks(callback);
29983         callback.reset();
29984     }
29985 
29986     /**
29987      * <p>
29988      * This class represents a delegate that can be registered in a {@link View}
29989      * to enhance accessibility support via composition rather via inheritance.
29990      * It is specifically targeted to widget developers that extend basic View
29991      * classes i.e. classes in package android.view, that would like their
29992      * applications to be backwards compatible.
29993      * </p>
29994      * <div class="special reference">
29995      * <h3>Developer Guides</h3>
29996      * <p>For more information about making applications accessible, read the
29997      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
29998      * developer guide.</p>
29999      * </div>
30000      * <p>
30001      * A scenario in which a developer would like to use an accessibility delegate
30002      * is overriding a method introduced in a later API version than the minimal API
30003      * version supported by the application. For example, the method
30004      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
30005      * in API version 4 when the accessibility APIs were first introduced. If a
30006      * developer would like their application to run on API version 4 devices (assuming
30007      * all other APIs used by the application are version 4 or lower) and take advantage
30008      * of this method, instead of overriding the method which would break the application's
30009      * backwards compatibility, they can override the corresponding method in this
30010      * delegate and register the delegate in the target View if the API version of
30011      * the system is high enough, i.e. the API version is the same as or higher than the API
30012      * version that introduced
30013      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
30014      * </p>
30015      * <p>
30016      * Here is an example implementation:
30017      * </p>
30018      * <code><pre><p>
30019      * if (Build.VERSION.SDK_INT >= 14) {
30020      *     // If the API version is equal of higher than the version in
30021      *     // which onInitializeAccessibilityNodeInfo was introduced we
30022      *     // register a delegate with a customized implementation.
30023      *     View view = findViewById(R.id.view_id);
30024      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
30025      *         public void onInitializeAccessibilityNodeInfo(View host,
30026      *                 AccessibilityNodeInfo info) {
30027      *             // Let the default implementation populate the info.
30028      *             super.onInitializeAccessibilityNodeInfo(host, info);
30029      *             // Set some other information.
30030      *             info.setEnabled(host.isEnabled());
30031      *         }
30032      *     });
30033      * }
30034      * </code></pre></p>
30035      * <p>
30036      * This delegate contains methods that correspond to the accessibility methods
30037      * in View. If a delegate has been specified the implementation in View hands
30038      * off handling to the corresponding method in this delegate. The default
30039      * implementation the delegate methods behaves exactly as the corresponding
30040      * method in View for the case of no accessibility delegate been set. Hence,
30041      * to customize the behavior of a View method, clients can override only the
30042      * corresponding delegate method without altering the behavior of the rest
30043      * accessibility related methods of the host view.
30044      * </p>
30045      * <p>
30046      * <strong>Note:</strong> On platform versions prior to
30047      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
30048      * views in the {@code android.widget.*} package are called <i>before</i>
30049      * host methods. This prevents certain properties such as class name from
30050      * being modified by overriding
30051      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
30052      * as any changes will be overwritten by the host class.
30053      * <p>
30054      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
30055      * methods are called <i>after</i> host methods, which all properties to be
30056      * modified without being overwritten by the host class.
30057      */
30058     public static class AccessibilityDelegate {
30059 
30060         /**
30061          * Sends an accessibility event of the given type. If accessibility is not
30062          * enabled this method has no effect.
30063          * <p>
30064          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
30065          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
30066          * been set.
30067          * </p>
30068          *
30069          * @param host The View hosting the delegate.
30070          * @param eventType The type of the event to send.
30071          *
30072          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
30073          */
sendAccessibilityEvent(View host, int eventType)30074         public void sendAccessibilityEvent(View host, int eventType) {
30075             host.sendAccessibilityEventInternal(eventType);
30076         }
30077 
30078         /**
30079          * Performs the specified accessibility action on the view. For
30080          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
30081          * <p>
30082          * The default implementation behaves as
30083          * {@link View#performAccessibilityAction(int, Bundle)
30084          *  View#performAccessibilityAction(int, Bundle)} for the case of
30085          *  no accessibility delegate been set.
30086          * </p>
30087          *
30088          * @param action The action to perform.
30089          * @return Whether the action was performed.
30090          *
30091          * @see View#performAccessibilityAction(int, Bundle)
30092          *      View#performAccessibilityAction(int, Bundle)
30093          */
performAccessibilityAction(View host, int action, Bundle args)30094         public boolean performAccessibilityAction(View host, int action, Bundle args) {
30095             return host.performAccessibilityActionInternal(action, args);
30096         }
30097 
30098         /**
30099          * Sends an accessibility event. This method behaves exactly as
30100          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
30101          * empty {@link AccessibilityEvent} and does not perform a check whether
30102          * accessibility is enabled.
30103          * <p>
30104          * The default implementation behaves as
30105          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
30106          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
30107          * the case of no accessibility delegate been set.
30108          * </p>
30109          *
30110          * @param host The View hosting the delegate.
30111          * @param event The event to send.
30112          *
30113          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
30114          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
30115          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)30116         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
30117             host.sendAccessibilityEventUncheckedInternal(event);
30118         }
30119 
30120         /**
30121          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
30122          * to its children for adding their text content to the event.
30123          * <p>
30124          * The default implementation behaves as
30125          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30126          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
30127          * the case of no accessibility delegate been set.
30128          * </p>
30129          *
30130          * @param host The View hosting the delegate.
30131          * @param event The event.
30132          * @return True if the event population was completed.
30133          *
30134          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30135          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30136          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)30137         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
30138             return host.dispatchPopulateAccessibilityEventInternal(event);
30139         }
30140 
30141         /**
30142          * Gives a chance to the host View to populate the accessibility event with its
30143          * text content.
30144          * <p>
30145          * The default implementation behaves as
30146          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
30147          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
30148          * the case of no accessibility delegate been set.
30149          * </p>
30150          *
30151          * @param host The View hosting the delegate.
30152          * @param event The accessibility event which to populate.
30153          *
30154          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
30155          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
30156          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)30157         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
30158             host.onPopulateAccessibilityEventInternal(event);
30159         }
30160 
30161         /**
30162          * Initializes an {@link AccessibilityEvent} with information about the
30163          * the host View which is the event source.
30164          * <p>
30165          * The default implementation behaves as
30166          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
30167          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
30168          * the case of no accessibility delegate been set.
30169          * </p>
30170          *
30171          * @param host The View hosting the delegate.
30172          * @param event The event to initialize.
30173          *
30174          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
30175          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
30176          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)30177         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
30178             host.onInitializeAccessibilityEventInternal(event);
30179         }
30180 
30181         /**
30182          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
30183          * <p>
30184          * The default implementation behaves as
30185          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30186          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
30187          * the case of no accessibility delegate been set.
30188          * </p>
30189          *
30190          * @param host The View hosting the delegate.
30191          * @param info The instance to initialize.
30192          *
30193          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30194          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30195          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)30196         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
30197             host.onInitializeAccessibilityNodeInfoInternal(info);
30198         }
30199 
30200         /**
30201          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
30202          * additional data.
30203          * <p>
30204          * This method only needs to be implemented if the View offers to provide additional data.
30205          * </p>
30206          * <p>
30207          * The default implementation behaves as
30208          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
30209          * for the case where no accessibility delegate is set.
30210          * </p>
30211          *
30212          * @param host The View hosting the delegate. Never {@code null}.
30213          * @param info The info to which to add the extra data. Never {@code null}.
30214          * @param extraDataKey A key specifying the type of extra data to add to the info. The
30215          *                     extra data should be added to the {@link Bundle} returned by
30216          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
30217          *                     {@code null}.
30218          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
30219          *                  May be {@code null} if the if the service provided no arguments.
30220          *
30221          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
30222          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)30223         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
30224                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
30225                 @Nullable Bundle arguments) {
30226             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
30227         }
30228 
30229         /**
30230          * Called when a child of the host View has requested sending an
30231          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
30232          * to augment the event.
30233          * <p>
30234          * The default implementation behaves as
30235          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30236          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
30237          * the case of no accessibility delegate been set.
30238          * </p>
30239          *
30240          * @param host The View hosting the delegate.
30241          * @param child The child which requests sending the event.
30242          * @param event The event to be sent.
30243          * @return True if the event should be sent
30244          *
30245          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30246          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30247          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)30248         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
30249                 AccessibilityEvent event) {
30250             return host.onRequestSendAccessibilityEventInternal(child, event);
30251         }
30252 
30253         /**
30254          * Gets the provider for managing a virtual view hierarchy rooted at this View
30255          * and reported to {@link android.accessibilityservice.AccessibilityService}s
30256          * that explore the window content.
30257          * <p>
30258          * The default implementation behaves as
30259          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
30260          * the case of no accessibility delegate been set.
30261          * </p>
30262          *
30263          * @return The provider.
30264          *
30265          * @see AccessibilityNodeProvider
30266          */
getAccessibilityNodeProvider(View host)30267         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
30268             return null;
30269         }
30270 
30271         /**
30272          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
30273          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
30274          * This method is responsible for obtaining an accessibility node info from a
30275          * pool of reusable instances and calling
30276          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
30277          * view to initialize the former.
30278          * <p>
30279          * <strong>Note:</strong> The client is responsible for recycling the obtained
30280          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
30281          * creation.
30282          * </p>
30283          * <p>
30284          * The default implementation behaves as
30285          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
30286          * the case of no accessibility delegate been set.
30287          * </p>
30288          * @return A populated {@link AccessibilityNodeInfo}.
30289          *
30290          * @see AccessibilityNodeInfo
30291          *
30292          * @hide
30293          */
30294         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
createAccessibilityNodeInfo(View host)30295         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
30296             return host.createAccessibilityNodeInfoInternal();
30297         }
30298     }
30299 
30300     private static class MatchIdPredicate implements Predicate<View> {
30301         public int mId;
30302 
30303         @Override
test(View view)30304         public boolean test(View view) {
30305             return (view.mID == mId);
30306         }
30307     }
30308 
30309     private static class MatchLabelForPredicate implements Predicate<View> {
30310         private int mLabeledId;
30311 
30312         @Override
test(View view)30313         public boolean test(View view) {
30314             return (view.mLabelForId == mLabeledId);
30315         }
30316     }
30317 
30318 
30319     /**
30320      * Returns the current scroll capture hint for this view.
30321      *
30322      * @return the current scroll capture hint
30323      */
30324     @ScrollCaptureHint
getScrollCaptureHint()30325     public int getScrollCaptureHint() {
30326         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
30327                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
30328     }
30329 
30330     /**
30331      * Sets the scroll capture hint for this View. These flags affect the search for a potential
30332      * scroll capture targets.
30333      *
30334      * @param hint the scrollCaptureHint flags value to set
30335      */
setScrollCaptureHint(@crollCaptureHint int hint)30336     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
30337         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
30338         // Since include/exclude are mutually exclusive, exclude takes precedence.
30339         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
30340             hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
30341         }
30342         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
30343                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
30344     }
30345 
30346     /**
30347      * Sets the callback to receive scroll capture requests. This component is the adapter between
30348      * the scroll capture API and application UI code. If no callback is set, the system may provide
30349      * an implementation. Any value provided here will take precedence over a system version.
30350      * <p>
30351      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
30352      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
30353      * <p>
30354      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
30355      * setting a custom callback to help ensure it is selected as the target.
30356      *
30357      * @param callback the new callback to assign
30358      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)30359     public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
30360         getListenerInfo().mScrollCaptureCallback = callback;
30361     }
30362 
30363     /** {@hide} */
30364     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)30365     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
30366             @NonNull Point windowOffset) {
30367         if (mAttachInfo == null) {
30368             return null;
30369         }
30370         if (mAttachInfo.mScrollCaptureInternal == null) {
30371             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
30372         }
30373         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
30374                 windowOffset);
30375     }
30376 
30377     /**
30378      * Dispatch a scroll capture search request down the view hierarchy.
30379      *
30380      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
30381      *                         the parent
30382      * @param windowOffset     the offset of this view within the window
30383      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
30384      *                         results.accept} may be called zero or more times on the calling
30385      *                         thread before onScrollCaptureSearch returns
30386      */
dispatchScrollCaptureSearch( @onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)30387     public void dispatchScrollCaptureSearch(
30388             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
30389             @NonNull Consumer<ScrollCaptureTarget> targets) {
30390         onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
30391     }
30392 
30393     /**
30394      * Called when scroll capture is requested, to search for appropriate content to scroll. If
30395      * applicable, this view adds itself to the provided list for consideration, subject to the
30396      * flags set by {@link #setScrollCaptureHint}.
30397      *
30398      * @param localVisibleRect the local visible rect of this view
30399      * @param windowOffset     the offset of localVisibleRect within the window
30400      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
30401      *                         results.accept} may be called zero or more times on the calling
30402      *                         thread before onScrollCaptureSearch returns
30403      * @throws IllegalStateException if this view is not attached to a window
30404      */
onScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)30405     public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
30406             @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
30407         int hint = getScrollCaptureHint();
30408         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
30409             return;
30410         }
30411         boolean rectIsVisible = true;
30412 
30413         // Apply clipBounds if present.
30414         if (mClipBounds != null) {
30415             rectIsVisible = localVisibleRect.intersect(mClipBounds);
30416         }
30417         if (!rectIsVisible) {
30418             return;
30419         }
30420 
30421         // Get a callback provided by the framework, library or application.
30422         ScrollCaptureCallback callback =
30423                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
30424 
30425         // Try framework support for standard scrolling containers.
30426         if (callback == null) {
30427             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
30428         }
30429 
30430         // If found, then add it to the list.
30431         if (callback != null) {
30432             // Add to the list for consideration
30433             Point offset = new Point(windowOffset.x, windowOffset.y);
30434             Rect rect = new Rect(localVisibleRect);
30435             targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
30436         }
30437     }
30438 
30439     /**
30440      * Dump all private flags in readable format, useful for documentation and
30441      * consistency checking.
30442      */
dumpFlags()30443     private static void dumpFlags() {
30444         final HashMap<String, String> found = Maps.newHashMap();
30445         try {
30446             for (Field field : View.class.getDeclaredFields()) {
30447                 final int modifiers = field.getModifiers();
30448                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
30449                     if (field.getType().equals(int.class)) {
30450                         final int value = field.getInt(null);
30451                         dumpFlag(found, field.getName(), value);
30452                     } else if (field.getType().equals(int[].class)) {
30453                         final int[] values = (int[]) field.get(null);
30454                         for (int i = 0; i < values.length; i++) {
30455                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
30456                         }
30457                     }
30458                 }
30459             }
30460         } catch (IllegalAccessException e) {
30461             throw new RuntimeException(e);
30462         }
30463 
30464         final ArrayList<String> keys = Lists.newArrayList();
30465         keys.addAll(found.keySet());
30466         Collections.sort(keys);
30467         for (String key : keys) {
30468             Log.d(VIEW_LOG_TAG, found.get(key));
30469         }
30470     }
30471 
dumpFlag(HashMap<String, String> found, String name, int value)30472     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
30473         // Sort flags by prefix, then by bits, always keeping unique keys
30474         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
30475         final int prefix = name.indexOf('_');
30476         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
30477         final String output = bits + " " + name;
30478         found.put(key, output);
30479     }
30480 
30481     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)30482     public void encode(@NonNull ViewHierarchyEncoder stream) {
30483         stream.beginObject(this);
30484         encodeProperties(stream);
30485         stream.endObject();
30486     }
30487 
30488     /** {@hide} */
30489     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)30490     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
30491         Object resolveId = ViewDebug.resolveId(getContext(), mID);
30492         if (resolveId instanceof String) {
30493             stream.addProperty("id", (String) resolveId);
30494         } else {
30495             stream.addProperty("id", mID);
30496         }
30497 
30498         stream.addProperty("misc:transformation.alpha",
30499                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
30500         stream.addProperty("misc:transitionName", getTransitionName());
30501 
30502         // layout
30503         stream.addProperty("layout:left", mLeft);
30504         stream.addProperty("layout:right", mRight);
30505         stream.addProperty("layout:top", mTop);
30506         stream.addProperty("layout:bottom", mBottom);
30507         stream.addProperty("layout:width", getWidth());
30508         stream.addProperty("layout:height", getHeight());
30509         stream.addProperty("layout:layoutDirection", getLayoutDirection());
30510         stream.addProperty("layout:layoutRtl", isLayoutRtl());
30511         stream.addProperty("layout:hasTransientState", hasTransientState());
30512         stream.addProperty("layout:baseline", getBaseline());
30513 
30514         // layout params
30515         ViewGroup.LayoutParams layoutParams = getLayoutParams();
30516         if (layoutParams != null) {
30517             stream.addPropertyKey("layoutParams");
30518             layoutParams.encode(stream);
30519         }
30520 
30521         // scrolling
30522         stream.addProperty("scrolling:scrollX", mScrollX);
30523         stream.addProperty("scrolling:scrollY", mScrollY);
30524 
30525         // padding
30526         stream.addProperty("padding:paddingLeft", mPaddingLeft);
30527         stream.addProperty("padding:paddingRight", mPaddingRight);
30528         stream.addProperty("padding:paddingTop", mPaddingTop);
30529         stream.addProperty("padding:paddingBottom", mPaddingBottom);
30530         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
30531         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
30532         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
30533         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
30534         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
30535 
30536         // measurement
30537         stream.addProperty("measurement:minHeight", mMinHeight);
30538         stream.addProperty("measurement:minWidth", mMinWidth);
30539         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
30540         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
30541 
30542         // drawing
30543         stream.addProperty("drawing:elevation", getElevation());
30544         stream.addProperty("drawing:translationX", getTranslationX());
30545         stream.addProperty("drawing:translationY", getTranslationY());
30546         stream.addProperty("drawing:translationZ", getTranslationZ());
30547         stream.addProperty("drawing:rotation", getRotation());
30548         stream.addProperty("drawing:rotationX", getRotationX());
30549         stream.addProperty("drawing:rotationY", getRotationY());
30550         stream.addProperty("drawing:scaleX", getScaleX());
30551         stream.addProperty("drawing:scaleY", getScaleY());
30552         stream.addProperty("drawing:pivotX", getPivotX());
30553         stream.addProperty("drawing:pivotY", getPivotY());
30554         stream.addProperty("drawing:clipBounds",
30555                 mClipBounds == null ? null : mClipBounds.toString());
30556         stream.addProperty("drawing:opaque", isOpaque());
30557         stream.addProperty("drawing:alpha", getAlpha());
30558         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
30559         stream.addProperty("drawing:shadow", hasShadow());
30560         stream.addProperty("drawing:solidColor", getSolidColor());
30561         stream.addProperty("drawing:layerType", mLayerType);
30562         stream.addProperty("drawing:willNotDraw", willNotDraw());
30563         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
30564         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
30565         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
30566         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
30567         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
30568         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
30569 
30570         // focus
30571         stream.addProperty("focus:hasFocus", hasFocus());
30572         stream.addProperty("focus:isFocused", isFocused());
30573         stream.addProperty("focus:focusable", getFocusable());
30574         stream.addProperty("focus:isFocusable", isFocusable());
30575         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
30576 
30577         stream.addProperty("misc:clickable", isClickable());
30578         stream.addProperty("misc:pressed", isPressed());
30579         stream.addProperty("misc:selected", isSelected());
30580         stream.addProperty("misc:touchMode", isInTouchMode());
30581         stream.addProperty("misc:hovered", isHovered());
30582         stream.addProperty("misc:activated", isActivated());
30583 
30584         stream.addProperty("misc:visibility", getVisibility());
30585         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
30586         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
30587 
30588         stream.addProperty("misc:enabled", isEnabled());
30589         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
30590         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
30591 
30592         // theme attributes
30593         Resources.Theme theme = getContext().getTheme();
30594         if (theme != null) {
30595             stream.addPropertyKey("theme");
30596             theme.encode(stream);
30597         }
30598 
30599         // view attribute information
30600         int n = mAttributes != null ? mAttributes.length : 0;
30601         stream.addProperty("meta:__attrCount__", n/2);
30602         for (int i = 0; i < n; i += 2) {
30603             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
30604         }
30605 
30606         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
30607 
30608         // text
30609         stream.addProperty("text:textDirection", getTextDirection());
30610         stream.addProperty("text:textAlignment", getTextAlignment());
30611 
30612         // accessibility
30613         CharSequence contentDescription = getContentDescription();
30614         stream.addUserProperty("accessibility:contentDescription",
30615                 contentDescription == null ? "" : contentDescription.toString());
30616         stream.addProperty("accessibility:labelFor", getLabelFor());
30617         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
30618     }
30619 
30620     /**
30621      * Determine if this view is rendered on a round wearable device and is the main view
30622      * on the screen.
30623      */
shouldDrawRoundScrollbar()30624     boolean shouldDrawRoundScrollbar() {
30625         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
30626             return false;
30627         }
30628 
30629         final View rootView = getRootView();
30630         final WindowInsets insets = getRootWindowInsets();
30631 
30632         int height = getHeight();
30633         int width = getWidth();
30634         int displayHeight = rootView.getHeight();
30635         int displayWidth = rootView.getWidth();
30636 
30637         if (height != displayHeight || width != displayWidth) {
30638             return false;
30639         }
30640 
30641         getLocationInWindow(mAttachInfo.mTmpLocation);
30642         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
30643                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
30644     }
30645 
30646     /**
30647      * Sets the tooltip text which will be displayed in a small popup next to the view.
30648      * <p>
30649      * The tooltip will be displayed:
30650      * <ul>
30651      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
30652      * menu). </li>
30653      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
30654      * </ul>
30655      * <p>
30656      * <strong>Note:</strong> Do not override this method, as it will have no
30657      * effect on the text displayed in the tooltip.
30658      *
30659      * @param tooltipText the tooltip text, or null if no tooltip is required
30660      * @see #getTooltipText()
30661      * @attr ref android.R.styleable#View_tooltipText
30662      */
setTooltipText(@ullable CharSequence tooltipText)30663     public void setTooltipText(@Nullable CharSequence tooltipText) {
30664         if (TextUtils.isEmpty(tooltipText)) {
30665             setFlags(0, TOOLTIP);
30666             hideTooltip();
30667             mTooltipInfo = null;
30668         } else {
30669             setFlags(TOOLTIP, TOOLTIP);
30670             if (mTooltipInfo == null) {
30671                 mTooltipInfo = new TooltipInfo();
30672                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
30673                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
30674                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
30675                 mTooltipInfo.clearAnchorPos();
30676             }
30677             mTooltipInfo.mTooltipText = tooltipText;
30678         }
30679     }
30680 
30681     /**
30682      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
30683      */
30684     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)30685     public void setTooltip(@Nullable CharSequence tooltipText) {
30686         setTooltipText(tooltipText);
30687     }
30688 
30689     /**
30690      * Returns the view's tooltip text.
30691      *
30692      * <strong>Note:</strong> Do not override this method, as it will have no
30693      * effect on the text displayed in the tooltip. You must call
30694      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
30695      *
30696      * @return the tooltip text
30697      * @see #setTooltipText(CharSequence)
30698      * @attr ref android.R.styleable#View_tooltipText
30699      */
30700     @InspectableProperty
30701     @Nullable
getTooltipText()30702     public CharSequence getTooltipText() {
30703         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
30704     }
30705 
30706     /**
30707      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
30708      */
30709     @Nullable
getTooltip()30710     public CharSequence getTooltip() {
30711         return getTooltipText();
30712     }
30713 
showTooltip(int x, int y, boolean fromLongClick)30714     private boolean showTooltip(int x, int y, boolean fromLongClick) {
30715         if (mAttachInfo == null || mTooltipInfo == null) {
30716             return false;
30717         }
30718         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
30719             return false;
30720         }
30721         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
30722             return false;
30723         }
30724         hideTooltip();
30725         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
30726         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
30727         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
30728         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
30729         mAttachInfo.mTooltipHost = this;
30730         // The available accessibility actions have changed
30731         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
30732         return true;
30733     }
30734 
30735     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hideTooltip()30736     void hideTooltip() {
30737         if (mTooltipInfo == null) {
30738             return;
30739         }
30740         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30741         if (mTooltipInfo.mTooltipPopup == null) {
30742             return;
30743         }
30744         mTooltipInfo.mTooltipPopup.hide();
30745         mTooltipInfo.mTooltipPopup = null;
30746         mTooltipInfo.mTooltipFromLongClick = false;
30747         mTooltipInfo.clearAnchorPos();
30748         if (mAttachInfo != null) {
30749             mAttachInfo.mTooltipHost = null;
30750         }
30751         // The available accessibility actions have changed
30752         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
30753     }
30754 
showLongClickTooltip(int x, int y)30755     private boolean showLongClickTooltip(int x, int y) {
30756         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30757         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30758         return showTooltip(x, y, true);
30759     }
30760 
showHoverTooltip()30761     private boolean showHoverTooltip() {
30762         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
30763     }
30764 
dispatchTooltipHoverEvent(MotionEvent event)30765     boolean dispatchTooltipHoverEvent(MotionEvent event) {
30766         if (mTooltipInfo == null) {
30767             return false;
30768         }
30769         switch(event.getAction()) {
30770             case MotionEvent.ACTION_HOVER_MOVE:
30771                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
30772                     break;
30773                 }
30774                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
30775                     if (mTooltipInfo.mTooltipPopup == null) {
30776                         // Schedule showing the tooltip after a timeout.
30777                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30778                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
30779                                 ViewConfiguration.getHoverTooltipShowTimeout());
30780                     }
30781 
30782                     // Hide hover-triggered tooltip after a period of inactivity.
30783                     // Match the timeout used by NativeInputManager to hide the mouse pointer
30784                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
30785                     final int timeout;
30786                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
30787                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
30788                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
30789                     } else {
30790                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
30791                     }
30792                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30793                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
30794                 }
30795                 return true;
30796 
30797             case MotionEvent.ACTION_HOVER_EXIT:
30798                 mTooltipInfo.clearAnchorPos();
30799                 if (!mTooltipInfo.mTooltipFromLongClick) {
30800                     hideTooltip();
30801                 }
30802                 break;
30803         }
30804         return false;
30805     }
30806 
handleTooltipKey(KeyEvent event)30807     void handleTooltipKey(KeyEvent event) {
30808         switch (event.getAction()) {
30809             case KeyEvent.ACTION_DOWN:
30810                 if (event.getRepeatCount() == 0) {
30811                     hideTooltip();
30812                 }
30813                 break;
30814 
30815             case KeyEvent.ACTION_UP:
30816                 handleTooltipUp();
30817                 break;
30818         }
30819     }
30820 
handleTooltipUp()30821     private void handleTooltipUp() {
30822         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
30823             return;
30824         }
30825         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30826         postDelayed(mTooltipInfo.mHideTooltipRunnable,
30827                 ViewConfiguration.getLongPressTooltipHideTimeout());
30828     }
30829 
getFocusableAttribute(TypedArray attributes)30830     private int getFocusableAttribute(TypedArray attributes) {
30831         TypedValue val = new TypedValue();
30832         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
30833             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
30834                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
30835             } else {
30836                 return val.data;
30837             }
30838         } else {
30839             return FOCUSABLE_AUTO;
30840         }
30841     }
30842 
30843     /**
30844      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
30845      * is not showing.
30846      * @hide
30847      */
30848     @TestApi
getTooltipView()30849     public View getTooltipView() {
30850         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
30851             return null;
30852         }
30853         return mTooltipInfo.mTooltipPopup.getContentView();
30854     }
30855 
30856     /**
30857      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
30858      * @hide
30859      */
30860     @TestApi
isDefaultFocusHighlightEnabled()30861     public static boolean isDefaultFocusHighlightEnabled() {
30862         return sUseDefaultFocusHighlight;
30863     }
30864 
30865     /**
30866      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
30867      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
30868      * (visually on-top views first).
30869      *
30870      * @param evt the previously unhandled {@link KeyEvent}.
30871      * @return the {@link View} which consumed the event or {@code null} if not consumed.
30872      */
dispatchUnhandledKeyEvent(KeyEvent evt)30873     View dispatchUnhandledKeyEvent(KeyEvent evt) {
30874         if (onUnhandledKeyEvent(evt)) {
30875             return this;
30876         }
30877         return null;
30878     }
30879 
30880     /**
30881      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
30882      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
30883      * this will dispatch into all the listeners registered via
30884      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
30885      * order (most recently added will receive events first).
30886      *
30887      * @param event An unhandled event.
30888      * @return {@code true} if the event was handled, {@code false} otherwise.
30889      * @see #addOnUnhandledKeyEventListener
30890      */
onUnhandledKeyEvent(@onNull KeyEvent event)30891     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
30892         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
30893             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
30894                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
30895                     return true;
30896                 }
30897             }
30898         }
30899         return false;
30900     }
30901 
hasUnhandledKeyListener()30902     boolean hasUnhandledKeyListener() {
30903         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
30904                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
30905     }
30906 
30907     /**
30908      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
30909      * UI thread.
30910      *
30911      * @param listener a receiver of unhandled {@link KeyEvent}s.
30912      * @see #removeOnUnhandledKeyEventListener
30913      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)30914     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
30915         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
30916         if (listeners == null) {
30917             listeners = new ArrayList<>();
30918             getListenerInfo().mUnhandledKeyListeners = listeners;
30919         }
30920         listeners.add(listener);
30921         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
30922             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
30923         }
30924     }
30925 
30926     /**
30927      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
30928      * UI thread.
30929      *
30930      * @param listener a receiver of unhandled {@link KeyEvent}s.
30931      * @see #addOnUnhandledKeyEventListener
30932      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)30933     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
30934         if (mListenerInfo != null) {
30935             if (mListenerInfo.mUnhandledKeyListeners != null
30936                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
30937                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
30938                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
30939                     mListenerInfo.mUnhandledKeyListeners = null;
30940                     if (mParent instanceof ViewGroup) {
30941                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
30942                     }
30943                 }
30944             }
30945         }
30946     }
30947 
30948     /**
30949      * Set the view to be detached or not detached.
30950      *
30951      * @param detached Whether the view is detached.
30952      *
30953      * @hide
30954      */
setDetached(boolean detached)30955     protected void setDetached(boolean detached) {
30956         if (detached) {
30957             mPrivateFlags4 |= PFLAG4_DETACHED;
30958         } else {
30959             mPrivateFlags4 &= ~PFLAG4_DETACHED;
30960         }
30961     }
30962 
30963     /**
30964      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
30965      * the view.
30966      *
30967      * <p>The default implementation does nothing.</p>
30968      *
30969      * @param supportedFormats the supported translation formats. For now, the only possible value
30970      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
30971      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to
30972      * collect the information to be translated in the view. The {@code requestsCollector} only
30973      * accepts one request; an IllegalStateException is thrown if more than one
30974      * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the
30975      * {@link ViewTranslationRequest}.
30976      */
onCreateViewTranslationRequest(@onNull @ataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)30977     public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
30978             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
30979     }
30980 
30981     /**
30982      * Collects {@link ViewTranslationRequest}s which represents the content to be translated
30983      * for the virtual views in the host view. This is called if this view returned a virtual
30984      * view structure from {@link #onProvideContentCaptureStructure} and the system determined that
30985      * those virtual views were relevant for translation.
30986      *
30987      * <p>The default implementation does nothing.</p>
30988      *
30989      * @param virtualIds the virtual view ids which represents the virtual views in the host
30990      * view.
30991      * @param supportedFormats the supported translation formats. For now, the only possible value
30992      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
30993      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
30994      * multiple times to collect the information to be translated in the host view. One
30995      * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
30996      * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
30997      * Consumer after the method returns.
30998      */
30999     @SuppressLint("NullableCollection")
onCreateVirtualViewTranslationRequests(@onNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)31000     public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
31001             @NonNull @DataFormat int[] supportedFormats,
31002             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
31003         // no-op
31004     }
31005 
31006     /**
31007      * Returns a {@link ViewTranslationCallback} that is used to display the translated information
31008      * or {@code null} if this View doesn't support translation.
31009      *
31010      * @hide
31011      */
31012     @Nullable
getViewTranslationCallback()31013     public ViewTranslationCallback getViewTranslationCallback() {
31014         return mViewTranslationCallback;
31015     }
31016 
31017     /**
31018      * Sets a {@link ViewTranslationCallback} that is used to display/hide the translated
31019      * information. Developers can provide the customized implementation for show/hide translated
31020      * information.
31021      *
31022      * @param callback a {@link ViewTranslationCallback} that is used to control how to display the
31023      * translated information
31024      */
setViewTranslationCallback(@onNull ViewTranslationCallback callback)31025     public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
31026         mViewTranslationCallback = callback;
31027     }
31028 
31029     /**
31030      * Clear the {@link ViewTranslationCallback} from this view.
31031      */
clearViewTranslationCallback()31032     public void clearViewTranslationCallback() {
31033         mViewTranslationCallback = null;
31034     }
31035 
31036     /**
31037      * Returns the {@link ViewTranslationResponse} associated with this view. The response will be
31038      * set when the translation is done then {@link #onViewTranslationResponse} is called. The
31039      * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the
31040      * translated information.
31041      *
31042      * @return a {@link ViewTranslationResponse} that contains the translated information associated
31043      * with this view or {@code null} if this View doesn't have the translation.
31044      */
31045     @Nullable
getViewTranslationResponse()31046     public ViewTranslationResponse getViewTranslationResponse() {
31047         return mViewTranslationResponse;
31048     }
31049 
31050     /**
31051      * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated
31052      * by the TranslationService. The {@link ViewTranslationResponse} should be saved here so that
31053      * the {@link ViewTranslationResponse} can be used to display the translation when the system
31054      * calls {@link ViewTranslationCallback#onShowTranslation}.
31055      *
31056      * <p> The default implementation will set the ViewTranslationResponse that can be get from
31057      * {@link View#getViewTranslationResponse}. </p>
31058      *
31059      * @param response a {@link ViewTranslationResponse} that contains the translated information
31060      * which can be shown in the view.
31061      */
onViewTranslationResponse(@onNull ViewTranslationResponse response)31062     public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
31063         mViewTranslationResponse = response;
31064     }
31065 
31066     /**
31067      * Clears the ViewTranslationResponse stored by the default implementation of {@link
31068      * #onViewTranslationResponse}.
31069      *
31070      * @hide
31071      */
clearViewTranslationResponse()31072     public void clearViewTranslationResponse() {
31073         mViewTranslationResponse = null;
31074     }
31075 
31076     /**
31077      * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
31078      * translated by the TranslationService.
31079      *
31080      * <p> The default implementation does nothing.</p>
31081      *
31082      * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
31083      * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information
31084      * which can be shown in the view. The key of SparseArray is the virtual child ids.
31085      */
onVirtualViewTranslationResponses( @onNull LongSparseArray<ViewTranslationResponse> response)31086     public void onVirtualViewTranslationResponses(
31087             @NonNull LongSparseArray<ViewTranslationResponse> response) {
31088         // no-op
31089     }
31090 
31091     /**
31092      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
31093      * the hierarchy when the app requests ui translation. Typically, this method should only be
31094      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
31095      * classes should override {@link View#onCreateViewTranslationRequest} for normal view or
31096      * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children.
31097      * When requested to start the ui translation, the system will call this method to traverse the
31098      * view hierarchy to collect {@link ViewTranslationRequest}s and create a
31099      * {@link android.view.translation.Translator} to translate the requests. All the
31100      * {@link ViewTranslationRequest}s must be added when the traversal is done.
31101      *
31102      * <p> The default implementation calls {@link View#onCreateViewTranslationRequest} for normal
31103      * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
31104      * children to build {@link ViewTranslationRequest} if the view should be translated.
31105      * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
31106      * recycling of views doesn't prevent the system from attaching the response to it. Therefore,
31107      * if overriding this method, you should set or reset the transient state. </p>
31108      *
31109      * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
31110      * {@code null} if the view doesn't have virtual child that should be translated. The virtual
31111      * child ids are the same virtual ids provided by ContentCapture.
31112      * @param supportedFormats the supported translation formats. For now, the only possible value
31113      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
31114      * @param capability a {@link TranslationCapability} that holds translation capability.
31115      * information, e.g. source spec, target spec.
31116      * @param requests fill in with {@link ViewTranslationRequest}s for translation purpose.
31117      */
dispatchCreateViewTranslationRequest(@onNull Map<AutofillId, long[]> viewIds, @NonNull @DataFormat int[] supportedFormats, @NonNull TranslationCapability capability, @NonNull List<ViewTranslationRequest> requests)31118     public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
31119             @NonNull @DataFormat int[] supportedFormats,
31120             @NonNull TranslationCapability capability,
31121             @NonNull List<ViewTranslationRequest> requests) {
31122         AutofillId autofillId = getAutofillId();
31123         if (viewIds.containsKey(autofillId)) {
31124             if (viewIds.get(autofillId) == null) {
31125                 // TODO: avoiding the allocation per view
31126                 onCreateViewTranslationRequest(supportedFormats,
31127                         new ViewTranslationRequestConsumer(requests));
31128             } else {
31129                 onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
31130                         request -> {
31131                             requests.add(request);
31132                         });
31133             }
31134         }
31135     }
31136 
31137     private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
31138         private final List<ViewTranslationRequest> mRequests;
31139         private boolean mCalled;
31140 
ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests)31141         ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
31142             mRequests = requests;
31143         }
31144 
31145         @Override
accept(ViewTranslationRequest request)31146         public void accept(ViewTranslationRequest request) {
31147             if (mCalled) {
31148                 throw new IllegalStateException("The translation Consumer is not reusable.");
31149             }
31150             mCalled = true;
31151             if (request != null && request.getKeys().size() > 0) {
31152                 mRequests.add(request);
31153                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
31154                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
31155                             + getAutofillId());
31156                 }
31157                 setHasTransientState(true);
31158                 setHasTranslationTransientState(true);
31159             }
31160         }
31161     }
31162 
31163     /**
31164      * Called to generate a {@link DisplayHash} for this view.
31165      *
31166      * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
31167      *                      the values returned from
31168      *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
31169      * @param bounds The bounds for the content within the View to generate the hash for. If
31170      *               bounds are null, the entire View's bounds will be used. If empty, it will
31171      *               invoke the callback
31172      *               {@link DisplayHashResultCallback#onDisplayHashError} with error
31173      *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
31174      * @param executor The executor that the callback should be invoked on.
31175      * @param callback The callback to handle the results of generating the display hash
31176      */
generateDisplayHash(@onNull String hashAlgorithm, @Nullable Rect bounds, @NonNull Executor executor, @NonNull DisplayHashResultCallback callback)31177     public void generateDisplayHash(@NonNull String hashAlgorithm,
31178             @Nullable Rect bounds, @NonNull Executor executor,
31179             @NonNull DisplayHashResultCallback callback) {
31180         IWindowSession session = getWindowSession();
31181         if (session == null) {
31182             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
31183             return;
31184         }
31185         IWindow window = getWindow();
31186         if (window == null) {
31187             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
31188             return;
31189         }
31190 
31191         Rect visibleBounds = new Rect();
31192         getGlobalVisibleRect(visibleBounds);
31193 
31194         if (bounds != null && bounds.isEmpty()) {
31195             callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
31196             return;
31197         }
31198 
31199         if (bounds != null) {
31200             bounds.offset(visibleBounds.left, visibleBounds.top);
31201             visibleBounds.intersectUnchecked(bounds);
31202         }
31203 
31204         if (visibleBounds.isEmpty()) {
31205             callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
31206             return;
31207         }
31208 
31209         RemoteCallback remoteCallback = new RemoteCallback(result ->
31210                 executor.execute(() -> {
31211                     DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH);
31212                     int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
31213                             DISPLAY_HASH_ERROR_UNKNOWN);
31214                     if (displayHash != null) {
31215                         callback.onDisplayHashResult(displayHash);
31216                     } else {
31217                         callback.onDisplayHashError(errorCode);
31218                     }
31219                 }));
31220 
31221         try {
31222             session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
31223         } catch (RemoteException e) {
31224             Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
31225             callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
31226         }
31227     }
31228 
31229     /**
31230      * The AttachedSurfaceControl itself is not a View, it is just the interface to the
31231      * windowing-system object that contains the entire view hierarchy.
31232      * For the root View of a given hierarchy see {@link #getRootView}.
31233 
31234      * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
31235      * This will only return a non-null value when called between {@link #onAttachedToWindow}
31236      * and {@link #onDetachedFromWindow}.
31237      */
getRootSurfaceControl()31238     public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
31239         if (mAttachInfo != null) {
31240           return mAttachInfo.getRootSurfaceControl();
31241         }
31242         return null;
31243     }
31244 }
31245