• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static android.content.res.Resources.ID_NULL;
20 import static android.view.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      * |-------|-------|-------|-------|
3519      */
3520 
3521     /**
3522      * Mask for obtaining the bits which specify how to determine
3523      * whether a view is important for autofill.
3524      *
3525      * <p>NOTE: the important for content capture values were the first flags added and are set in
3526      * the rightmost position, so we don't need to shift them
3527      */
3528     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3529             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3530             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3531             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3532             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3533 
3534     /*
3535      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3536      * should be called.
3537      *
3538      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3539      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3540      */
3541     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3542     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3543 
3544     /*
3545      * Flags used to cache the value returned by isImportantForContentCapture while the view
3546      * hierarchy is being traversed.
3547      */
3548     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3549     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3550 
3551     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3552             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3553             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3554 
3555     /**
3556      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3557      */
3558     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3559 
3560     /**
3561      * Flag indicating the field should not have yellow highlight when autofilled.
3562      */
3563     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3564 
3565     /**
3566      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3567      */
3568     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3569 
3570     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3571             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3572             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3573 
3574     /**
3575      * Indicates if the view can receive click events when disabled.
3576      */
3577     private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
3578 
3579     /**
3580      * Indicates if the view is just detached.
3581      */
3582     private static final int PFLAG4_DETACHED = 0x000002000;
3583 
3584     /**
3585      * Indicates that the view has transient state because the system is translating it.
3586      */
3587     private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
3588 
3589     /* End of masks for mPrivateFlags4 */
3590 
3591     /** @hide */
3592     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3593     /** @hide */
3594     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3595     /** @hide */
3596     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3597 
3598     /** @hide */
3599     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3600             VIEW_STRUCTURE_FOR_ASSIST,
3601             VIEW_STRUCTURE_FOR_AUTOFILL,
3602             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3603     })
3604     @Retention(RetentionPolicy.SOURCE)
3605     public @interface ViewStructureType {}
3606 
3607     /**
3608      * Always allow a user to over-scroll this view, provided it is a
3609      * view that can scroll.
3610      *
3611      * @see #getOverScrollMode()
3612      * @see #setOverScrollMode(int)
3613      */
3614     public static final int OVER_SCROLL_ALWAYS = 0;
3615 
3616     /**
3617      * Allow a user to over-scroll this view only if the content is large
3618      * enough to meaningfully scroll, provided it is a view that can scroll.
3619      *
3620      * @see #getOverScrollMode()
3621      * @see #setOverScrollMode(int)
3622      */
3623     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3624 
3625     /**
3626      * Never allow a user to over-scroll this view.
3627      *
3628      * @see #getOverScrollMode()
3629      * @see #setOverScrollMode(int)
3630      */
3631     public static final int OVER_SCROLL_NEVER = 2;
3632 
3633     /**
3634      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3635      * requested the system UI (status bar) to be visible (the default).
3636      *
3637      * @see #setSystemUiVisibility(int)
3638      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
3639      * instead.
3640      */
3641     @Deprecated
3642     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3643 
3644     /**
3645      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3646      * system UI to enter an unobtrusive "low profile" mode.
3647      *
3648      * <p>This is for use in games, book readers, video players, or any other
3649      * "immersive" application where the usual system chrome is deemed too distracting.
3650      *
3651      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3652      *
3653      * @see #setSystemUiVisibility(int)
3654      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
3655      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
3656      * {@link Type#systemBars()}.
3657      */
3658     @Deprecated
3659     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3660 
3661     /**
3662      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3663      * system navigation be temporarily hidden.
3664      *
3665      * <p>This is an even less obtrusive state than that called for by
3666      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3667      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3668      * those to disappear. This is useful (in conjunction with the
3669      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3670      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3671      * window flags) for displaying content using every last pixel on the display.
3672      *
3673      * <p>There is a limitation: because navigation controls are so important, the least user
3674      * interaction will cause them to reappear immediately.  When this happens, both
3675      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3676      * so that both elements reappear at the same time.
3677      *
3678      * @see #setSystemUiVisibility(int)
3679      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
3680      * instead.
3681      */
3682     @Deprecated
3683     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3684 
3685     /**
3686      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3687      * into the normal fullscreen mode so that its content can take over the screen
3688      * while still allowing the user to interact with the application.
3689      *
3690      * <p>This has the same visual effect as
3691      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3692      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3693      * meaning that non-critical screen decorations (such as the status bar) will be
3694      * hidden while the user is in the View's window, focusing the experience on
3695      * that content.  Unlike the window flag, if you are using ActionBar in
3696      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3697      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3698      * hide the action bar.
3699      *
3700      * <p>This approach to going fullscreen is best used over the window flag when
3701      * it is a transient state -- that is, the application does this at certain
3702      * points in its user interaction where it wants to allow the user to focus
3703      * on content, but not as a continuous state.  For situations where the application
3704      * would like to simply stay full screen the entire time (such as a game that
3705      * wants to take over the screen), the
3706      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3707      * is usually a better approach.  The state set here will be removed by the system
3708      * in various situations (such as the user moving to another application) like
3709      * the other system UI states.
3710      *
3711      * <p>When using this flag, the application should provide some easy facility
3712      * for the user to go out of it.  A common example would be in an e-book
3713      * reader, where tapping on the screen brings back whatever screen and UI
3714      * decorations that had been hidden while the user was immersed in reading
3715      * the book.
3716      *
3717      * @see #setSystemUiVisibility(int)
3718      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
3719      * instead.
3720      */
3721     @Deprecated
3722     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3723 
3724     /**
3725      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3726      * flags, we would like a stable view of the content insets given to
3727      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3728      * will always represent the worst case that the application can expect
3729      * as a continuous state.  In the stock Android UI this is the space for
3730      * the system bar, nav bar, and status bar, but not more transient elements
3731      * such as an input method.
3732      *
3733      * The stable layout your UI sees is based on the system UI modes you can
3734      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3735      * then you will get a stable layout for changes of the
3736      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3737      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3738      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3739      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3740      * with a stable layout.  (Note that you should avoid using
3741      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3742      *
3743      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3744      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3745      * then a hidden status bar will be considered a "stable" state for purposes
3746      * here.  This allows your UI to continually hide the status bar, while still
3747      * using the system UI flags to hide the action bar while still retaining
3748      * a stable layout.  Note that changing the window fullscreen flag will never
3749      * provide a stable layout for a clean transition.
3750      *
3751      * <p>If you are using ActionBar in
3752      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3753      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3754      * insets it adds to those given to the application.
3755      *
3756      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
3757      * insets that don't change when system bars change visibility state.
3758      */
3759     @Deprecated
3760     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3761 
3762     /**
3763      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3764      * to be laid out as if it has requested
3765      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3766      * allows it to avoid artifacts when switching in and out of that mode, at
3767      * the expense that some of its user interface may be covered by screen
3768      * decorations when they are shown.  You can perform layout of your inner
3769      * UI elements to account for the navigation system UI through the
3770      * {@link #fitSystemWindows(Rect)} method.
3771      *
3772      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3773      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
3774      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3775      */
3776     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3777 
3778     /**
3779      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3780      * to be laid out as if it has requested
3781      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3782      * allows it to avoid artifacts when switching in and out of that mode, at
3783      * the expense that some of its user interface may be covered by screen
3784      * decorations when they are shown.  You can perform layout of your inner
3785      * UI elements to account for non-fullscreen system UI through the
3786      * {@link #fitSystemWindows(Rect)} method.
3787      *
3788      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3789      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3790      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3791      *  layoutInDisplayCutoutMode} is
3792      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3793      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3794      *
3795      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3796      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3797      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3798      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3799      *
3800      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3801      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
3802      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3803      */
3804     @Deprecated
3805     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3806 
3807     /**
3808      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3809      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3810      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3811      * user interaction.
3812      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3813      * has an effect when used in combination with that flag.</p>
3814      *
3815      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_DEFAULT} instead.
3816      */
3817     @Deprecated
3818     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3819 
3820     /**
3821      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3822      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3823      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3824      * experience while also hiding the system bars.  If this flag is not set,
3825      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3826      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3827      * if the user swipes from the top of the screen.
3828      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3829      * system gestures, such as swiping from the top of the screen.  These transient system bars
3830      * will overlay app's content, may have some degree of transparency, and will automatically
3831      * hide after a short timeout.
3832      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3833      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3834      * with one or both of those flags.</p>
3835      *
3836      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
3837      */
3838     @Deprecated
3839     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3840 
3841     /**
3842      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3843      * is compatible with light status bar backgrounds.
3844      *
3845      * <p>For this to take effect, the window must request
3846      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3847      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3848      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3849      *         FLAG_TRANSLUCENT_STATUS}.
3850      *
3851      * @see android.R.attr#windowLightStatusBar
3852      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
3853      */
3854     @Deprecated
3855     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3856 
3857     /**
3858      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3859      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3860      */
3861     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
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_LEGACY2 = 0x00010000;
3868 
3869     /**
3870      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3871      * that is compatible with light navigation bar backgrounds.
3872      *
3873      * <p>For this to take effect, the window must request
3874      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3875      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3876      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3877      *         FLAG_TRANSLUCENT_NAVIGATION}.
3878      *
3879      * @see android.R.attr#windowLightNavigationBar
3880      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
3881      */
3882     @Deprecated
3883     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3884 
3885     /**
3886      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3887      */
3888     @Deprecated
3889     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3890 
3891     /**
3892      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3893      */
3894     @Deprecated
3895     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3896 
3897     /**
3898      * @hide
3899      *
3900      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3901      * out of the public fields to keep the undefined bits out of the developer's way.
3902      *
3903      * Flag to make the status bar not expandable.  Unless you also
3904      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3905      */
3906     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3907     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3908 
3909     /**
3910      * @hide
3911      *
3912      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3913      * out of the public fields to keep the undefined bits out of the developer's way.
3914      *
3915      * Flag to hide notification icons and scrolling ticker text.
3916      */
3917     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3918 
3919     /**
3920      * @hide
3921      *
3922      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3923      * out of the public fields to keep the undefined bits out of the developer's way.
3924      *
3925      * Flag to disable incoming notification alerts.  This will not block
3926      * icons, but it will block sound, vibrating and other visual or aural notifications.
3927      */
3928     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3929 
3930     /**
3931      * @hide
3932      *
3933      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3934      * out of the public fields to keep the undefined bits out of the developer's way.
3935      *
3936      * Flag to hide only the scrolling ticker.  Note that
3937      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3938      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3939      */
3940     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3941 
3942     /**
3943      * @hide
3944      *
3945      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3946      * out of the public fields to keep the undefined bits out of the developer's way.
3947      *
3948      * Flag to hide the center system info area.
3949      */
3950     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3951 
3952     /**
3953      * @hide
3954      *
3955      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3956      * out of the public fields to keep the undefined bits out of the developer's way.
3957      *
3958      * Flag to hide only the home button.  Don't use this
3959      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3960      */
3961     @UnsupportedAppUsage
3962     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3963 
3964     /**
3965      * @hide
3966      *
3967      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3968      * out of the public fields to keep the undefined bits out of the developer's way.
3969      *
3970      * Flag to hide only the back button. Don't use this
3971      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3972      */
3973     @UnsupportedAppUsage
3974     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3975 
3976     /**
3977      * @hide
3978      *
3979      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3980      * out of the public fields to keep the undefined bits out of the developer's way.
3981      *
3982      * Flag to hide only the clock.  You might use this if your activity has
3983      * its own clock making the status bar's clock redundant.
3984      */
3985     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3986 
3987     /**
3988      * @hide
3989      *
3990      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3991      * out of the public fields to keep the undefined bits out of the developer's way.
3992      *
3993      * Flag to hide only the recent apps button. Don't use this
3994      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3995      */
3996     @UnsupportedAppUsage
3997     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3998 
3999     /**
4000      * @hide
4001      *
4002      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4003      * out of the public fields to keep the undefined bits out of the developer's way.
4004      *
4005      * Flag to disable the global search gesture. Don't use this
4006      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4007      */
4008     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
4009 
4010     /**
4011      * @hide
4012      *
4013      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4014      * out of the public fields to keep the undefined bits out of the developer's way.
4015      *
4016      * Flag to disable the ongoing call chip.
4017      */
4018     public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
4019 
4020     /**
4021      * @hide
4022      */
4023     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4024 
4025     /**
4026      * These are the system UI flags that can be cleared by events outside
4027      * of an application.  Currently this is just the ability to tap on the
4028      * screen while hiding the navigation bar to have it return.
4029      * @hide
4030      */
4031     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4032             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4033             | SYSTEM_UI_FLAG_FULLSCREEN;
4034 
4035     /**
4036      * Flags that can impact the layout in relation to system UI.
4037      *
4038      * @deprecated System UI layout flags are deprecated.
4039      */
4040     @Deprecated
4041     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4042             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4043             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4044 
4045     /** @hide */
4046     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4047             FIND_VIEWS_WITH_TEXT,
4048             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4049     })
4050     @Retention(RetentionPolicy.SOURCE)
4051     public @interface FindViewFlags {}
4052 
4053     /**
4054      * Find views that render the specified text.
4055      *
4056      * @see #findViewsWithText(ArrayList, CharSequence, int)
4057      */
4058     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4059 
4060     /**
4061      * Find find views that contain the specified content description.
4062      *
4063      * @see #findViewsWithText(ArrayList, CharSequence, int)
4064      */
4065     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4066 
4067     /**
4068      * Find views that contain {@link AccessibilityNodeProvider}. Such
4069      * a View is a root of virtual view hierarchy and may contain the searched
4070      * text. If this flag is set Views with providers are automatically
4071      * added and it is a responsibility of the client to call the APIs of
4072      * the provider to determine whether the virtual tree rooted at this View
4073      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4074      * representing the virtual views with this text.
4075      *
4076      * @see #findViewsWithText(ArrayList, CharSequence, int)
4077      *
4078      * @hide
4079      */
4080     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4081 
4082     /**
4083      * The undefined cursor position.
4084      *
4085      * @hide
4086      */
4087     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4088 
4089     /**
4090      * Indicates that the screen has changed state and is now off.
4091      *
4092      * @see #onScreenStateChanged(int)
4093      */
4094     public static final int SCREEN_STATE_OFF = 0x0;
4095 
4096     /**
4097      * Indicates that the screen has changed state and is now on.
4098      *
4099      * @see #onScreenStateChanged(int)
4100      */
4101     public static final int SCREEN_STATE_ON = 0x1;
4102 
4103     /**
4104      * Indicates no axis of view scrolling.
4105      */
4106     public static final int SCROLL_AXIS_NONE = 0;
4107 
4108     /**
4109      * Indicates scrolling along the horizontal axis.
4110      */
4111     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4112 
4113     /**
4114      * Indicates scrolling along the vertical axis.
4115      */
4116     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4117 
4118     /**
4119      * Controls the over-scroll mode for this view.
4120      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4121      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4122      * and {@link #OVER_SCROLL_NEVER}.
4123      */
4124     private int mOverScrollMode;
4125 
4126     /**
4127      * The parent this view is attached to.
4128      * {@hide}
4129      *
4130      * @see #getParent()
4131      */
4132     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4133     protected ViewParent mParent;
4134 
4135     /**
4136      * {@hide}
4137      *
4138      * Not available for general use. If you need help, hang up and then dial one of the following
4139      * public APIs:
4140      *
4141      * @see #isAttachedToWindow() for current attach state
4142      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4143      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4144      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4145      * @see #getHandler() for posting messages to this view's UI thread/looper
4146      * @see #getParent() for interacting with the parent chain
4147      * @see #getWindowToken() for the current window token
4148      * @see #getRootView() for the view at the root of the attached hierarchy
4149      * @see #getDisplay() for the Display this view is presented on
4150      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4151      * @see #hasWindowFocus() for whether the attached window is currently focused
4152      * @see #getWindowVisibility() for checking the visibility of the attached window
4153      */
4154     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4155     AttachInfo mAttachInfo;
4156 
4157     /**
4158      * {@hide}
4159      */
4160     @ViewDebug.ExportedProperty(flagMapping = {
4161         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4162                 name = "FORCE_LAYOUT"),
4163         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4164                 name = "LAYOUT_REQUIRED"),
4165         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4166             name = "DRAWING_CACHE_INVALID", outputIf = false),
4167         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4168         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4169         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4170     }, formatToHexString = true)
4171 
4172     /* @hide */
4173     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4174     public int mPrivateFlags;
4175     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4176     int mPrivateFlags2;
4177     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4178     int mPrivateFlags3;
4179 
4180     private int mPrivateFlags4;
4181 
4182     /**
4183      * This view's request for the visibility of the status bar.
4184      * @hide
4185      */
4186     @ViewDebug.ExportedProperty(flagMapping = {
4187             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4188                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4189                     name = "LOW_PROFILE"),
4190             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4191                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4192                     name = "HIDE_NAVIGATION"),
4193             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4194                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4195                     name = "FULLSCREEN"),
4196             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4197                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4198                     name = "LAYOUT_STABLE"),
4199             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4200                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4201                     name = "LAYOUT_HIDE_NAVIGATION"),
4202             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4203                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4204                     name = "LAYOUT_FULLSCREEN"),
4205             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4206                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4207                     name = "IMMERSIVE"),
4208             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4209                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4210                     name = "IMMERSIVE_STICKY"),
4211             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4212                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4213                     name = "LIGHT_STATUS_BAR"),
4214             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4215                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4216                     name = "LIGHT_NAVIGATION_BAR"),
4217             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4218                     equals = STATUS_BAR_DISABLE_EXPAND,
4219                     name = "STATUS_BAR_DISABLE_EXPAND"),
4220             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4221                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4222                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4223             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4224                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4225                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4226             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4227                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4228                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4229             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4230                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4231                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4232             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4233                     equals = STATUS_BAR_DISABLE_HOME,
4234                     name = "STATUS_BAR_DISABLE_HOME"),
4235             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4236                     equals = STATUS_BAR_DISABLE_BACK,
4237                     name = "STATUS_BAR_DISABLE_BACK"),
4238             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4239                     equals = STATUS_BAR_DISABLE_CLOCK,
4240                     name = "STATUS_BAR_DISABLE_CLOCK"),
4241             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4242                     equals = STATUS_BAR_DISABLE_RECENT,
4243                     name = "STATUS_BAR_DISABLE_RECENT"),
4244             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4245                     equals = STATUS_BAR_DISABLE_SEARCH,
4246                     name = "STATUS_BAR_DISABLE_SEARCH"),
4247             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4248                     equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4249                     name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
4250     }, formatToHexString = true)
4251     @SystemUiVisibility
4252     int mSystemUiVisibility;
4253 
4254     /**
4255      * @hide
4256      */
4257     @IntDef(flag = true, prefix = "", value = {
4258             SYSTEM_UI_FLAG_LOW_PROFILE,
4259             SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4260             SYSTEM_UI_FLAG_FULLSCREEN,
4261             SYSTEM_UI_FLAG_LAYOUT_STABLE,
4262             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4263             SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4264             SYSTEM_UI_FLAG_IMMERSIVE,
4265             SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4266             SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4267             SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4268             STATUS_BAR_DISABLE_EXPAND,
4269             STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4270             STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4271             STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4272             STATUS_BAR_DISABLE_SYSTEM_INFO,
4273             STATUS_BAR_DISABLE_HOME,
4274             STATUS_BAR_DISABLE_BACK,
4275             STATUS_BAR_DISABLE_CLOCK,
4276             STATUS_BAR_DISABLE_RECENT,
4277             STATUS_BAR_DISABLE_SEARCH,
4278             STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4279     })
4280     @Retention(RetentionPolicy.SOURCE)
4281     public @interface SystemUiVisibility {}
4282 
4283     /**
4284      * Reference count for transient state.
4285      * @see #setHasTransientState(boolean)
4286      */
4287     int mTransientStateCount = 0;
4288 
4289     /**
4290      * Count of how many windows this view has been attached to.
4291      */
4292     int mWindowAttachCount;
4293 
4294     /**
4295      * The layout parameters associated with this view and used by the parent
4296      * {@link android.view.ViewGroup} to determine how this view should be
4297      * laid out.
4298      *
4299      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4300      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4301      * state correctness of the class.
4302      * {@hide}
4303      */
4304     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4305     protected ViewGroup.LayoutParams mLayoutParams;
4306 
4307     /**
4308      * The view flags hold various views states.
4309      *
4310      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4311      * triggering updates.
4312      * {@hide}
4313      */
4314     @ViewDebug.ExportedProperty(formatToHexString = true)
4315     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4316     int mViewFlags;
4317 
4318     static class TransformationInfo {
4319         /**
4320          * The transform matrix for the View. This transform is calculated internally
4321          * based on the translation, rotation, and scale properties.
4322          *
4323          * Do *not* use this variable directly; instead call getMatrix(), which will
4324          * load the value from the View's RenderNode.
4325          */
4326         private final Matrix mMatrix = new Matrix();
4327 
4328         /**
4329          * The inverse transform matrix for the View. This transform is calculated
4330          * internally based on the translation, rotation, and scale properties.
4331          *
4332          * Do *not* use this variable directly; instead call getInverseMatrix(),
4333          * which will load the value from the View's RenderNode.
4334          */
4335         private Matrix mInverseMatrix;
4336 
4337         /**
4338          * The opacity of the View. This is a value from 0 to 1, where 0 means
4339          * completely transparent and 1 means completely opaque.
4340          */
4341         @ViewDebug.ExportedProperty
4342         private float mAlpha = 1f;
4343 
4344         /**
4345          * The opacity of the view as manipulated by the Fade transition. This is a
4346          * property only used by transitions, which is composited with the other alpha
4347          * values to calculate the final visual alpha value.
4348          */
4349         float mTransitionAlpha = 1f;
4350     }
4351 
4352     /** @hide */
4353     @UnsupportedAppUsage
4354     public TransformationInfo mTransformationInfo;
4355 
4356     /**
4357      * Current clip bounds. to which all drawing of this view are constrained.
4358      */
4359     @ViewDebug.ExportedProperty(category = "drawing")
4360     Rect mClipBounds = null;
4361 
4362     private boolean mLastIsOpaque;
4363 
4364     /**
4365      * The distance in pixels from the left edge of this view's parent
4366      * to the left edge of this view.
4367      * {@hide}
4368      */
4369     @ViewDebug.ExportedProperty(category = "layout")
4370     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4371     protected int mLeft;
4372     /**
4373      * The distance in pixels from the left edge of this view's parent
4374      * to the right edge of this view.
4375      * {@hide}
4376      */
4377     @ViewDebug.ExportedProperty(category = "layout")
4378     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4379     protected int mRight;
4380     /**
4381      * The distance in pixels from the top edge of this view's parent
4382      * to the top edge of this view.
4383      * {@hide}
4384      */
4385     @ViewDebug.ExportedProperty(category = "layout")
4386     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4387     protected int mTop;
4388     /**
4389      * The distance in pixels from the top edge of this view's parent
4390      * to the bottom edge of this view.
4391      * {@hide}
4392      */
4393     @ViewDebug.ExportedProperty(category = "layout")
4394     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4395     protected int mBottom;
4396 
4397     /**
4398      * The offset, in pixels, by which the content of this view is scrolled
4399      * horizontally.
4400      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4401      * accessing these directly.
4402      * {@hide}
4403      */
4404     @ViewDebug.ExportedProperty(category = "scrolling")
4405     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4406     protected int mScrollX;
4407     /**
4408      * The offset, in pixels, by which the content of this view is scrolled
4409      * vertically.
4410      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4411      * accessing these directly.
4412      * {@hide}
4413      */
4414     @ViewDebug.ExportedProperty(category = "scrolling")
4415     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4416     protected int mScrollY;
4417 
4418     /**
4419      * The final computed left padding in pixels that is used for drawing. This is the distance in
4420      * pixels between the left edge of this view and the left edge of its content.
4421      * {@hide}
4422      */
4423     @ViewDebug.ExportedProperty(category = "padding")
4424     @UnsupportedAppUsage
4425     protected int mPaddingLeft = 0;
4426     /**
4427      * The final computed right padding in pixels that is used for drawing. This is the distance in
4428      * pixels between the right edge of this view and the right edge of its content.
4429      * {@hide}
4430      */
4431     @ViewDebug.ExportedProperty(category = "padding")
4432     @UnsupportedAppUsage
4433     protected int mPaddingRight = 0;
4434     /**
4435      * The final computed top padding in pixels that is used for drawing. This is the distance in
4436      * pixels between the top edge of this view and the top edge of its content.
4437      * {@hide}
4438      */
4439     @ViewDebug.ExportedProperty(category = "padding")
4440     @UnsupportedAppUsage
4441     protected int mPaddingTop;
4442     /**
4443      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4444      * pixels between the bottom edge of this view and the bottom edge of its content.
4445      * {@hide}
4446      */
4447     @ViewDebug.ExportedProperty(category = "padding")
4448     @UnsupportedAppUsage
4449     protected int mPaddingBottom;
4450 
4451     /**
4452      * The layout insets in pixels, that is the distance in pixels between the
4453      * visible edges of this view its bounds.
4454      */
4455     private Insets mLayoutInsets;
4456 
4457     /**
4458      * Briefly describes the state of the view and is primarily used for accessibility support.
4459      */
4460     private CharSequence mStateDescription;
4461 
4462     /**
4463      * Briefly describes the view and is primarily used for accessibility support.
4464      */
4465     private CharSequence mContentDescription;
4466 
4467     /**
4468      * If this view represents a distinct part of the window, it can have a title that labels the
4469      * area.
4470      */
4471     private CharSequence mAccessibilityPaneTitle;
4472 
4473     /**
4474      * Specifies the id of a view for which this view serves as a label for
4475      * accessibility purposes.
4476      */
4477     private int mLabelForId = View.NO_ID;
4478 
4479     /**
4480      * Predicate for matching labeled view id with its label for
4481      * accessibility purposes.
4482      */
4483     private MatchLabelForPredicate mMatchLabelForPredicate;
4484 
4485     /**
4486      * Specifies a view before which this one is visited in accessibility traversal.
4487      */
4488     private int mAccessibilityTraversalBeforeId = NO_ID;
4489 
4490     /**
4491      * Specifies a view after which this one is visited in accessibility traversal.
4492      */
4493     private int mAccessibilityTraversalAfterId = NO_ID;
4494 
4495     /**
4496      * Predicate for matching a view by its id.
4497      */
4498     private MatchIdPredicate mMatchIdPredicate;
4499 
4500     /**
4501      * The right padding after RTL resolution, but before taking account of scroll bars.
4502      *
4503      * @hide
4504      */
4505     @ViewDebug.ExportedProperty(category = "padding")
4506     protected int mUserPaddingRight;
4507 
4508     /**
4509      * The resolved bottom padding before taking account of scroll bars.
4510      *
4511      * @hide
4512      */
4513     @ViewDebug.ExportedProperty(category = "padding")
4514     protected int mUserPaddingBottom;
4515 
4516     /**
4517      * The left padding after RTL resolution, but before taking account of scroll bars.
4518      *
4519      * @hide
4520      */
4521     @ViewDebug.ExportedProperty(category = "padding")
4522     protected int mUserPaddingLeft;
4523 
4524     /**
4525      * Cache the paddingStart set by the user to append to the scrollbar's size.
4526      *
4527      */
4528     @ViewDebug.ExportedProperty(category = "padding")
4529     int mUserPaddingStart;
4530 
4531     /**
4532      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4533      *
4534      */
4535     @ViewDebug.ExportedProperty(category = "padding")
4536     int mUserPaddingEnd;
4537 
4538     /**
4539      * The left padding as set by a setter method, a background's padding, or via XML property
4540      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4541      *
4542      * @hide
4543      */
4544     int mUserPaddingLeftInitial;
4545 
4546     /**
4547      * The right padding as set by a setter method, a background's padding, or via XML property
4548      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4549      *
4550      * @hide
4551      */
4552     int mUserPaddingRightInitial;
4553 
4554     /**
4555      * Default undefined padding
4556      */
4557     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4558 
4559     /**
4560      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4561      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4562      */
4563     private boolean mLeftPaddingDefined = false;
4564 
4565     /**
4566      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4567      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4568      */
4569     private boolean mRightPaddingDefined = false;
4570 
4571     /**
4572      * @hide
4573      */
4574     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4575     /**
4576      * @hide
4577      */
4578     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4579 
4580     private LongSparseLongArray mMeasureCache;
4581 
4582     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4583     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4584     private Drawable mBackground;
4585     private TintInfo mBackgroundTint;
4586 
4587     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4588     private ForegroundInfo mForegroundInfo;
4589 
4590     private Drawable mScrollIndicatorDrawable;
4591 
4592     /**
4593      * RenderNode used for backgrounds.
4594      * <p>
4595      * When non-null and valid, this is expected to contain an up-to-date copy
4596      * of the background drawable. It is cleared on temporary detach, and reset
4597      * on cleanup.
4598      * @hide
4599      */
4600     RenderNode mBackgroundRenderNode;
4601 
4602     @UnsupportedAppUsage
4603     private int mBackgroundResource;
4604     private boolean mBackgroundSizeChanged;
4605 
4606     /** The default focus highlight.
4607      * @see #mDefaultFocusHighlightEnabled
4608      * @see Drawable#hasFocusStateSpecified()
4609      */
4610     private Drawable mDefaultFocusHighlight;
4611     private Drawable mDefaultFocusHighlightCache;
4612     private boolean mDefaultFocusHighlightSizeChanged;
4613     /**
4614      * True if the default focus highlight is needed on the target device.
4615      */
4616     private static boolean sUseDefaultFocusHighlight;
4617 
4618     /**
4619      * True if zero-sized views can be focused.
4620      */
4621     private static boolean sCanFocusZeroSized;
4622 
4623     /**
4624      * Always assign focus if a focusable View is available.
4625      */
4626     private static boolean sAlwaysAssignFocus;
4627 
4628     private String mTransitionName;
4629 
4630     static class TintInfo {
4631         ColorStateList mTintList;
4632         BlendMode mBlendMode;
4633         boolean mHasTintMode;
4634         boolean mHasTintList;
4635     }
4636 
4637     private static class ForegroundInfo {
4638         private Drawable mDrawable;
4639         private TintInfo mTintInfo;
4640         private int mGravity = Gravity.FILL;
4641         private boolean mInsidePadding = true;
4642         private boolean mBoundsChanged = true;
4643         private final Rect mSelfBounds = new Rect();
4644         private final Rect mOverlayBounds = new Rect();
4645     }
4646 
4647     static class ListenerInfo {
4648 
4649         @UnsupportedAppUsage
ListenerInfo()4650         ListenerInfo() {
4651         }
4652 
4653         /**
4654          * Listener used to dispatch focus change events.
4655          * This field should be made private, so it is hidden from the SDK.
4656          * {@hide}
4657          */
4658         @UnsupportedAppUsage
4659         protected OnFocusChangeListener mOnFocusChangeListener;
4660 
4661         /**
4662          * Listeners for layout change events.
4663          */
4664         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4665 
4666         protected OnScrollChangeListener mOnScrollChangeListener;
4667 
4668         /**
4669          * Listeners for attach events.
4670          */
4671         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4672 
4673         /**
4674          * Listener used to dispatch click events.
4675          * This field should be made private, so it is hidden from the SDK.
4676          * {@hide}
4677          */
4678         @UnsupportedAppUsage
4679         public OnClickListener mOnClickListener;
4680 
4681         /**
4682          * Listener used to dispatch long click events.
4683          * This field should be made private, so it is hidden from the SDK.
4684          * {@hide}
4685          */
4686         @UnsupportedAppUsage
4687         protected OnLongClickListener mOnLongClickListener;
4688 
4689         /**
4690          * Listener used to dispatch context click events. This field should be made private, so it
4691          * is hidden from the SDK.
4692          * {@hide}
4693          */
4694         protected OnContextClickListener mOnContextClickListener;
4695 
4696         /**
4697          * Listener used to build the context menu.
4698          * This field should be made private, so it is hidden from the SDK.
4699          * {@hide}
4700          */
4701         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4702         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4703 
4704         @UnsupportedAppUsage
4705         private OnKeyListener mOnKeyListener;
4706 
4707         @UnsupportedAppUsage
4708         private OnTouchListener mOnTouchListener;
4709 
4710         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4711         private OnHoverListener mOnHoverListener;
4712 
4713         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4714         private OnGenericMotionListener mOnGenericMotionListener;
4715 
4716         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4717         private OnDragListener mOnDragListener;
4718 
4719         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4720 
4721         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4722 
4723         OnCapturedPointerListener mOnCapturedPointerListener;
4724 
4725         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4726 
4727         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
4728 
4729         /**
4730          * This lives here since it's only valid for interactive views. This list is null until the
4731          * first use.
4732          */
4733         private List<Rect> mSystemGestureExclusionRects = null;
4734 
4735         /**
4736          * Used to track {@link #mSystemGestureExclusionRects}
4737          */
4738         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4739 
4740         /**
4741          * Allows the application to implement custom scroll capture support.
4742          */
4743         ScrollCaptureCallback mScrollCaptureCallback;
4744 
4745         @Nullable
4746         private OnReceiveContentListener mOnReceiveContentListener;
4747     }
4748 
4749     @UnsupportedAppUsage
4750     ListenerInfo mListenerInfo;
4751 
4752     private static class TooltipInfo {
4753         /**
4754          * Text to be displayed in a tooltip popup.
4755          */
4756         @Nullable
4757         CharSequence mTooltipText;
4758 
4759         /**
4760          * View-relative position of the tooltip anchor point.
4761          */
4762         int mAnchorX;
4763         int mAnchorY;
4764 
4765         /**
4766          * The tooltip popup.
4767          */
4768         @Nullable
4769         TooltipPopup mTooltipPopup;
4770 
4771         /**
4772          * Set to true if the tooltip was shown as a result of a long click.
4773          */
4774         boolean mTooltipFromLongClick;
4775 
4776         /**
4777          * Keep these Runnables so that they can be used to reschedule.
4778          */
4779         Runnable mShowTooltipRunnable;
4780         Runnable mHideTooltipRunnable;
4781 
4782         /**
4783          * Hover move is ignored if it is within this distance in pixels from the previous one.
4784          */
4785         int mHoverSlop;
4786 
4787         /**
4788          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4789          * different from the previously stored position. Ignoring insignificant changes
4790          * filters out the jitter which is typical for such input sources as stylus.
4791          *
4792          * @return True if the position has been updated.
4793          */
updateAnchorPos(MotionEvent event)4794         private boolean updateAnchorPos(MotionEvent event) {
4795             final int newAnchorX = (int) event.getX();
4796             final int newAnchorY = (int) event.getY();
4797             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4798                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4799                 return false;
4800             }
4801             mAnchorX = newAnchorX;
4802             mAnchorY = newAnchorY;
4803             return true;
4804         }
4805 
4806         /**
4807          *  Clear the anchor position to ensure that the next change is considered significant.
4808          */
clearAnchorPos()4809         private void clearAnchorPos() {
4810             mAnchorX = Integer.MAX_VALUE;
4811             mAnchorY = Integer.MAX_VALUE;
4812         }
4813     }
4814 
4815     TooltipInfo mTooltipInfo;
4816 
4817     // Temporary values used to hold (x,y) coordinates when delegating from the
4818     // two-arg performLongClick() method to the legacy no-arg version.
4819     private float mLongClickX = Float.NaN;
4820     private float mLongClickY = Float.NaN;
4821 
4822     /**
4823      * The application environment this view lives in.
4824      * This field should be made private, so it is hidden from the SDK.
4825      * {@hide}
4826      */
4827     @ViewDebug.ExportedProperty(deepExport = true)
4828     @UnsupportedAppUsage
4829     @UiContext
4830     protected Context mContext;
4831 
4832     @UnsupportedAppUsage
4833     private final Resources mResources;
4834 
4835     @UnsupportedAppUsage
4836     private ScrollabilityCache mScrollCache;
4837 
4838     private int[] mDrawableState = null;
4839 
4840     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4841 
4842     /**
4843      * Animator that automatically runs based on state changes.
4844      */
4845     private StateListAnimator mStateListAnimator;
4846 
4847     /**
4848      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4849      * the user may specify which view to go to next.
4850      */
4851     private int mNextFocusLeftId = View.NO_ID;
4852 
4853     /**
4854      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4855      * the user may specify which view to go to next.
4856      */
4857     private int mNextFocusRightId = View.NO_ID;
4858 
4859     /**
4860      * When this view has focus and the next focus is {@link #FOCUS_UP},
4861      * the user may specify which view to go to next.
4862      */
4863     private int mNextFocusUpId = View.NO_ID;
4864 
4865     /**
4866      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4867      * the user may specify which view to go to next.
4868      */
4869     private int mNextFocusDownId = View.NO_ID;
4870 
4871     /**
4872      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4873      * the user may specify which view to go to next.
4874      */
4875     int mNextFocusForwardId = View.NO_ID;
4876 
4877     /**
4878      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4879      *
4880      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4881      */
4882     int mNextClusterForwardId = View.NO_ID;
4883 
4884     /**
4885      * Whether this View should use a default focus highlight when it gets focused but doesn't
4886      * have {@link android.R.attr#state_focused} defined in its background.
4887      */
4888     boolean mDefaultFocusHighlightEnabled = true;
4889 
4890     private CheckForLongPress mPendingCheckForLongPress;
4891     @UnsupportedAppUsage
4892     private CheckForTap mPendingCheckForTap = null;
4893     private PerformClick mPerformClick;
4894     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4895     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
4896     private UnsetPressedState mUnsetPressedState;
4897 
4898     /**
4899      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4900      * up event while a long press is invoked as soon as the long press duration is reached, so
4901      * a long press could be performed before the tap is checked, in which case the tap's action
4902      * should not be invoked.
4903      */
4904     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4905     private boolean mHasPerformedLongPress;
4906 
4907     /**
4908      * Whether a context click button is currently pressed down. This is true when the stylus is
4909      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4910      * pressed. This is false once the button is released or if the stylus has been lifted.
4911      */
4912     private boolean mInContextButtonPress;
4913 
4914     /**
4915      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4916      * true after a stylus button press has occured, when the next up event should not be recognized
4917      * as a tap.
4918      */
4919     private boolean mIgnoreNextUpEvent;
4920 
4921     /**
4922      * The minimum height of the view. We'll try our best to have the height
4923      * of this view to at least this amount.
4924      */
4925     @ViewDebug.ExportedProperty(category = "measurement")
4926     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4927     private int mMinHeight;
4928 
4929     /**
4930      * The minimum width of the view. We'll try our best to have the width
4931      * of this view to at least this amount.
4932      */
4933     @ViewDebug.ExportedProperty(category = "measurement")
4934     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4935     private int mMinWidth;
4936 
4937     /**
4938      * The delegate to handle touch events that are physically in this view
4939      * but should be handled by another view.
4940      */
4941     private TouchDelegate mTouchDelegate = null;
4942 
4943     /**
4944      * While touch exploration is in use, set to true when hovering across boundaries and
4945      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
4946      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
4947      * {@link MotionEvent#ACTION_HOVER_EXIT}.
4948      * Note that children of view group are excluded in the touch area.
4949      * @see #dispatchTouchExplorationHoverEvent
4950      */
4951     private boolean mHoveringTouchDelegate = false;
4952 
4953     /**
4954      * Solid color to use as a background when creating the drawing cache. Enables
4955      * the cache to use 16 bit bitmaps instead of 32 bit.
4956      */
4957     private int mDrawingCacheBackgroundColor = 0;
4958 
4959     /**
4960      * Special tree observer used when mAttachInfo is null.
4961      */
4962     private ViewTreeObserver mFloatingTreeObserver;
4963 
4964     /**
4965      * Cache the touch slop from the context that created the view.
4966      */
4967     private int mTouchSlop;
4968 
4969     /**
4970      * Cache the ambiguous gesture multiplier from the context that created the view.
4971      */
4972     private float mAmbiguousGestureMultiplier;
4973 
4974     /**
4975      * Object that handles automatic animation of view properties.
4976      */
4977     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4978     private ViewPropertyAnimator mAnimator = null;
4979 
4980     /**
4981      * List of registered FrameMetricsObservers.
4982      */
4983     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4984 
4985     /**
4986      * Flag indicating that a drag can cross window boundaries.  When
4987      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4988      * with this flag set, all visible applications with targetSdkVersion >=
4989      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4990      * in the drag operation and receive the dragged content.
4991      *
4992      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4993      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4994      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4995      */
4996     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4997 
4998     /**
4999      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5000      * request read access to the content URI(s) contained in the {@link ClipData} object.
5001      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5002      */
5003     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5004 
5005     /**
5006      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5007      * request write access to the content URI(s) contained in the {@link ClipData} object.
5008      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5009      */
5010     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5011 
5012     /**
5013      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5014      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5015      * reboots until explicitly revoked with
5016      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5017      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5018      */
5019     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5020             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5021 
5022     /**
5023      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5024      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5025      * match against the original granted URI.
5026      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5027      */
5028     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5029             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5030 
5031     /**
5032      * Flag indicating that the drag shadow will be opaque.  When
5033      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5034      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5035      */
5036     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5037 
5038     /**
5039      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5040      */
5041     private float mVerticalScrollFactor;
5042 
5043     /**
5044      * Position of the vertical scroll bar.
5045      */
5046     @UnsupportedAppUsage
5047     private int mVerticalScrollbarPosition;
5048 
5049     /**
5050      * Position the scroll bar at the default position as determined by the system.
5051      */
5052     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5053 
5054     /**
5055      * Position the scroll bar along the left edge.
5056      */
5057     public static final int SCROLLBAR_POSITION_LEFT = 1;
5058 
5059     /**
5060      * Position the scroll bar along the right edge.
5061      */
5062     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5063 
5064     /**
5065      * Indicates that the view does not have a layer.
5066      *
5067      * @see #getLayerType()
5068      * @see #setLayerType(int, android.graphics.Paint)
5069      * @see #LAYER_TYPE_SOFTWARE
5070      * @see #LAYER_TYPE_HARDWARE
5071      */
5072     public static final int LAYER_TYPE_NONE = 0;
5073 
5074     /**
5075      * <p>Indicates that the view has a software layer. A software layer is backed
5076      * by a bitmap and causes the view to be rendered using Android's software
5077      * rendering pipeline, even if hardware acceleration is enabled.</p>
5078      *
5079      * <p>Software layers have various usages:</p>
5080      * <p>When the application is not using hardware acceleration, a software layer
5081      * is useful to apply a specific color filter and/or blending mode and/or
5082      * translucency to a view and all its children.</p>
5083      * <p>When the application is using hardware acceleration, a software layer
5084      * is useful to render drawing primitives not supported by the hardware
5085      * accelerated pipeline. It can also be used to cache a complex view tree
5086      * into a texture and reduce the complexity of drawing operations. For instance,
5087      * when animating a complex view tree with a translation, a software layer can
5088      * be used to render the view tree only once.</p>
5089      * <p>Software layers should be avoided when the affected view tree updates
5090      * often. Every update will require to re-render the software layer, which can
5091      * potentially be slow (particularly when hardware acceleration is turned on
5092      * since the layer will have to be uploaded into a hardware texture after every
5093      * update.)</p>
5094      *
5095      * @see #getLayerType()
5096      * @see #setLayerType(int, android.graphics.Paint)
5097      * @see #LAYER_TYPE_NONE
5098      * @see #LAYER_TYPE_HARDWARE
5099      */
5100     public static final int LAYER_TYPE_SOFTWARE = 1;
5101 
5102     /**
5103      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5104      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5105      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5106      * rendering pipeline, but only if hardware acceleration is turned on for the
5107      * view hierarchy. When hardware acceleration is turned off, hardware layers
5108      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5109      *
5110      * <p>A hardware layer is useful to apply a specific color filter and/or
5111      * blending mode and/or translucency to a view and all its children.</p>
5112      * <p>A hardware layer can be used to cache a complex view tree into a
5113      * texture and reduce the complexity of drawing operations. For instance,
5114      * when animating a complex view tree with a translation, a hardware layer can
5115      * be used to render the view tree only once.</p>
5116      * <p>A hardware layer can also be used to increase the rendering quality when
5117      * rotation transformations are applied on a view. It can also be used to
5118      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5119      *
5120      * @see #getLayerType()
5121      * @see #setLayerType(int, android.graphics.Paint)
5122      * @see #LAYER_TYPE_NONE
5123      * @see #LAYER_TYPE_SOFTWARE
5124      */
5125     public static final int LAYER_TYPE_HARDWARE = 2;
5126 
5127     /** @hide */
5128     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5129             LAYER_TYPE_NONE,
5130             LAYER_TYPE_SOFTWARE,
5131             LAYER_TYPE_HARDWARE
5132     })
5133     @Retention(RetentionPolicy.SOURCE)
5134     public @interface LayerType {}
5135 
5136     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
5137             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
5138             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
5139             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
5140     })
5141     int mLayerType = LAYER_TYPE_NONE;
5142     Paint mLayerPaint;
5143 
5144     /**
5145      * Set to true when drawing cache is enabled and cannot be created.
5146      *
5147      * @hide
5148      */
5149     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5150     public boolean mCachingFailed;
5151     @UnsupportedAppUsage
5152     private Bitmap mDrawingCache;
5153     @UnsupportedAppUsage
5154     private Bitmap mUnscaledDrawingCache;
5155 
5156     /**
5157      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5158      * <p>
5159      * When non-null and valid, this is expected to contain an up-to-date copy
5160      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5161      * cleanup.
5162      */
5163     @UnsupportedAppUsage
5164     final RenderNode mRenderNode;
5165 
5166     /**
5167      * Set to true when the view is sending hover accessibility events because it
5168      * is the innermost hovered view.
5169      */
5170     private boolean mSendingHoverAccessibilityEvents;
5171 
5172     /**
5173      * Delegate for injecting accessibility functionality.
5174      */
5175     @UnsupportedAppUsage
5176     AccessibilityDelegate mAccessibilityDelegate;
5177 
5178     /**
5179      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5180      * and add/remove objects to/from the overlay directly through the Overlay methods.
5181      */
5182     ViewOverlay mOverlay;
5183 
5184     /**
5185      * The currently active parent view for receiving delegated nested scrolling events.
5186      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5187      * by {@link #stopNestedScroll()} at the same point where we clear
5188      * requestDisallowInterceptTouchEvent.
5189      */
5190     private ViewParent mNestedScrollingParent;
5191 
5192     /**
5193      * Consistency verifier for debugging purposes.
5194      * @hide
5195      */
5196     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5197             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5198                     new InputEventConsistencyVerifier(this, 0) : null;
5199 
5200     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5201 
5202     private int[] mTempNestedScrollConsumed;
5203 
5204     /**
5205      * An overlay is going to draw this View instead of being drawn as part of this
5206      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5207      * when this view is invalidated.
5208      */
5209     GhostView mGhostView;
5210 
5211     /**
5212      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5213      * @hide
5214      */
5215     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5216     public String[] mAttributes;
5217 
5218     /**
5219      * Maps a Resource id to its name.
5220      */
5221     private static SparseArray<String> mAttributeMap;
5222 
5223     /**
5224      * Queue of pending runnables. Used to postpone calls to post() until this
5225      * view is attached and has a handler.
5226      */
5227     private HandlerActionQueue mRunQueue;
5228 
5229     /**
5230      * The pointer icon when the mouse hovers on this view. The default is null.
5231      */
5232     private PointerIcon mPointerIcon;
5233 
5234     /**
5235      * @hide
5236      */
5237     @UnsupportedAppUsage
5238     String mStartActivityRequestWho;
5239 
5240     @Nullable
5241     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5242 
5243     /** Used to delay visibility updates sent to the autofill manager */
5244     private Handler mVisibilityChangeForAutofillHandler;
5245 
5246     /**
5247      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5248      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5249      */
5250     @Nullable
5251     private ContentCaptureSession mContentCaptureSession;
5252 
5253     /**
5254      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5255      */
5256     private boolean mContentCaptureSessionCached;
5257 
5258     @LayoutRes
5259     private int mSourceLayoutId = ID_NULL;
5260 
5261     @Nullable
5262     private SparseIntArray mAttributeSourceResId;
5263 
5264     @Nullable
5265     private SparseArray<int[]> mAttributeResolutionStacks;
5266 
5267     @StyleRes
5268     private int mExplicitStyle;
5269 
5270     /**
5271      * Specifies which input source classes should provide unbuffered input events to this view
5272      *
5273      * @see View#requestUnbufferedDispatch(int)
5274      */
5275     @InputSourceClass
5276     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5277 
5278     @Nullable
5279     private String[] mReceiveContentMimeTypes;
5280 
5281     @Nullable
5282     private ViewTranslationCallback mViewTranslationCallback;
5283 
5284     @Nullable
5285 
5286     private ViewTranslationResponse mViewTranslationResponse;
5287 
5288     /**
5289      * Simple constructor to use when creating a view from code.
5290      *
5291      * @param context The Context the view is running in, through which it can
5292      *        access the current theme, resources, etc.
5293      */
View(Context context)5294     public View(Context context) {
5295         mContext = context;
5296         mResources = context != null ? context.getResources() : null;
5297         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5298         // Set some flags defaults
5299         mPrivateFlags2 =
5300                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5301                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5302                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5303                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5304                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5305                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5306 
5307         final ViewConfiguration configuration = ViewConfiguration.get(context);
5308         mTouchSlop = configuration.getScaledTouchSlop();
5309         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5310 
5311         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5312         mUserPaddingStart = UNDEFINED_PADDING;
5313         mUserPaddingEnd = UNDEFINED_PADDING;
5314         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5315 
5316         if (!sCompatibilityDone && context != null) {
5317             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5318 
5319             // Older apps may need this compatibility hack for measurement.
5320             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5321 
5322             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5323             // of whether a layout was requested on that View.
5324             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5325 
5326             // In M and newer, our widgets can pass a "hint" value in the size
5327             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5328             // know what the expected parent size is going to be, so e.g. list items can size
5329             // themselves at 1/3 the size of their container. It breaks older apps though,
5330             // specifically apps that use some popular open source libraries.
5331             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5332 
5333             // Old versions of the platform would give different results from
5334             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5335             // modes, so we always need to run an additional EXACTLY pass.
5336             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5337 
5338             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5339             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5340             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5341 
5342             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5343             // in apps so we target check it to avoid breaking existing apps.
5344             sPreserveMarginParamsInLayoutParamConversion =
5345                     targetSdkVersion >= Build.VERSION_CODES.N;
5346 
5347             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5348 
5349             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5350 
5351             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5352 
5353             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5354                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5355 
5356             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5357 
5358             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5359 
5360             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5361 
5362             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5363 
5364             sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
5365 
5366             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5367 
5368             GradientDrawable.sWrapNegativeAngleMeasurements =
5369                     targetSdkVersion >= Build.VERSION_CODES.Q;
5370 
5371             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5372 
5373             sCompatibilityDone = true;
5374         }
5375     }
5376 
5377     /**
5378      * Constructor that is called when inflating a view from XML. This is called
5379      * when a view is being constructed from an XML file, supplying attributes
5380      * that were specified in the XML file. This version uses a default style of
5381      * 0, so the only attribute values applied are those in the Context's Theme
5382      * and the given AttributeSet.
5383      *
5384      * <p>
5385      * The method onFinishInflate() will be called after all children have been
5386      * added.
5387      *
5388      * @param context The Context the view is running in, through which it can
5389      *        access the current theme, resources, etc.
5390      * @param attrs The attributes of the XML tag that is inflating the view.
5391      * @see #View(Context, AttributeSet, int)
5392      */
5393     public View(Context context, @Nullable AttributeSet attrs) {
5394         this(context, attrs, 0);
5395     }
5396 
5397     /**
5398      * Perform inflation from XML and apply a class-specific base style from a
5399      * theme attribute. This constructor of View allows subclasses to use their
5400      * own base style when they are inflating. For example, a Button class's
5401      * constructor would call this version of the super class constructor and
5402      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5403      * allows the theme's button style to modify all of the base view attributes
5404      * (in particular its background) as well as the Button class's attributes.
5405      *
5406      * @param context The Context the view is running in, through which it can
5407      *        access the current theme, resources, etc.
5408      * @param attrs The attributes of the XML tag that is inflating the view.
5409      * @param defStyleAttr An attribute in the current theme that contains a
5410      *        reference to a style resource that supplies default values for
5411      *        the view. Can be 0 to not look for defaults.
5412      * @see #View(Context, AttributeSet)
5413      */
5414     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5415         this(context, attrs, defStyleAttr, 0);
5416     }
5417 
5418     /**
5419      * Perform inflation from XML and apply a class-specific base style from a
5420      * theme attribute or style resource. This constructor of View allows
5421      * subclasses to use their own base style when they are inflating.
5422      * <p>
5423      * When determining the final value of a particular attribute, there are
5424      * four inputs that come into play:
5425      * <ol>
5426      * <li>Any attribute values in the given AttributeSet.
5427      * <li>The style resource specified in the AttributeSet (named "style").
5428      * <li>The default style specified by <var>defStyleAttr</var>.
5429      * <li>The default style specified by <var>defStyleRes</var>.
5430      * <li>The base values in this theme.
5431      * </ol>
5432      * <p>
5433      * Each of these inputs is considered in-order, with the first listed taking
5434      * precedence over the following ones. In other words, if in the
5435      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5436      * , then the button's text will <em>always</em> be black, regardless of
5437      * what is specified in any of the styles.
5438      *
5439      * @param context The Context the view is running in, through which it can
5440      *        access the current theme, resources, etc.
5441      * @param attrs The attributes of the XML tag that is inflating the view.
5442      * @param defStyleAttr An attribute in the current theme that contains a
5443      *        reference to a style resource that supplies default values for
5444      *        the view. Can be 0 to not look for defaults.
5445      * @param defStyleRes A resource identifier of a style resource that
5446      *        supplies default values for the view, used only if
5447      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5448      *        to not look for defaults.
5449      * @see #View(Context, AttributeSet, int)
5450      */
5451     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5452         this(context);
5453 
5454         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5455 
5456         final TypedArray a = context.obtainStyledAttributes(
5457                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5458 
5459         retrieveExplicitStyle(context.getTheme(), attrs);
5460         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5461                 defStyleAttr, defStyleRes);
5462 
5463         if (sDebugViewAttributes) {
5464             saveAttributeData(attrs, a);
5465         }
5466 
5467         Drawable background = null;
5468 
5469         int leftPadding = -1;
5470         int topPadding = -1;
5471         int rightPadding = -1;
5472         int bottomPadding = -1;
5473         int startPadding = UNDEFINED_PADDING;
5474         int endPadding = UNDEFINED_PADDING;
5475 
5476         int padding = -1;
5477         int paddingHorizontal = -1;
5478         int paddingVertical = -1;
5479 
5480         int viewFlagValues = 0;
5481         int viewFlagMasks = 0;
5482 
5483         boolean setScrollContainer = false;
5484 
5485         int x = 0;
5486         int y = 0;
5487 
5488         float tx = 0;
5489         float ty = 0;
5490         float tz = 0;
5491         float elevation = 0;
5492         float rotation = 0;
5493         float rotationX = 0;
5494         float rotationY = 0;
5495         float sx = 1f;
5496         float sy = 1f;
5497         boolean transformSet = false;
5498 
5499         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5500         int overScrollMode = mOverScrollMode;
5501         boolean initializeScrollbars = false;
5502         boolean initializeScrollIndicators = false;
5503 
5504         boolean startPaddingDefined = false;
5505         boolean endPaddingDefined = false;
5506         boolean leftPaddingDefined = false;
5507         boolean rightPaddingDefined = false;
5508 
5509         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5510 
5511         // Set default values.
5512         viewFlagValues |= FOCUSABLE_AUTO;
5513         viewFlagMasks |= FOCUSABLE_AUTO;
5514 
5515         final int N = a.getIndexCount();
5516         for (int i = 0; i < N; i++) {
5517             int attr = a.getIndex(i);
5518             switch (attr) {
5519                 case com.android.internal.R.styleable.View_background:
5520                     background = a.getDrawable(attr);
5521                     break;
5522                 case com.android.internal.R.styleable.View_padding:
5523                     padding = a.getDimensionPixelSize(attr, -1);
5524                     mUserPaddingLeftInitial = padding;
5525                     mUserPaddingRightInitial = padding;
5526                     leftPaddingDefined = true;
5527                     rightPaddingDefined = true;
5528                     break;
5529                 case com.android.internal.R.styleable.View_paddingHorizontal:
5530                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5531                     mUserPaddingLeftInitial = paddingHorizontal;
5532                     mUserPaddingRightInitial = paddingHorizontal;
5533                     leftPaddingDefined = true;
5534                     rightPaddingDefined = true;
5535                     break;
5536                 case com.android.internal.R.styleable.View_paddingVertical:
5537                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5538                     break;
5539                 case com.android.internal.R.styleable.View_paddingLeft:
5540                     leftPadding = a.getDimensionPixelSize(attr, -1);
5541                     mUserPaddingLeftInitial = leftPadding;
5542                     leftPaddingDefined = true;
5543                     break;
5544                 case com.android.internal.R.styleable.View_paddingTop:
5545                     topPadding = a.getDimensionPixelSize(attr, -1);
5546                     break;
5547                 case com.android.internal.R.styleable.View_paddingRight:
5548                     rightPadding = a.getDimensionPixelSize(attr, -1);
5549                     mUserPaddingRightInitial = rightPadding;
5550                     rightPaddingDefined = true;
5551                     break;
5552                 case com.android.internal.R.styleable.View_paddingBottom:
5553                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5554                     break;
5555                 case com.android.internal.R.styleable.View_paddingStart:
5556                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5557                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5558                     break;
5559                 case com.android.internal.R.styleable.View_paddingEnd:
5560                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5561                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5562                     break;
5563                 case com.android.internal.R.styleable.View_scrollX:
5564                     x = a.getDimensionPixelOffset(attr, 0);
5565                     break;
5566                 case com.android.internal.R.styleable.View_scrollY:
5567                     y = a.getDimensionPixelOffset(attr, 0);
5568                     break;
5569                 case com.android.internal.R.styleable.View_alpha:
5570                     setAlpha(a.getFloat(attr, 1f));
5571                     break;
5572                 case com.android.internal.R.styleable.View_transformPivotX:
5573                     setPivotX(a.getDimension(attr, 0));
5574                     break;
5575                 case com.android.internal.R.styleable.View_transformPivotY:
5576                     setPivotY(a.getDimension(attr, 0));
5577                     break;
5578                 case com.android.internal.R.styleable.View_translationX:
5579                     tx = a.getDimension(attr, 0);
5580                     transformSet = true;
5581                     break;
5582                 case com.android.internal.R.styleable.View_translationY:
5583                     ty = a.getDimension(attr, 0);
5584                     transformSet = true;
5585                     break;
5586                 case com.android.internal.R.styleable.View_translationZ:
5587                     tz = a.getDimension(attr, 0);
5588                     transformSet = true;
5589                     break;
5590                 case com.android.internal.R.styleable.View_elevation:
5591                     elevation = a.getDimension(attr, 0);
5592                     transformSet = true;
5593                     break;
5594                 case com.android.internal.R.styleable.View_rotation:
5595                     rotation = a.getFloat(attr, 0);
5596                     transformSet = true;
5597                     break;
5598                 case com.android.internal.R.styleable.View_rotationX:
5599                     rotationX = a.getFloat(attr, 0);
5600                     transformSet = true;
5601                     break;
5602                 case com.android.internal.R.styleable.View_rotationY:
5603                     rotationY = a.getFloat(attr, 0);
5604                     transformSet = true;
5605                     break;
5606                 case com.android.internal.R.styleable.View_scaleX:
5607                     sx = a.getFloat(attr, 1f);
5608                     transformSet = true;
5609                     break;
5610                 case com.android.internal.R.styleable.View_scaleY:
5611                     sy = a.getFloat(attr, 1f);
5612                     transformSet = true;
5613                     break;
5614                 case com.android.internal.R.styleable.View_id:
5615                     mID = a.getResourceId(attr, NO_ID);
5616                     break;
5617                 case com.android.internal.R.styleable.View_tag:
5618                     mTag = a.getText(attr);
5619                     break;
5620                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5621                     if (a.getBoolean(attr, false)) {
5622                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5623                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5624                     }
5625                     break;
5626                 case com.android.internal.R.styleable.View_focusable:
5627                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5628                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5629                         viewFlagMasks |= FOCUSABLE_MASK;
5630                     }
5631                     break;
5632                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5633                     if (a.getBoolean(attr, false)) {
5634                         // unset auto focus since focusableInTouchMode implies explicit focusable
5635                         viewFlagValues &= ~FOCUSABLE_AUTO;
5636                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5637                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5638                     }
5639                     break;
5640                 case com.android.internal.R.styleable.View_clickable:
5641                     if (a.getBoolean(attr, false)) {
5642                         viewFlagValues |= CLICKABLE;
5643                         viewFlagMasks |= CLICKABLE;
5644                     }
5645                     break;
5646                 case com.android.internal.R.styleable.View_allowClickWhenDisabled:
5647                     setAllowClickWhenDisabled(a.getBoolean(attr, false));
5648                     break;
5649                 case com.android.internal.R.styleable.View_longClickable:
5650                     if (a.getBoolean(attr, false)) {
5651                         viewFlagValues |= LONG_CLICKABLE;
5652                         viewFlagMasks |= LONG_CLICKABLE;
5653                     }
5654                     break;
5655                 case com.android.internal.R.styleable.View_contextClickable:
5656                     if (a.getBoolean(attr, false)) {
5657                         viewFlagValues |= CONTEXT_CLICKABLE;
5658                         viewFlagMasks |= CONTEXT_CLICKABLE;
5659                     }
5660                     break;
5661                 case com.android.internal.R.styleable.View_saveEnabled:
5662                     if (!a.getBoolean(attr, true)) {
5663                         viewFlagValues |= SAVE_DISABLED;
5664                         viewFlagMasks |= SAVE_DISABLED_MASK;
5665                     }
5666                     break;
5667                 case com.android.internal.R.styleable.View_duplicateParentState:
5668                     if (a.getBoolean(attr, false)) {
5669                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5670                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5671                     }
5672                     break;
5673                 case com.android.internal.R.styleable.View_visibility:
5674                     final int visibility = a.getInt(attr, 0);
5675                     if (visibility != 0) {
5676                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5677                         viewFlagMasks |= VISIBILITY_MASK;
5678                     }
5679                     break;
5680                 case com.android.internal.R.styleable.View_layoutDirection:
5681                     // Clear any layout direction flags (included resolved bits) already set
5682                     mPrivateFlags2 &=
5683                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5684                     // Set the layout direction flags depending on the value of the attribute
5685                     final int layoutDirection = a.getInt(attr, -1);
5686                     final int value = (layoutDirection != -1) ?
5687                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5688                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5689                     break;
5690                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5691                     final int cacheQuality = a.getInt(attr, 0);
5692                     if (cacheQuality != 0) {
5693                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5694                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5695                     }
5696                     break;
5697                 case com.android.internal.R.styleable.View_contentDescription:
5698                     setContentDescription(a.getString(attr));
5699                     break;
5700                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5701                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5702                     break;
5703                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5704                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5705                     break;
5706                 case com.android.internal.R.styleable.View_labelFor:
5707                     setLabelFor(a.getResourceId(attr, NO_ID));
5708                     break;
5709                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5710                     if (!a.getBoolean(attr, true)) {
5711                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5712                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5713                     }
5714                     break;
5715                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5716                     if (!a.getBoolean(attr, true)) {
5717                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5718                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5719                     }
5720                     break;
5721                 case R.styleable.View_scrollbars:
5722                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5723                     if (scrollbars != SCROLLBARS_NONE) {
5724                         viewFlagValues |= scrollbars;
5725                         viewFlagMasks |= SCROLLBARS_MASK;
5726                         initializeScrollbars = true;
5727                     }
5728                     break;
5729                 //noinspection deprecation
5730                 case R.styleable.View_fadingEdge:
5731                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5732                         // Ignore the attribute starting with ICS
5733                         break;
5734                     }
5735                     // With builds < ICS, fall through and apply fading edges
5736                 case R.styleable.View_requiresFadingEdge:
5737                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5738                     if (fadingEdge != FADING_EDGE_NONE) {
5739                         viewFlagValues |= fadingEdge;
5740                         viewFlagMasks |= FADING_EDGE_MASK;
5741                         initializeFadingEdgeInternal(a);
5742                     }
5743                     break;
5744                 case R.styleable.View_scrollbarStyle:
5745                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5746                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5747                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5748                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5749                     }
5750                     break;
5751                 case R.styleable.View_isScrollContainer:
5752                     setScrollContainer = true;
5753                     if (a.getBoolean(attr, false)) {
5754                         setScrollContainer(true);
5755                     }
5756                     break;
5757                 case com.android.internal.R.styleable.View_keepScreenOn:
5758                     if (a.getBoolean(attr, false)) {
5759                         viewFlagValues |= KEEP_SCREEN_ON;
5760                         viewFlagMasks |= KEEP_SCREEN_ON;
5761                     }
5762                     break;
5763                 case R.styleable.View_filterTouchesWhenObscured:
5764                     if (a.getBoolean(attr, false)) {
5765                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5766                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5767                     }
5768                     break;
5769                 case R.styleable.View_nextFocusLeft:
5770                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5771                     break;
5772                 case R.styleable.View_nextFocusRight:
5773                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5774                     break;
5775                 case R.styleable.View_nextFocusUp:
5776                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5777                     break;
5778                 case R.styleable.View_nextFocusDown:
5779                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5780                     break;
5781                 case R.styleable.View_nextFocusForward:
5782                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5783                     break;
5784                 case R.styleable.View_nextClusterForward:
5785                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5786                     break;
5787                 case R.styleable.View_minWidth:
5788                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5789                     break;
5790                 case R.styleable.View_minHeight:
5791                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5792                     break;
5793                 case R.styleable.View_onClick:
5794                     if (context.isRestricted()) {
5795                         throw new IllegalStateException("The android:onClick attribute cannot "
5796                                 + "be used within a restricted context");
5797                     }
5798 
5799                     final String handlerName = a.getString(attr);
5800                     if (handlerName != null) {
5801                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5802                     }
5803                     break;
5804                 case R.styleable.View_overScrollMode:
5805                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5806                     break;
5807                 case R.styleable.View_verticalScrollbarPosition:
5808                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5809                     break;
5810                 case R.styleable.View_layerType:
5811                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5812                     break;
5813                 case R.styleable.View_textDirection:
5814                     // Clear any text direction flag already set
5815                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5816                     // Set the text direction flags depending on the value of the attribute
5817                     final int textDirection = a.getInt(attr, -1);
5818                     if (textDirection != -1) {
5819                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5820                     }
5821                     break;
5822                 case R.styleable.View_textAlignment:
5823                     // Clear any text alignment flag already set
5824                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5825                     // Set the text alignment flag depending on the value of the attribute
5826                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5827                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5828                     break;
5829                 case R.styleable.View_importantForAccessibility:
5830                     setImportantForAccessibility(a.getInt(attr,
5831                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5832                     break;
5833                 case R.styleable.View_accessibilityLiveRegion:
5834                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5835                     break;
5836                 case R.styleable.View_transitionName:
5837                     setTransitionName(a.getString(attr));
5838                     break;
5839                 case R.styleable.View_nestedScrollingEnabled:
5840                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5841                     break;
5842                 case R.styleable.View_stateListAnimator:
5843                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5844                             a.getResourceId(attr, 0)));
5845                     break;
5846                 case R.styleable.View_backgroundTint:
5847                     // This will get applied later during setBackground().
5848                     if (mBackgroundTint == null) {
5849                         mBackgroundTint = new TintInfo();
5850                     }
5851                     mBackgroundTint.mTintList = a.getColorStateList(
5852                             R.styleable.View_backgroundTint);
5853                     mBackgroundTint.mHasTintList = true;
5854                     break;
5855                 case R.styleable.View_backgroundTintMode:
5856                     // This will get applied later during setBackground().
5857                     if (mBackgroundTint == null) {
5858                         mBackgroundTint = new TintInfo();
5859                     }
5860                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
5861                             R.styleable.View_backgroundTintMode, -1), null);
5862                     mBackgroundTint.mHasTintMode = true;
5863                     break;
5864                 case R.styleable.View_outlineProvider:
5865                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5866                             PROVIDER_BACKGROUND));
5867                     break;
5868                 case R.styleable.View_foreground:
5869                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5870                         setForeground(a.getDrawable(attr));
5871                     }
5872                     break;
5873                 case R.styleable.View_foregroundGravity:
5874                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5875                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5876                     }
5877                     break;
5878                 case R.styleable.View_foregroundTintMode:
5879                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5880                         setForegroundTintBlendMode(
5881                                 Drawable.parseBlendMode(a.getInt(attr, -1),
5882                                         null));
5883                     }
5884                     break;
5885                 case R.styleable.View_foregroundTint:
5886                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5887                         setForegroundTintList(a.getColorStateList(attr));
5888                     }
5889                     break;
5890                 case R.styleable.View_foregroundInsidePadding:
5891                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5892                         if (mForegroundInfo == null) {
5893                             mForegroundInfo = new ForegroundInfo();
5894                         }
5895                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5896                                 mForegroundInfo.mInsidePadding);
5897                     }
5898                     break;
5899                 case R.styleable.View_scrollIndicators:
5900                     final int scrollIndicators =
5901                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5902                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5903                     if (scrollIndicators != 0) {
5904                         mPrivateFlags3 |= scrollIndicators;
5905                         initializeScrollIndicators = true;
5906                     }
5907                     break;
5908                 case R.styleable.View_pointerIcon:
5909                     final int resourceId = a.getResourceId(attr, 0);
5910                     if (resourceId != 0) {
5911                         setPointerIcon(PointerIcon.load(
5912                                 context.getResources(), resourceId));
5913                     } else {
5914                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5915                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5916                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5917                         }
5918                     }
5919                     break;
5920                 case R.styleable.View_forceHasOverlappingRendering:
5921                     if (a.peekValue(attr) != null) {
5922                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5923                     }
5924                     break;
5925                 case R.styleable.View_tooltipText:
5926                     setTooltipText(a.getText(attr));
5927                     break;
5928                 case R.styleable.View_keyboardNavigationCluster:
5929                     if (a.peekValue(attr) != null) {
5930                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5931                     }
5932                     break;
5933                 case R.styleable.View_focusedByDefault:
5934                     if (a.peekValue(attr) != null) {
5935                         setFocusedByDefault(a.getBoolean(attr, true));
5936                     }
5937                     break;
5938                 case R.styleable.View_autofillHints:
5939                     if (a.peekValue(attr) != null) {
5940                         CharSequence[] rawHints = null;
5941                         String rawString = null;
5942 
5943                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5944                             int resId = a.getResourceId(attr, 0);
5945 
5946                             try {
5947                                 rawHints = a.getTextArray(attr);
5948                             } catch (Resources.NotFoundException e) {
5949                                 rawString = getResources().getString(resId);
5950                             }
5951                         } else {
5952                             rawString = a.getString(attr);
5953                         }
5954 
5955                         if (rawHints == null) {
5956                             if (rawString == null) {
5957                                 throw new IllegalArgumentException(
5958                                         "Could not resolve autofillHints");
5959                             } else {
5960                                 rawHints = rawString.split(",");
5961                             }
5962                         }
5963 
5964                         String[] hints = new String[rawHints.length];
5965 
5966                         int numHints = rawHints.length;
5967                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5968                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5969                         }
5970                         setAutofillHints(hints);
5971                     }
5972                     break;
5973                 case R.styleable.View_importantForAutofill:
5974                     if (a.peekValue(attr) != null) {
5975                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5976                     }
5977                     break;
5978                 case R.styleable.View_importantForContentCapture:
5979                     if (a.peekValue(attr) != null) {
5980                         setImportantForContentCapture(a.getInt(attr,
5981                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
5982                     }
5983                 case R.styleable.View_defaultFocusHighlightEnabled:
5984                     if (a.peekValue(attr) != null) {
5985                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5986                     }
5987                     break;
5988                 case R.styleable.View_screenReaderFocusable:
5989                     if (a.peekValue(attr) != null) {
5990                         setScreenReaderFocusable(a.getBoolean(attr, false));
5991                     }
5992                     break;
5993                 case R.styleable.View_accessibilityPaneTitle:
5994                     if (a.peekValue(attr) != null) {
5995                         setAccessibilityPaneTitle(a.getString(attr));
5996                     }
5997                     break;
5998                 case R.styleable.View_outlineSpotShadowColor:
5999                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6000                     break;
6001                 case R.styleable.View_outlineAmbientShadowColor:
6002                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6003                     break;
6004                 case com.android.internal.R.styleable.View_accessibilityHeading:
6005                     setAccessibilityHeading(a.getBoolean(attr, false));
6006                     break;
6007                 case R.styleable.View_forceDarkAllowed:
6008                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6009                     break;
6010                 case R.styleable.View_scrollCaptureHint:
6011                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6012                     break;
6013                 case R.styleable.View_clipToOutline:
6014                     setClipToOutline(a.getBoolean(attr, false));
6015                     break;
6016             }
6017         }
6018 
6019         setOverScrollMode(overScrollMode);
6020 
6021         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6022         // the resolved layout direction). Those cached values will be used later during padding
6023         // resolution.
6024         mUserPaddingStart = startPadding;
6025         mUserPaddingEnd = endPadding;
6026 
6027         if (background != null) {
6028             setBackground(background);
6029         }
6030 
6031         // setBackground above will record that padding is currently provided by the background.
6032         // If we have padding specified via xml, record that here instead and use it.
6033         mLeftPaddingDefined = leftPaddingDefined;
6034         mRightPaddingDefined = rightPaddingDefined;
6035 
6036         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6037         // bottomPadding, and padding set by background.  Valid padding beats everything.
6038         if (padding >= 0) {
6039             leftPadding = padding;
6040             topPadding = padding;
6041             rightPadding = padding;
6042             bottomPadding = padding;
6043             mUserPaddingLeftInitial = padding;
6044             mUserPaddingRightInitial = padding;
6045         } else {
6046             if (paddingHorizontal >= 0) {
6047                 leftPadding = paddingHorizontal;
6048                 rightPadding = paddingHorizontal;
6049                 mUserPaddingLeftInitial = paddingHorizontal;
6050                 mUserPaddingRightInitial = paddingHorizontal;
6051             }
6052             if (paddingVertical >= 0) {
6053                 topPadding = paddingVertical;
6054                 bottomPadding = paddingVertical;
6055             }
6056         }
6057 
6058         if (isRtlCompatibilityMode()) {
6059             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6060             // left / right padding are used if defined (meaning here nothing to do). If they are not
6061             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6062             // start / end and resolve them as left / right (layout direction is not taken into account).
6063             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6064             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6065             // defined.
6066             if (!mLeftPaddingDefined && startPaddingDefined) {
6067                 leftPadding = startPadding;
6068             }
6069             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6070             if (!mRightPaddingDefined && endPaddingDefined) {
6071                 rightPadding = endPadding;
6072             }
6073             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6074         } else {
6075             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6076             // values defined. Otherwise, left /right values are used.
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             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6081 
6082             if (mLeftPaddingDefined && !hasRelativePadding) {
6083                 mUserPaddingLeftInitial = leftPadding;
6084             }
6085             if (mRightPaddingDefined && !hasRelativePadding) {
6086                 mUserPaddingRightInitial = rightPadding;
6087             }
6088         }
6089 
6090         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6091         // them on if topPadding or bottomPadding are not valid.
6092         internalSetPadding(
6093                 mUserPaddingLeftInitial,
6094                 topPadding >= 0 ? topPadding : mPaddingTop,
6095                 mUserPaddingRightInitial,
6096                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6097 
6098         if (viewFlagMasks != 0) {
6099             setFlags(viewFlagValues, viewFlagMasks);
6100         }
6101 
6102         if (initializeScrollbars) {
6103             initializeScrollbarsInternal(a);
6104         }
6105 
6106         if (initializeScrollIndicators) {
6107             initializeScrollIndicatorsInternal();
6108         }
6109 
6110         a.recycle();
6111 
6112         // Needs to be called after mViewFlags is set
6113         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6114             recomputePadding();
6115         }
6116 
6117         if (x != 0 || y != 0) {
6118             scrollTo(x, y);
6119         }
6120 
6121         if (transformSet) {
6122             setTranslationX(tx);
6123             setTranslationY(ty);
6124             setTranslationZ(tz);
6125             setElevation(elevation);
6126             setRotation(rotation);
6127             setRotationX(rotationX);
6128             setRotationY(rotationY);
6129             setScaleX(sx);
6130             setScaleY(sy);
6131         }
6132 
6133         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6134             setScrollContainer(true);
6135         }
6136 
6137         computeOpaqueFlags();
6138     }
6139 
6140     /**
6141      * Returns the ordered list of resource ID that are considered when resolving attribute values
6142      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6143      * XML. It will also include a set of explicit styles if specified in XML using
6144      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6145      *
6146      * <p>
6147      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6148      * is enabled in Android developer options.
6149      *
6150      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6151      * @return ordered list of resource ID that are considered when resolving attribute values for
6152      * this {@link View}.
6153      */
6154     @NonNull
6155     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6156         if (!sDebugViewAttributes
6157                 || mAttributeResolutionStacks == null
6158                 || mAttributeResolutionStacks.get(attribute) == null) {
6159             return new int[0];
6160         }
6161         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6162         int stackSize = attributeResolutionStack.length;
6163         if (mSourceLayoutId != ID_NULL) {
6164             stackSize++;
6165         }
6166 
6167         int currentIndex = 0;
6168         int[] stack = new int[stackSize];
6169 
6170         if (mSourceLayoutId != ID_NULL) {
6171             stack[currentIndex] = mSourceLayoutId;
6172             currentIndex++;
6173         }
6174         for (int i = 0; i < attributeResolutionStack.length; i++) {
6175             stack[currentIndex] = attributeResolutionStack[i];
6176             currentIndex++;
6177         }
6178         return stack;
6179     }
6180 
6181     /**
6182      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6183      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6184      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6185      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6186      *
6187      * <p>
6188      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6189      * is enabled in Android developer options.
6190      *
6191      * @return mapping of attribute resource ID to source resource ID where the attribute value
6192      * was set.
6193      */
6194     @NonNull
6195     @SuppressWarnings("AndroidFrameworkEfficientCollections")
6196     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6197         HashMap<Integer, Integer> map = new HashMap<>();
6198         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6199             return map;
6200         }
6201         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6202             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6203         }
6204         return map;
6205     }
6206 
6207     /**
6208      * Returns the resource ID for the style specified using {@code style="..."} in the
6209      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6210      * specified or otherwise not applicable.
6211      * <p>
6212      * Each {@link View} can have an explicit style specified in the layout file.
6213      * This style is used first during the {@link View} attribute resolution, then if an attribute
6214      * is not defined there the resource system looks at default style and theme as fallbacks.
6215      *
6216      * <p>
6217      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6218      * is enabled in Android developer options.
6219      *
6220      * @return The resource ID for the style specified using {@code style="..."} in the
6221      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6222      *      if not specified or otherwise not applicable.
6223      */
6224     @StyleRes
6225     public int getExplicitStyle() {
6226         if (!sDebugViewAttributes) {
6227             return ID_NULL;
6228         }
6229         return mExplicitStyle;
6230     }
6231 
6232     /**
6233      * An implementation of OnClickListener that attempts to lazily load a
6234      * named click handling method from a parent or ancestor context.
6235      */
6236     private static class DeclaredOnClickListener implements OnClickListener {
6237         private final View mHostView;
6238         private final String mMethodName;
6239 
6240         private Method mResolvedMethod;
6241         private Context mResolvedContext;
6242 
6243         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6244             mHostView = hostView;
6245             mMethodName = methodName;
6246         }
6247 
6248         @Override
6249         public void onClick(@NonNull View v) {
6250             if (mResolvedMethod == null) {
6251                 resolveMethod(mHostView.getContext(), mMethodName);
6252             }
6253 
6254             try {
6255                 mResolvedMethod.invoke(mResolvedContext, v);
6256             } catch (IllegalAccessException e) {
6257                 throw new IllegalStateException(
6258                         "Could not execute non-public method for android:onClick", e);
6259             } catch (InvocationTargetException e) {
6260                 throw new IllegalStateException(
6261                         "Could not execute method for android:onClick", e);
6262             }
6263         }
6264 
6265         @NonNull
6266         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6267             while (context != null) {
6268                 try {
6269                     if (!context.isRestricted()) {
6270                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6271                         if (method != null) {
6272                             mResolvedMethod = method;
6273                             mResolvedContext = context;
6274                             return;
6275                         }
6276                     }
6277                 } catch (NoSuchMethodException e) {
6278                     // Failed to find method, keep searching up the hierarchy.
6279                 }
6280 
6281                 if (context instanceof ContextWrapper) {
6282                     context = ((ContextWrapper) context).getBaseContext();
6283                 } else {
6284                     // Can't search up the hierarchy, null out and fail.
6285                     context = null;
6286                 }
6287             }
6288 
6289             final int id = mHostView.getId();
6290             final String idText = id == NO_ID ? "" : " with id '"
6291                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6292             throw new IllegalStateException("Could not find method " + mMethodName
6293                     + "(View) in a parent or ancestor Context for android:onClick "
6294                     + "attribute defined on view " + mHostView.getClass() + idText);
6295         }
6296     }
6297 
6298     /**
6299      * Non-public constructor for use in testing
6300      */
6301     @UnsupportedAppUsage
6302     View() {
6303         mResources = null;
6304         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6305     }
6306 
6307     /**
6308      * Returns {@code true} when the View is attached and the system developer setting to show
6309      * the layout bounds is enabled or {@code false} otherwise.
6310      */
6311     public final boolean isShowingLayoutBounds() {
6312         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6313     }
6314 
6315     /**
6316      * Used to test isShowingLayoutBounds(). This sets the local value used
6317      * by that function. This method does nothing if the layout isn't attached.
6318      *
6319      * @hide
6320      */
6321     @TestApi
6322     public final void setShowingLayoutBounds(boolean debugLayout) {
6323         if (mAttachInfo != null) {
6324             mAttachInfo.mDebugLayout = debugLayout;
6325         }
6326     }
6327 
6328     private static SparseArray<String> getAttributeMap() {
6329         if (mAttributeMap == null) {
6330             mAttributeMap = new SparseArray<>();
6331         }
6332         return mAttributeMap;
6333     }
6334 
6335     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6336             @Nullable AttributeSet attrs) {
6337         if (!sDebugViewAttributes) {
6338             return;
6339         }
6340         mExplicitStyle = theme.getExplicitStyle(attrs);
6341     }
6342 
6343     /**
6344      * Stores debugging information about attributes. This should be called in a constructor by
6345      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6346      * then the custom attributes used by this view will not be visible in layout inspection tools.
6347      *
6348      *  @param context Context under which this view is created.
6349      * @param styleable A reference to styleable array R.styleable.Foo
6350      * @param attrs AttributeSet used to construct this view.
6351      * @param t Resolved {@link TypedArray} returned by a call to
6352      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6353      * @param defStyleAttr Default style attribute passed into the view constructor.
6354      * @param defStyleRes Default style resource passed into the view constructor.
6355      */
6356     public final void saveAttributeDataForStyleable(@NonNull Context context,
6357             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6358             int defStyleAttr, int defStyleRes) {
6359         if (!sDebugViewAttributes) {
6360             return;
6361         }
6362 
6363         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6364                 defStyleAttr, defStyleRes, mExplicitStyle);
6365 
6366         if (mAttributeResolutionStacks == null) {
6367             mAttributeResolutionStacks = new SparseArray<>();
6368         }
6369 
6370         if (mAttributeSourceResId == null) {
6371             mAttributeSourceResId = new SparseIntArray();
6372         }
6373 
6374         final int indexCount = t.getIndexCount();
6375         for (int j = 0; j < indexCount; ++j) {
6376             final int index = t.getIndex(j);
6377             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6378             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6379         }
6380     }
6381 
6382     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6383         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6384         final int indexCount = t.getIndexCount();
6385         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6386 
6387         int i = 0;
6388 
6389         // Store raw XML attributes.
6390         for (int j = 0; j < attrsCount; ++j) {
6391             attributes[i] = attrs.getAttributeName(j);
6392             attributes[i + 1] = attrs.getAttributeValue(j);
6393             i += 2;
6394         }
6395 
6396         // Store resolved styleable attributes.
6397         final Resources res = t.getResources();
6398         final SparseArray<String> attributeMap = getAttributeMap();
6399         for (int j = 0; j < indexCount; ++j) {
6400             final int index = t.getIndex(j);
6401             if (!t.hasValueOrEmpty(index)) {
6402                 // Value is undefined. Skip it.
6403                 continue;
6404             }
6405 
6406             final int resourceId = t.getResourceId(index, 0);
6407             if (resourceId == 0) {
6408                 // Value is not a reference. Skip it.
6409                 continue;
6410             }
6411 
6412             String resourceName = attributeMap.get(resourceId);
6413             if (resourceName == null) {
6414                 try {
6415                     resourceName = res.getResourceName(resourceId);
6416                 } catch (Resources.NotFoundException e) {
6417                     resourceName = "0x" + Integer.toHexString(resourceId);
6418                 }
6419                 attributeMap.put(resourceId, resourceName);
6420             }
6421 
6422             attributes[i] = resourceName;
6423             attributes[i + 1] = t.getString(index);
6424             i += 2;
6425         }
6426 
6427         // Trim to fit contents.
6428         final String[] trimmed = new String[i];
6429         System.arraycopy(attributes, 0, trimmed, 0, i);
6430         mAttributes = trimmed;
6431     }
6432 
6433     @Override
6434     public String toString() {
6435         StringBuilder out = new StringBuilder(128);
6436         out.append(getClass().getName());
6437         out.append('{');
6438         out.append(Integer.toHexString(System.identityHashCode(this)));
6439         out.append(' ');
6440         switch (mViewFlags&VISIBILITY_MASK) {
6441             case VISIBLE: out.append('V'); break;
6442             case INVISIBLE: out.append('I'); break;
6443             case GONE: out.append('G'); break;
6444             default: out.append('.'); break;
6445         }
6446         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6447         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6448         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6449         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6450         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6451         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6452         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6453         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6454         out.append(' ');
6455         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6456         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6457         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6458         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6459             out.append('p');
6460         } else {
6461             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6462         }
6463         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6464         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6465         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6466         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6467         out.append(' ');
6468         out.append(mLeft);
6469         out.append(',');
6470         out.append(mTop);
6471         out.append('-');
6472         out.append(mRight);
6473         out.append(',');
6474         out.append(mBottom);
6475         final int id = getId();
6476         if (id != NO_ID) {
6477             out.append(" #");
6478             out.append(Integer.toHexString(id));
6479             final Resources r = mResources;
6480             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6481                 try {
6482                     String pkgname;
6483                     switch (id&0xff000000) {
6484                         case 0x7f000000:
6485                             pkgname="app";
6486                             break;
6487                         case 0x01000000:
6488                             pkgname="android";
6489                             break;
6490                         default:
6491                             pkgname = r.getResourcePackageName(id);
6492                             break;
6493                     }
6494                     String typename = r.getResourceTypeName(id);
6495                     String entryname = r.getResourceEntryName(id);
6496                     out.append(" ");
6497                     out.append(pkgname);
6498                     out.append(":");
6499                     out.append(typename);
6500                     out.append("/");
6501                     out.append(entryname);
6502                 } catch (Resources.NotFoundException e) {
6503                 }
6504             }
6505         }
6506         if (mAutofillId != null) {
6507             out.append(" aid="); out.append(mAutofillId);
6508         }
6509         out.append("}");
6510         return out.toString();
6511     }
6512 
6513     /**
6514      * <p>
6515      * Initializes the fading edges from a given set of styled attributes. This
6516      * method should be called by subclasses that need fading edges and when an
6517      * instance of these subclasses is created programmatically rather than
6518      * being inflated from XML. This method is automatically called when the XML
6519      * is inflated.
6520      * </p>
6521      *
6522      * @param a the styled attributes set to initialize the fading edges from
6523      *
6524      * @removed
6525      */
6526     protected void initializeFadingEdge(TypedArray a) {
6527         // This method probably shouldn't have been included in the SDK to begin with.
6528         // It relies on 'a' having been initialized using an attribute filter array that is
6529         // not publicly available to the SDK. The old method has been renamed
6530         // to initializeFadingEdgeInternal and hidden for framework use only;
6531         // this one initializes using defaults to make it safe to call for apps.
6532 
6533         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6534 
6535         initializeFadingEdgeInternal(arr);
6536 
6537         arr.recycle();
6538     }
6539 
6540     /**
6541      * <p>
6542      * Initializes the fading edges from a given set of styled attributes. This
6543      * method should be called by subclasses that need fading edges and when an
6544      * instance of these subclasses is created programmatically rather than
6545      * being inflated from XML. This method is automatically called when the XML
6546      * is inflated.
6547      * </p>
6548      *
6549      * @param a the styled attributes set to initialize the fading edges from
6550      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6551      */
6552     protected void initializeFadingEdgeInternal(TypedArray a) {
6553         initScrollCache();
6554 
6555         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6556                 R.styleable.View_fadingEdgeLength,
6557                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6558     }
6559 
6560     /**
6561      * Returns the size of the vertical faded edges used to indicate that more
6562      * content in this view is visible.
6563      *
6564      * @return The size in pixels of the vertical faded edge or 0 if vertical
6565      *         faded edges are not enabled for this view.
6566      * @attr ref android.R.styleable#View_fadingEdgeLength
6567      */
6568     public int getVerticalFadingEdgeLength() {
6569         if (isVerticalFadingEdgeEnabled()) {
6570             ScrollabilityCache cache = mScrollCache;
6571             if (cache != null) {
6572                 return cache.fadingEdgeLength;
6573             }
6574         }
6575         return 0;
6576     }
6577 
6578     /**
6579      * Set the size of the faded edge used to indicate that more content in this
6580      * view is available.  Will not change whether the fading edge is enabled; use
6581      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6582      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6583      * for the vertical or horizontal fading edges.
6584      *
6585      * @param length The size in pixels of the faded edge used to indicate that more
6586      *        content in this view is visible.
6587      */
6588     public void setFadingEdgeLength(int length) {
6589         initScrollCache();
6590         mScrollCache.fadingEdgeLength = length;
6591     }
6592 
6593     /**
6594      * Returns the size of the horizontal faded edges used to indicate that more
6595      * content in this view is visible.
6596      *
6597      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6598      *         faded edges are not enabled for this view.
6599      * @attr ref android.R.styleable#View_fadingEdgeLength
6600      */
6601     public int getHorizontalFadingEdgeLength() {
6602         if (isHorizontalFadingEdgeEnabled()) {
6603             ScrollabilityCache cache = mScrollCache;
6604             if (cache != null) {
6605                 return cache.fadingEdgeLength;
6606             }
6607         }
6608         return 0;
6609     }
6610 
6611     /**
6612      * Returns the width of the vertical scrollbar.
6613      *
6614      * @return The width in pixels of the vertical scrollbar or 0 if there
6615      *         is no vertical scrollbar.
6616      */
6617     public int getVerticalScrollbarWidth() {
6618         ScrollabilityCache cache = mScrollCache;
6619         if (cache != null) {
6620             ScrollBarDrawable scrollBar = cache.scrollBar;
6621             if (scrollBar != null) {
6622                 int size = scrollBar.getSize(true);
6623                 if (size <= 0) {
6624                     size = cache.scrollBarSize;
6625                 }
6626                 return size;
6627             }
6628             return 0;
6629         }
6630         return 0;
6631     }
6632 
6633     /**
6634      * Returns the height of the horizontal scrollbar.
6635      *
6636      * @return The height in pixels of the horizontal scrollbar or 0 if
6637      *         there is no horizontal scrollbar.
6638      */
6639     protected int getHorizontalScrollbarHeight() {
6640         ScrollabilityCache cache = mScrollCache;
6641         if (cache != null) {
6642             ScrollBarDrawable scrollBar = cache.scrollBar;
6643             if (scrollBar != null) {
6644                 int size = scrollBar.getSize(false);
6645                 if (size <= 0) {
6646                     size = cache.scrollBarSize;
6647                 }
6648                 return size;
6649             }
6650             return 0;
6651         }
6652         return 0;
6653     }
6654 
6655     /**
6656      * <p>
6657      * Initializes the scrollbars from a given set of styled attributes. This
6658      * method should be called by subclasses that need scrollbars and when an
6659      * instance of these subclasses is created programmatically rather than
6660      * being inflated from XML. This method is automatically called when the XML
6661      * is inflated.
6662      * </p>
6663      *
6664      * @param a the styled attributes set to initialize the scrollbars from
6665      *
6666      * @removed
6667      */
6668     protected void initializeScrollbars(TypedArray a) {
6669         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6670         // using the View filter array which is not available to the SDK. As such, internal
6671         // framework usage now uses initializeScrollbarsInternal and we grab a default
6672         // TypedArray with the right filter instead here.
6673         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6674 
6675         initializeScrollbarsInternal(arr);
6676 
6677         // We ignored the method parameter. Recycle the one we actually did use.
6678         arr.recycle();
6679     }
6680 
6681     private void initializeScrollBarDrawable() {
6682         initScrollCache();
6683 
6684         if (mScrollCache.scrollBar == null) {
6685             mScrollCache.scrollBar = new ScrollBarDrawable();
6686             mScrollCache.scrollBar.setState(getDrawableState());
6687             mScrollCache.scrollBar.setCallback(this);
6688         }
6689     }
6690 
6691     /**
6692      * <p>
6693      * Initializes the scrollbars from a given set of styled attributes. This
6694      * method should be called by subclasses that need scrollbars and when an
6695      * instance of these subclasses is created programmatically rather than
6696      * being inflated from XML. This method is automatically called when the XML
6697      * is inflated.
6698      * </p>
6699      *
6700      * @param a the styled attributes set to initialize the scrollbars from
6701      * @hide
6702      */
6703     @UnsupportedAppUsage
6704     protected void initializeScrollbarsInternal(TypedArray a) {
6705         initScrollCache();
6706 
6707         final ScrollabilityCache scrollabilityCache = mScrollCache;
6708 
6709         if (scrollabilityCache.scrollBar == null) {
6710             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6711             scrollabilityCache.scrollBar.setState(getDrawableState());
6712             scrollabilityCache.scrollBar.setCallback(this);
6713         }
6714 
6715         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6716 
6717         if (!fadeScrollbars) {
6718             scrollabilityCache.state = ScrollabilityCache.ON;
6719         }
6720         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6721 
6722 
6723         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6724                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6725                         .getScrollBarFadeDuration());
6726         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6727                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6728                 ViewConfiguration.getScrollDefaultDelay());
6729 
6730 
6731         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6732                 com.android.internal.R.styleable.View_scrollbarSize,
6733                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6734 
6735         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6736         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6737 
6738         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6739         if (thumb != null) {
6740             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6741         }
6742 
6743         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6744                 false);
6745         if (alwaysDraw) {
6746             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6747         }
6748 
6749         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6750         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6751 
6752         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6753         if (thumb != null) {
6754             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6755         }
6756 
6757         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6758                 false);
6759         if (alwaysDraw) {
6760             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6761         }
6762 
6763         // Apply layout direction to the new Drawables if needed
6764         final int layoutDirection = getLayoutDirection();
6765         if (track != null) {
6766             track.setLayoutDirection(layoutDirection);
6767         }
6768         if (thumb != null) {
6769             thumb.setLayoutDirection(layoutDirection);
6770         }
6771 
6772         // Re-apply user/background padding so that scrollbar(s) get added
6773         resolvePadding();
6774     }
6775 
6776     /**
6777      * Defines the vertical scrollbar thumb drawable
6778      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6779      *
6780      * @see #awakenScrollBars(int)
6781      * @see #isVerticalScrollBarEnabled()
6782      * @see #setVerticalScrollBarEnabled(boolean)
6783      */
6784     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6785         initializeScrollBarDrawable();
6786         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
6787     }
6788 
6789     /**
6790      * Defines the vertical scrollbar track drawable
6791      * @attr ref android.R.styleable#View_scrollbarTrackVertical
6792      *
6793      * @see #awakenScrollBars(int)
6794      * @see #isVerticalScrollBarEnabled()
6795      * @see #setVerticalScrollBarEnabled(boolean)
6796      */
6797     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6798         initializeScrollBarDrawable();
6799         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
6800     }
6801 
6802     /**
6803      * Defines the horizontal thumb drawable
6804      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
6805      *
6806      * @see #awakenScrollBars(int)
6807      * @see #isHorizontalScrollBarEnabled()
6808      * @see #setHorizontalScrollBarEnabled(boolean)
6809      */
6810     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6811         initializeScrollBarDrawable();
6812         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
6813     }
6814 
6815     /**
6816      * Defines the horizontal track drawable
6817      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
6818      *
6819      * @see #awakenScrollBars(int)
6820      * @see #isHorizontalScrollBarEnabled()
6821      * @see #setHorizontalScrollBarEnabled(boolean)
6822      */
6823     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6824         initializeScrollBarDrawable();
6825         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
6826     }
6827 
6828     /**
6829      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
6830      * exists, null otherwise.
6831      *
6832      * @see #awakenScrollBars(int)
6833      * @see #isVerticalScrollBarEnabled()
6834      * @see #setVerticalScrollBarEnabled(boolean)
6835      */
6836     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
6837         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
6838     }
6839 
6840     /**
6841      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
6842      * exists, null otherwise.
6843      *
6844      * @see #awakenScrollBars(int)
6845      * @see #isVerticalScrollBarEnabled()
6846      * @see #setVerticalScrollBarEnabled(boolean)
6847      */
6848     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
6849         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
6850     }
6851 
6852     /**
6853      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
6854      * exists, null otherwise.
6855      *
6856      * @see #awakenScrollBars(int)
6857      * @see #isHorizontalScrollBarEnabled()
6858      * @see #setHorizontalScrollBarEnabled(boolean)
6859      */
6860     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
6861         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
6862     }
6863 
6864     /**
6865      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
6866      * exists, null otherwise.
6867      *
6868      * @see #awakenScrollBars(int)
6869      * @see #isHorizontalScrollBarEnabled()
6870      * @see #setHorizontalScrollBarEnabled(boolean)
6871      */
6872     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
6873         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
6874     }
6875 
6876     private void initializeScrollIndicatorsInternal() {
6877         // Some day maybe we'll break this into top/left/start/etc. and let the
6878         // client control it. Until then, you can have any scroll indicator you
6879         // want as long as it's a 1dp foreground-colored rectangle.
6880         if (mScrollIndicatorDrawable == null) {
6881             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6882         }
6883     }
6884 
6885     /**
6886      * <p>
6887      * Initalizes the scrollability cache if necessary.
6888      * </p>
6889      */
6890     private void initScrollCache() {
6891         if (mScrollCache == null) {
6892             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6893         }
6894     }
6895 
6896     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
6897     private ScrollabilityCache getScrollCache() {
6898         initScrollCache();
6899         return mScrollCache;
6900     }
6901 
6902     /**
6903      * Set the position of the vertical scroll bar. Should be one of
6904      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
6905      * {@link #SCROLLBAR_POSITION_RIGHT}.
6906      *
6907      * @param position Where the vertical scroll bar should be positioned.
6908      */
6909     public void setVerticalScrollbarPosition(int position) {
6910         if (mVerticalScrollbarPosition != position) {
6911             mVerticalScrollbarPosition = position;
6912             computeOpaqueFlags();
6913             resolvePadding();
6914         }
6915     }
6916 
6917     /**
6918      * @return The position where the vertical scroll bar will show, if applicable.
6919      * @see #setVerticalScrollbarPosition(int)
6920      */
6921     public int getVerticalScrollbarPosition() {
6922         return mVerticalScrollbarPosition;
6923     }
6924 
6925     boolean isOnScrollbar(float x, float y) {
6926         if (mScrollCache == null) {
6927             return false;
6928         }
6929         x += getScrollX();
6930         y += getScrollY();
6931         final boolean canScrollVertically =
6932                 computeVerticalScrollRange() > computeVerticalScrollExtent();
6933         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
6934             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6935             getVerticalScrollBarBounds(null, touchBounds);
6936             if (touchBounds.contains((int) x, (int) y)) {
6937                 return true;
6938             }
6939         }
6940         final boolean canScrollHorizontally =
6941                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
6942         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
6943             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6944             getHorizontalScrollBarBounds(null, touchBounds);
6945             if (touchBounds.contains((int) x, (int) y)) {
6946                 return true;
6947             }
6948         }
6949         return false;
6950     }
6951 
6952     @UnsupportedAppUsage
6953     boolean isOnScrollbarThumb(float x, float y) {
6954         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
6955     }
6956 
6957     private boolean isOnVerticalScrollbarThumb(float x, float y) {
6958         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
6959             return false;
6960         }
6961         final int range = computeVerticalScrollRange();
6962         final int extent = computeVerticalScrollExtent();
6963         if (range > extent) {
6964             x += getScrollX();
6965             y += getScrollY();
6966             final Rect bounds = mScrollCache.mScrollBarBounds;
6967             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6968             getVerticalScrollBarBounds(bounds, touchBounds);
6969             final int offset = computeVerticalScrollOffset();
6970             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
6971                     extent, range);
6972             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
6973                     extent, range, offset);
6974             final int thumbTop = bounds.top + thumbOffset;
6975             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6976             if (x >= touchBounds.left && x <= touchBounds.right
6977                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
6978                 return true;
6979             }
6980         }
6981         return false;
6982     }
6983 
6984     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
6985         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
6986             return false;
6987         }
6988         final int range = computeHorizontalScrollRange();
6989         final int extent = computeHorizontalScrollExtent();
6990         if (range > extent) {
6991             x += getScrollX();
6992             y += getScrollY();
6993             final Rect bounds = mScrollCache.mScrollBarBounds;
6994             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6995             getHorizontalScrollBarBounds(bounds, touchBounds);
6996             final int offset = computeHorizontalScrollOffset();
6997 
6998             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
6999                     extent, range);
7000             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7001                     extent, range, offset);
7002             final int thumbLeft = bounds.left + thumbOffset;
7003             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7004             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7005                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7006                 return true;
7007             }
7008         }
7009         return false;
7010     }
7011 
7012     @UnsupportedAppUsage
7013     boolean isDraggingScrollBar() {
7014         return mScrollCache != null
7015                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7016     }
7017 
7018     /**
7019      * Sets the state of all scroll indicators.
7020      * <p>
7021      * See {@link #setScrollIndicators(int, int)} for usage information.
7022      *
7023      * @param indicators a bitmask of indicators that should be enabled, or
7024      *                   {@code 0} to disable all indicators
7025      * @see #setScrollIndicators(int, int)
7026      * @see #getScrollIndicators()
7027      * @attr ref android.R.styleable#View_scrollIndicators
7028      */
7029     @RemotableViewMethod
7030     public void setScrollIndicators(@ScrollIndicators int indicators) {
7031         setScrollIndicators(indicators,
7032                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7033     }
7034 
7035     /**
7036      * Sets the state of the scroll indicators specified by the mask. To change
7037      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7038      * <p>
7039      * When a scroll indicator is enabled, it will be displayed if the view
7040      * can scroll in the direction of the indicator.
7041      * <p>
7042      * Multiple indicator types may be enabled or disabled by passing the
7043      * logical OR of the desired types. If multiple types are specified, they
7044      * will all be set to the same enabled state.
7045      * <p>
7046      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7047      *
7048      * @param indicators the indicator direction, or the logical OR of multiple
7049      *             indicator directions. One or more of:
7050      *             <ul>
7051      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7052      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7053      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7054      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7055      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7056      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7057      *             </ul>
7058      * @see #setScrollIndicators(int)
7059      * @see #getScrollIndicators()
7060      * @attr ref android.R.styleable#View_scrollIndicators
7061      */
7062     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7063         // Shift and sanitize mask.
7064         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7065         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7066 
7067         // Shift and mask indicators.
7068         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7069         indicators &= mask;
7070 
7071         // Merge with non-masked flags.
7072         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7073 
7074         if (mPrivateFlags3 != updatedFlags) {
7075             mPrivateFlags3 = updatedFlags;
7076 
7077             if (indicators != 0) {
7078                 initializeScrollIndicatorsInternal();
7079             }
7080             invalidate();
7081         }
7082     }
7083 
7084     /**
7085      * Returns a bitmask representing the enabled scroll indicators.
7086      * <p>
7087      * For example, if the top and left scroll indicators are enabled and all
7088      * other indicators are disabled, the return value will be
7089      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7090      * <p>
7091      * To check whether the bottom scroll indicator is enabled, use the value
7092      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7093      *
7094      * @return a bitmask representing the enabled scroll indicators
7095      */
7096     @InspectableProperty(flagMapping = {
7097             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7098             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7099             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7100             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7101             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7102             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7103             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7104     })
7105     @ScrollIndicators
7106     public int getScrollIndicators() {
7107         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7108                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7109     }
7110 
7111     @UnsupportedAppUsage
7112     ListenerInfo getListenerInfo() {
7113         if (mListenerInfo != null) {
7114             return mListenerInfo;
7115         }
7116         mListenerInfo = new ListenerInfo();
7117         return mListenerInfo;
7118     }
7119 
7120     /**
7121      * Register a callback to be invoked when the scroll X or Y positions of
7122      * this view change.
7123      * <p>
7124      * <b>Note:</b> Some views handle scrolling independently from View and may
7125      * have their own separate listeners for scroll-type events. For example,
7126      * {@link android.widget.ListView ListView} allows clients to register an
7127      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7128      * to listen for changes in list scroll position.
7129      *
7130      * @param l The listener to notify when the scroll X or Y position changes.
7131      * @see android.view.View#getScrollX()
7132      * @see android.view.View#getScrollY()
7133      */
7134     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7135         getListenerInfo().mOnScrollChangeListener = l;
7136     }
7137 
7138     /**
7139      * Register a callback to be invoked when focus of this view changed.
7140      *
7141      * @param l The callback that will run.
7142      */
7143     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7144         getListenerInfo().mOnFocusChangeListener = l;
7145     }
7146 
7147     /**
7148      * Add a listener that will be called when the bounds of the view change due to
7149      * layout processing.
7150      *
7151      * @param listener The listener that will be called when layout bounds change.
7152      */
7153     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7154         ListenerInfo li = getListenerInfo();
7155         if (li.mOnLayoutChangeListeners == null) {
7156             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7157         }
7158         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7159             li.mOnLayoutChangeListeners.add(listener);
7160         }
7161     }
7162 
7163     /**
7164      * Remove a listener for layout changes.
7165      *
7166      * @param listener The listener for layout bounds change.
7167      */
7168     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7169         ListenerInfo li = mListenerInfo;
7170         if (li == null || li.mOnLayoutChangeListeners == null) {
7171             return;
7172         }
7173         li.mOnLayoutChangeListeners.remove(listener);
7174     }
7175 
7176     /**
7177      * Add a listener for attach state changes.
7178      *
7179      * This listener will be called whenever this view is attached or detached
7180      * from a window. Remove the listener using
7181      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7182      *
7183      * @param listener Listener to attach
7184      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7185      */
7186     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7187         ListenerInfo li = getListenerInfo();
7188         if (li.mOnAttachStateChangeListeners == null) {
7189             li.mOnAttachStateChangeListeners
7190                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7191         }
7192         li.mOnAttachStateChangeListeners.add(listener);
7193     }
7194 
7195     /**
7196      * Remove a listener for attach state changes. The listener will receive no further
7197      * notification of window attach/detach events.
7198      *
7199      * @param listener Listener to remove
7200      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7201      */
7202     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7203         ListenerInfo li = mListenerInfo;
7204         if (li == null || li.mOnAttachStateChangeListeners == null) {
7205             return;
7206         }
7207         li.mOnAttachStateChangeListeners.remove(listener);
7208     }
7209 
7210     /**
7211      * Returns the focus-change callback registered for this view.
7212      *
7213      * @return The callback, or null if one is not registered.
7214      */
7215     public OnFocusChangeListener getOnFocusChangeListener() {
7216         ListenerInfo li = mListenerInfo;
7217         return li != null ? li.mOnFocusChangeListener : null;
7218     }
7219 
7220     /**
7221      * Register a callback to be invoked when this view is clicked. If this view is not
7222      * clickable, it becomes clickable.
7223      *
7224      * @param l The callback that will run
7225      *
7226      * @see #setClickable(boolean)
7227      */
7228     public void setOnClickListener(@Nullable OnClickListener l) {
7229         if (!isClickable()) {
7230             setClickable(true);
7231         }
7232         getListenerInfo().mOnClickListener = l;
7233     }
7234 
7235     /**
7236      * Return whether this view has an attached OnClickListener.  Returns
7237      * true if there is a listener, false if there is none.
7238      */
7239     public boolean hasOnClickListeners() {
7240         ListenerInfo li = mListenerInfo;
7241         return (li != null && li.mOnClickListener != null);
7242     }
7243 
7244     /**
7245      * Register a callback to be invoked when this view is clicked and held. If this view is not
7246      * long clickable, it becomes long clickable.
7247      *
7248      * @param l The callback that will run
7249      *
7250      * @see #setLongClickable(boolean)
7251      */
7252     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7253         if (!isLongClickable()) {
7254             setLongClickable(true);
7255         }
7256         getListenerInfo().mOnLongClickListener = l;
7257     }
7258 
7259     /**
7260      * Return whether this view has an attached OnLongClickListener.  Returns
7261      * true if there is a listener, false if there is none.
7262      */
7263     public boolean hasOnLongClickListeners() {
7264         ListenerInfo li = mListenerInfo;
7265         return (li != null && li.mOnLongClickListener != null);
7266     }
7267 
7268     /**
7269      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7270      * @hide
7271      */
7272     @Nullable
7273     public OnLongClickListener getOnLongClickListener() {
7274         ListenerInfo li = mListenerInfo;
7275         return (li != null) ? li.mOnLongClickListener : null;
7276     }
7277 
7278     /**
7279      * Register a callback to be invoked when this view is context clicked. If the view is not
7280      * context clickable, it becomes context clickable.
7281      *
7282      * @param l The callback that will run
7283      * @see #setContextClickable(boolean)
7284      */
7285     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7286         if (!isContextClickable()) {
7287             setContextClickable(true);
7288         }
7289         getListenerInfo().mOnContextClickListener = l;
7290     }
7291 
7292     /**
7293      * Register a callback to be invoked when the context menu for this view is
7294      * being built. If this view is not long clickable, it becomes long clickable.
7295      *
7296      * @param l The callback that will run
7297      *
7298      */
7299     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7300         if (!isLongClickable()) {
7301             setLongClickable(true);
7302         }
7303         getListenerInfo().mOnCreateContextMenuListener = l;
7304     }
7305 
7306     /**
7307      * Set an observer to collect stats for each frame rendered for this view.
7308      *
7309      * @hide
7310      */
7311     public void addFrameMetricsListener(Window window,
7312             Window.OnFrameMetricsAvailableListener listener,
7313             Handler handler) {
7314         if (mAttachInfo != null) {
7315             if (mAttachInfo.mThreadedRenderer != null) {
7316                 if (mFrameMetricsObservers == null) {
7317                     mFrameMetricsObservers = new ArrayList<>();
7318                 }
7319 
7320                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7321                 mFrameMetricsObservers.add(fmo);
7322                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7323             } else {
7324                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7325             }
7326         } else {
7327             if (mFrameMetricsObservers == null) {
7328                 mFrameMetricsObservers = new ArrayList<>();
7329             }
7330 
7331             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7332             mFrameMetricsObservers.add(fmo);
7333         }
7334     }
7335 
7336     /**
7337      * Remove observer configured to collect frame stats for this view.
7338      *
7339      * @hide
7340      */
7341     public void removeFrameMetricsListener(
7342             Window.OnFrameMetricsAvailableListener listener) {
7343         ThreadedRenderer renderer = getThreadedRenderer();
7344         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7345         if (fmo == null) {
7346             throw new IllegalArgumentException(
7347                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7348         }
7349 
7350         if (mFrameMetricsObservers != null) {
7351             mFrameMetricsObservers.remove(fmo);
7352             if (renderer != null) {
7353                 renderer.removeObserver(fmo.getRendererObserver());
7354             }
7355         }
7356     }
7357 
7358     private void registerPendingFrameMetricsObservers() {
7359         if (mFrameMetricsObservers != null) {
7360             ThreadedRenderer renderer = getThreadedRenderer();
7361             if (renderer != null) {
7362                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7363                     renderer.addObserver(fmo.getRendererObserver());
7364                 }
7365             } else {
7366                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7367             }
7368         }
7369     }
7370 
7371     private FrameMetricsObserver findFrameMetricsObserver(
7372             Window.OnFrameMetricsAvailableListener listener) {
7373         if (mFrameMetricsObservers != null) {
7374             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7375                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7376                 if (observer.mListener == listener) {
7377                     return observer;
7378                 }
7379             }
7380         }
7381 
7382         return null;
7383     }
7384 
7385     /** @hide */
7386     public void setNotifyAutofillManagerOnClick(boolean notify) {
7387         if (notify) {
7388             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7389         } else {
7390             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7391         }
7392     }
7393 
7394     private void notifyAutofillManagerOnClick() {
7395         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7396             try {
7397                 getAutofillManager().notifyViewClicked(this);
7398             } finally {
7399                 // Set it to already called so it's not called twice when called by
7400                 // performClickInternal()
7401                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7402             }
7403         }
7404     }
7405 
7406     /**
7407      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7408      * {@code performClick()} directly to make sure the autofill manager is notified when
7409      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7410      * method).
7411      */
7412     private boolean performClickInternal() {
7413         // Must notify autofill manager before performing the click actions to avoid scenarios where
7414         // the app has a click listener that changes the state of views the autofill service might
7415         // be interested on.
7416         notifyAutofillManagerOnClick();
7417 
7418         return performClick();
7419     }
7420 
7421     /**
7422      * Call this view's OnClickListener, if it is defined.  Performs all normal
7423      * actions associated with clicking: reporting accessibility event, playing
7424      * a sound, etc.
7425      *
7426      * @return True there was an assigned OnClickListener that was called, false
7427      *         otherwise is returned.
7428      */
7429     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7430     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7431     // could extend this method without calling super.performClick()).
7432     public boolean performClick() {
7433         // We still need to call this method to handle the cases where performClick() was called
7434         // externally, instead of through performClickInternal()
7435         notifyAutofillManagerOnClick();
7436 
7437         final boolean result;
7438         final ListenerInfo li = mListenerInfo;
7439         if (li != null && li.mOnClickListener != null) {
7440             playSoundEffect(SoundEffectConstants.CLICK);
7441             li.mOnClickListener.onClick(this);
7442             result = true;
7443         } else {
7444             result = false;
7445         }
7446 
7447         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7448 
7449         notifyEnterOrExitForAutoFillIfNeeded(true);
7450 
7451         return result;
7452     }
7453 
7454     /**
7455      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7456      * this only calls the listener, and does not do any associated clicking
7457      * actions like reporting an accessibility event.
7458      *
7459      * @return True there was an assigned OnClickListener that was called, false
7460      *         otherwise is returned.
7461      */
7462     public boolean callOnClick() {
7463         ListenerInfo li = mListenerInfo;
7464         if (li != null && li.mOnClickListener != null) {
7465             li.mOnClickListener.onClick(this);
7466             return true;
7467         }
7468         return false;
7469     }
7470 
7471     /**
7472      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7473      * context menu if the OnLongClickListener did not consume the event.
7474      *
7475      * @return {@code true} if one of the above receivers consumed the event,
7476      *         {@code false} otherwise
7477      */
7478     public boolean performLongClick() {
7479         return performLongClickInternal(mLongClickX, mLongClickY);
7480     }
7481 
7482     /**
7483      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7484      * context menu if the OnLongClickListener did not consume the event,
7485      * anchoring it to an (x,y) coordinate.
7486      *
7487      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7488      *          to disable anchoring
7489      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7490      *          to disable anchoring
7491      * @return {@code true} if one of the above receivers consumed the event,
7492      *         {@code false} otherwise
7493      */
7494     public boolean performLongClick(float x, float y) {
7495         mLongClickX = x;
7496         mLongClickY = y;
7497         final boolean handled = performLongClick();
7498         mLongClickX = Float.NaN;
7499         mLongClickY = Float.NaN;
7500         return handled;
7501     }
7502 
7503     /**
7504      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7505      * context menu if the OnLongClickListener did not consume the event,
7506      * optionally anchoring it to an (x,y) coordinate.
7507      *
7508      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7509      *          to disable anchoring
7510      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7511      *          to disable anchoring
7512      * @return {@code true} if one of the above receivers consumed the event,
7513      *         {@code false} otherwise
7514      */
7515     private boolean performLongClickInternal(float x, float y) {
7516         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7517 
7518         boolean handled = false;
7519         final ListenerInfo li = mListenerInfo;
7520         if (li != null && li.mOnLongClickListener != null) {
7521             handled = li.mOnLongClickListener.onLongClick(View.this);
7522         }
7523         if (!handled) {
7524             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7525             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7526         }
7527         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7528             if (!handled) {
7529                 handled = showLongClickTooltip((int) x, (int) y);
7530             }
7531         }
7532         if (handled) {
7533             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7534         }
7535         return handled;
7536     }
7537 
7538     /**
7539      * Call this view's OnContextClickListener, if it is defined.
7540      *
7541      * @param x the x coordinate of the context click
7542      * @param y the y coordinate of the context click
7543      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7544      *         otherwise.
7545      */
7546     public boolean performContextClick(float x, float y) {
7547         return performContextClick();
7548     }
7549 
7550     /**
7551      * Call this view's OnContextClickListener, if it is defined.
7552      *
7553      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7554      *         otherwise.
7555      */
7556     public boolean performContextClick() {
7557         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7558 
7559         boolean handled = false;
7560         ListenerInfo li = mListenerInfo;
7561         if (li != null && li.mOnContextClickListener != null) {
7562             handled = li.mOnContextClickListener.onContextClick(View.this);
7563         }
7564         if (handled) {
7565             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7566         }
7567         return handled;
7568     }
7569 
7570     /**
7571      * Performs button-related actions during a touch down event.
7572      *
7573      * @param event The event.
7574      * @return True if the down was consumed.
7575      *
7576      * @hide
7577      */
7578     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7579         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7580             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7581             showContextMenu(event.getX(), event.getY());
7582             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7583             return true;
7584         }
7585         return false;
7586     }
7587 
7588     /**
7589      * Shows the context menu for this view.
7590      *
7591      * @return {@code true} if the context menu was shown, {@code false}
7592      *         otherwise
7593      * @see #showContextMenu(float, float)
7594      */
7595     public boolean showContextMenu() {
7596         return getParent().showContextMenuForChild(this);
7597     }
7598 
7599     /**
7600      * Shows the context menu for this view anchored to the specified
7601      * view-relative coordinate.
7602      *
7603      * @param x the X coordinate in pixels relative to the view to which the
7604      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7605      * @param y the Y coordinate in pixels relative to the view to which the
7606      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7607      * @return {@code true} if the context menu was shown, {@code false}
7608      *         otherwise
7609      */
7610     public boolean showContextMenu(float x, float y) {
7611         return getParent().showContextMenuForChild(this, x, y);
7612     }
7613 
7614     /**
7615      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7616      *
7617      * @param callback Callback that will control the lifecycle of the action mode
7618      * @return The new action mode if it is started, null otherwise
7619      *
7620      * @see ActionMode
7621      * @see #startActionMode(android.view.ActionMode.Callback, int)
7622      */
7623     public ActionMode startActionMode(ActionMode.Callback callback) {
7624         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7625     }
7626 
7627     /**
7628      * Start an action mode with the given type.
7629      *
7630      * @param callback Callback that will control the lifecycle of the action mode
7631      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7632      * @return The new action mode if it is started, null otherwise
7633      *
7634      * @see ActionMode
7635      */
7636     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7637         ViewParent parent = getParent();
7638         if (parent == null) return null;
7639         try {
7640             return parent.startActionModeForChild(this, callback, type);
7641         } catch (AbstractMethodError ame) {
7642             // Older implementations of custom views might not implement this.
7643             return parent.startActionModeForChild(this, callback);
7644         }
7645     }
7646 
7647     /**
7648      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7649      * Context, creating a unique View identifier to retrieve the result.
7650      *
7651      * @param intent The Intent to be started.
7652      * @param requestCode The request code to use.
7653      * @hide
7654      */
7655     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7656     public void startActivityForResult(Intent intent, int requestCode) {
7657         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7658         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7659     }
7660 
7661     /**
7662      * If this View corresponds to the calling who, dispatches the activity result.
7663      * @param who The identifier for the targeted View to receive the result.
7664      * @param requestCode The integer request code originally supplied to
7665      *                    startActivityForResult(), allowing you to identify who this
7666      *                    result came from.
7667      * @param resultCode The integer result code returned by the child activity
7668      *                   through its setResult().
7669      * @param data An Intent, which can return result data to the caller
7670      *               (various data can be attached to Intent "extras").
7671      * @return {@code true} if the activity result was dispatched.
7672      * @hide
7673      */
7674     public boolean dispatchActivityResult(
7675             String who, int requestCode, int resultCode, Intent data) {
7676         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7677             onActivityResult(requestCode, resultCode, data);
7678             mStartActivityRequestWho = null;
7679             return true;
7680         }
7681         return false;
7682     }
7683 
7684     /**
7685      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7686      *
7687      * @param requestCode The integer request code originally supplied to
7688      *                    startActivityForResult(), allowing you to identify who this
7689      *                    result came from.
7690      * @param resultCode The integer result code returned by the child activity
7691      *                   through its setResult().
7692      * @param data An Intent, which can return result data to the caller
7693      *               (various data can be attached to Intent "extras").
7694      * @hide
7695      */
7696     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7697         // Do nothing.
7698     }
7699 
7700     /**
7701      * Register a callback to be invoked when a hardware key is pressed in this view.
7702      * Key presses in software input methods will generally not trigger the methods of
7703      * this listener.
7704      * @param l the key listener to attach to this view
7705      */
7706     public void setOnKeyListener(OnKeyListener l) {
7707         getListenerInfo().mOnKeyListener = l;
7708     }
7709 
7710     /**
7711      * Register a callback to be invoked when a touch event is sent to this view.
7712      * @param l the touch listener to attach to this view
7713      */
7714     public void setOnTouchListener(OnTouchListener l) {
7715         getListenerInfo().mOnTouchListener = l;
7716     }
7717 
7718     /**
7719      * Register a callback to be invoked when a generic motion event is sent to this view.
7720      * @param l the generic motion listener to attach to this view
7721      */
7722     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7723         getListenerInfo().mOnGenericMotionListener = l;
7724     }
7725 
7726     /**
7727      * Register a callback to be invoked when a hover event is sent to this view.
7728      * @param l the hover listener to attach to this view
7729      */
7730     public void setOnHoverListener(OnHoverListener l) {
7731         getListenerInfo().mOnHoverListener = l;
7732     }
7733 
7734     /**
7735      * Register a drag event listener callback object for this View. The parameter is
7736      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7737      * View, the system calls the
7738      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7739      * @param l An implementation of {@link android.view.View.OnDragListener}.
7740      */
7741     public void setOnDragListener(OnDragListener l) {
7742         getListenerInfo().mOnDragListener = l;
7743     }
7744 
7745     /**
7746      * Give this view focus. This will cause
7747      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7748      *
7749      * Note: this does not check whether this {@link View} should get focus, it just
7750      * gives it focus no matter what.  It should only be called internally by framework
7751      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7752      *
7753      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7754      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7755      *        focus moved when requestFocus() is called. It may not always
7756      *        apply, in which case use the default View.FOCUS_DOWN.
7757      * @param previouslyFocusedRect The rectangle of the view that had focus
7758      *        prior in this View's coordinate system.
7759      */
7760     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7761         if (DBG) {
7762             System.out.println(this + " requestFocus()");
7763         }
7764 
7765         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7766             mPrivateFlags |= PFLAG_FOCUSED;
7767 
7768             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7769 
7770             if (mParent != null) {
7771                 mParent.requestChildFocus(this, this);
7772                 updateFocusedInCluster(oldFocus, direction);
7773             }
7774 
7775             if (mAttachInfo != null) {
7776                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
7777             }
7778 
7779             onFocusChanged(true, direction, previouslyFocusedRect);
7780             refreshDrawableState();
7781         }
7782     }
7783 
7784     /**
7785      * Sets this view's preference for reveal behavior when it gains focus.
7786      *
7787      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
7788      * this view would prefer to be brought fully into view when it gains focus.
7789      * For example, a text field that a user is meant to type into. Other views such
7790      * as scrolling containers may prefer to opt-out of this behavior.</p>
7791      *
7792      * <p>The default value for views is true, though subclasses may change this
7793      * based on their preferred behavior.</p>
7794      *
7795      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
7796      *
7797      * @see #getRevealOnFocusHint()
7798      */
7799     public final void setRevealOnFocusHint(boolean revealOnFocus) {
7800         if (revealOnFocus) {
7801             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
7802         } else {
7803             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
7804         }
7805     }
7806 
7807     /**
7808      * Returns this view's preference for reveal behavior when it gains focus.
7809      *
7810      * <p>When this method returns true for a child view requesting focus, ancestor
7811      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
7812      * should make a best effort to make the newly focused child fully visible to the user.
7813      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
7814      * other properties affecting visibility to the user as part of the focus change.</p>
7815      *
7816      * @return true if this view would prefer to become fully visible when it gains focus,
7817      *         false if it would prefer not to disrupt scroll positioning
7818      *
7819      * @see #setRevealOnFocusHint(boolean)
7820      */
7821     public final boolean getRevealOnFocusHint() {
7822         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
7823     }
7824 
7825     /**
7826      * Populates <code>outRect</code> with the hotspot bounds. By default,
7827      * the hotspot bounds are identical to the screen bounds.
7828      *
7829      * @param outRect rect to populate with hotspot bounds
7830      * @hide Only for internal use by views and widgets.
7831      */
7832     public void getHotspotBounds(Rect outRect) {
7833         final Drawable background = getBackground();
7834         if (background != null) {
7835             background.getHotspotBounds(outRect);
7836         } else {
7837             getBoundsOnScreen(outRect);
7838         }
7839     }
7840 
7841     /**
7842      * Request that a rectangle of this view be visible on the screen,
7843      * scrolling if necessary just enough.
7844      *
7845      * <p>A View should call this if it maintains some notion of which part
7846      * of its content is interesting.  For example, a text editing view
7847      * should call this when its cursor moves.
7848      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7849      * It should not be affected by which part of the View is currently visible or its scroll
7850      * position.
7851      *
7852      * @param rectangle The rectangle in the View's content coordinate space
7853      * @return Whether any parent scrolled.
7854      */
7855     public boolean requestRectangleOnScreen(Rect rectangle) {
7856         return requestRectangleOnScreen(rectangle, false);
7857     }
7858 
7859     /**
7860      * Request that a rectangle of this view be visible on the screen,
7861      * scrolling if necessary just enough.
7862      *
7863      * <p>A View should call this if it maintains some notion of which part
7864      * of its content is interesting.  For example, a text editing view
7865      * should call this when its cursor moves.
7866      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7867      * It should not be affected by which part of the View is currently visible or its scroll
7868      * position.
7869      * <p>When <code>immediate</code> is set to true, scrolling will not be
7870      * animated.
7871      *
7872      * @param rectangle The rectangle in the View's content coordinate space
7873      * @param immediate True to forbid animated scrolling, false otherwise
7874      * @return Whether any parent scrolled.
7875      */
7876     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7877         if (mParent == null) {
7878             return false;
7879         }
7880 
7881         View child = this;
7882 
7883         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7884         position.set(rectangle);
7885 
7886         ViewParent parent = mParent;
7887         boolean scrolled = false;
7888         while (parent != null) {
7889             rectangle.set((int) position.left, (int) position.top,
7890                     (int) position.right, (int) position.bottom);
7891 
7892             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7893 
7894             if (!(parent instanceof View)) {
7895                 break;
7896             }
7897 
7898             // move it from child's content coordinate space to parent's content coordinate space
7899             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
7900 
7901             child = (View) parent;
7902             parent = child.getParent();
7903         }
7904 
7905         return scrolled;
7906     }
7907 
7908     /**
7909      * Called when this view wants to give up focus. If focus is cleared
7910      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
7911      * <p>
7912      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
7913      * to the first focusable View from the top after focus is cleared. Hence, if this
7914      * View is the first from the top that can take focus, then all callbacks
7915      * related to clearing focus will be invoked after which the framework will
7916      * give focus to this view.
7917      * </p>
7918      */
7919     public void clearFocus() {
7920         if (DBG) {
7921             System.out.println(this + " clearFocus()");
7922         }
7923 
7924         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
7925         clearFocusInternal(null, true, refocus);
7926     }
7927 
7928     /**
7929      * Clears focus from the view, optionally propagating the change up through
7930      * the parent hierarchy and requesting that the root view place new focus.
7931      *
7932      * @param propagate whether to propagate the change up through the parent
7933      *            hierarchy
7934      * @param refocus when propagate is true, specifies whether to request the
7935      *            root view place new focus
7936      */
7937     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
7938         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
7939             mPrivateFlags &= ~PFLAG_FOCUSED;
7940             clearParentsWantFocus();
7941 
7942             if (propagate && mParent != null) {
7943                 mParent.clearChildFocus(this);
7944             }
7945 
7946             onFocusChanged(false, 0, null);
7947             refreshDrawableState();
7948 
7949             if (propagate && (!refocus || !rootViewRequestFocus())) {
7950                 notifyGlobalFocusCleared(this);
7951             }
7952         }
7953     }
7954 
7955     void notifyGlobalFocusCleared(View oldFocus) {
7956         if (oldFocus != null && mAttachInfo != null) {
7957             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
7958         }
7959     }
7960 
7961     boolean rootViewRequestFocus() {
7962         final View root = getRootView();
7963         return root != null && root.requestFocus();
7964     }
7965 
7966     /**
7967      * Called internally by the view system when a new view is getting focus.
7968      * This is what clears the old focus.
7969      * <p>
7970      * <b>NOTE:</b> The parent view's focused child must be updated manually
7971      * after calling this method. Otherwise, the view hierarchy may be left in
7972      * an inconstent state.
7973      */
7974     void unFocus(View focused) {
7975         if (DBG) {
7976             System.out.println(this + " unFocus()");
7977         }
7978 
7979         clearFocusInternal(focused, false, false);
7980     }
7981 
7982     /**
7983      * Returns true if this view has focus itself, or is the ancestor of the
7984      * view that has focus.
7985      *
7986      * @return True if this view has or contains focus, false otherwise.
7987      */
7988     @ViewDebug.ExportedProperty(category = "focus")
7989     public boolean hasFocus() {
7990         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7991     }
7992 
7993     /**
7994      * Returns true if this view is focusable or if it contains a reachable View
7995      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
7996      * is a view whose parents do not block descendants focus.
7997      * Only {@link #VISIBLE} views are considered focusable.
7998      *
7999      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8000      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8001      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8002      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8003      * {@code false} for views not explicitly marked as focusable.
8004      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8005      * behavior.</p>
8006      *
8007      * @return {@code true} if the view is focusable or if the view contains a focusable
8008      *         view, {@code false} otherwise
8009      *
8010      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8011      * @see ViewGroup#getTouchscreenBlocksFocus()
8012      * @see #hasExplicitFocusable()
8013      */
8014     public boolean hasFocusable() {
8015         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8016     }
8017 
8018     /**
8019      * Returns true if this view is focusable or if it contains a reachable View
8020      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8021      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8022      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8023      * {@link #FOCUSABLE} are considered focusable.
8024      *
8025      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8026      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8027      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8028      * to focusable will not.</p>
8029      *
8030      * @return {@code true} if the view is focusable or if the view contains a focusable
8031      *         view, {@code false} otherwise
8032      *
8033      * @see #hasFocusable()
8034      */
8035     public boolean hasExplicitFocusable() {
8036         return hasFocusable(false, true);
8037     }
8038 
8039     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8040         if (!isFocusableInTouchMode()) {
8041             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8042                 final ViewGroup g = (ViewGroup) p;
8043                 if (g.shouldBlockFocusForTouchscreen()) {
8044                     return false;
8045                 }
8046             }
8047         }
8048 
8049         // Invisible, gone, or disabled views are never focusable.
8050         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8051                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8052             return false;
8053         }
8054 
8055         // Only use effective focusable value when allowed.
8056         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8057             return true;
8058         }
8059 
8060         return false;
8061     }
8062 
8063     /**
8064      * Called by the view system when the focus state of this view changes.
8065      * When the focus change event is caused by directional navigation, direction
8066      * and previouslyFocusedRect provide insight into where the focus is coming from.
8067      * When overriding, be sure to call up through to the super class so that
8068      * the standard focus handling will occur.
8069      *
8070      * @param gainFocus True if the View has focus; false otherwise.
8071      * @param direction The direction focus has moved when requestFocus()
8072      *                  is called to give this view focus. Values are
8073      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8074      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8075      *                  It may not always apply, in which case use the default.
8076      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8077      *        system, of the previously focused view.  If applicable, this will be
8078      *        passed in as finer grained information about where the focus is coming
8079      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8080      */
8081     @CallSuper
8082     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8083             @Nullable Rect previouslyFocusedRect) {
8084         if (gainFocus) {
8085             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8086         } else {
8087             notifyViewAccessibilityStateChangedIfNeeded(
8088                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8089         }
8090 
8091         // Here we check whether we still need the default focus highlight, and switch it on/off.
8092         switchDefaultFocusHighlight();
8093 
8094         if (!gainFocus) {
8095             if (isPressed()) {
8096                 setPressed(false);
8097             }
8098             if (hasWindowFocus()) {
8099                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8100             }
8101             onFocusLost();
8102         } else if (hasWindowFocus()) {
8103             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8104         }
8105 
8106         invalidate(true);
8107         ListenerInfo li = mListenerInfo;
8108         if (li != null && li.mOnFocusChangeListener != null) {
8109             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8110         }
8111 
8112         if (mAttachInfo != null) {
8113             mAttachInfo.mKeyDispatchState.reset(this);
8114         }
8115 
8116         if (mParent != null) {
8117             mParent.onDescendantUnbufferedRequested();
8118         }
8119 
8120         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8121     }
8122 
8123     /**
8124      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8125      *
8126      * @param hasFocus {@code true} when the {@link View} is being focused.
8127      */
8128     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8129         if (mAttachInfo == null) {
8130             return;
8131         }
8132         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8133     }
8134 
8135     /** @hide */
8136     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8137         if (canNotifyAutofillEnterExitEvent()) {
8138             AutofillManager afm = getAutofillManager();
8139             if (afm != null) {
8140                 if (enter && isFocused()) {
8141                     // We have not been laid out yet, hence cannot evaluate
8142                     // whether this view is visible to the user, we will do
8143                     // the evaluation once layout is complete.
8144                     if (!isLaidOut()) {
8145                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8146                     } else if (isVisibleToUser()) {
8147                         // TODO This is a potential problem that View gets focus before it's visible
8148                         // to User. Ideally View should handle the event when isVisibleToUser()
8149                         // becomes true where it should issue notifyViewEntered().
8150                         afm.notifyViewEntered(this);
8151                     }
8152                 } else if (!enter && !isFocused()) {
8153                     afm.notifyViewExited(this);
8154                 }
8155             }
8156         }
8157     }
8158 
8159     /**
8160      * Visually distinct portion of a window with window-like semantics are considered panes for
8161      * accessibility purposes. One example is the content view of a fragment that is replaced.
8162      * In order for accessibility services to understand a pane's window-like behavior, panes
8163      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
8164      * when they appear, disappear, or change title.
8165      *
8166      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8167      *                               View is not a pane.
8168      *
8169      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8170      *
8171      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8172      */
8173     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8174         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8175             mAccessibilityPaneTitle = accessibilityPaneTitle;
8176             notifyViewAccessibilityStateChangedIfNeeded(
8177                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8178         }
8179     }
8180 
8181     /**
8182      * Get the title of the pane for purposes of accessibility.
8183      *
8184      * @return The current pane title.
8185      *
8186      * {@see #setAccessibilityPaneTitle}.
8187      *
8188      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8189      */
8190     @InspectableProperty
8191     @Nullable
8192     public CharSequence getAccessibilityPaneTitle() {
8193         return mAccessibilityPaneTitle;
8194     }
8195 
8196     private boolean isAccessibilityPane() {
8197         return mAccessibilityPaneTitle != null;
8198     }
8199 
8200     /**
8201      * Sends an accessibility event of the given type. If accessibility is
8202      * not enabled this method has no effect. The default implementation calls
8203      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8204      * to populate information about the event source (this View), then calls
8205      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8206      * populate the text content of the event source including its descendants,
8207      * and last calls
8208      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8209      * on its parent to request sending of the event to interested parties.
8210      * <p>
8211      * If an {@link AccessibilityDelegate} has been specified via calling
8212      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8213      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8214      * responsible for handling this call.
8215      * </p>
8216      *
8217      * @param eventType The type of the event to send, as defined by several types from
8218      * {@link android.view.accessibility.AccessibilityEvent}, such as
8219      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
8220      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8221      *
8222      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8223      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8224      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8225      * @see AccessibilityDelegate
8226      */
8227     public void sendAccessibilityEvent(int eventType) {
8228         if (mAccessibilityDelegate != null) {
8229             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8230         } else {
8231             sendAccessibilityEventInternal(eventType);
8232         }
8233     }
8234 
8235     /**
8236      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8237      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8238      * specified text to its users.
8239      * <p>
8240      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8241      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8242      * accurately supplying the semantics of their UI.
8243      * They should not need to specify what exactly is announced to users.
8244      *
8245      * @param text The announcement text.
8246      */
8247     public void announceForAccessibility(CharSequence text) {
8248         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8249             AccessibilityEvent event = AccessibilityEvent.obtain(
8250                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8251             onInitializeAccessibilityEvent(event);
8252             event.getText().add(text);
8253             event.setContentDescription(null);
8254             mParent.requestSendAccessibilityEvent(this, event);
8255         }
8256     }
8257 
8258     /**
8259      * @see #sendAccessibilityEvent(int)
8260      *
8261      * Note: Called from the default {@link AccessibilityDelegate}.
8262      *
8263      * @hide
8264      */
8265     public void sendAccessibilityEventInternal(int eventType) {
8266         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8267             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8268         }
8269     }
8270 
8271     /**
8272      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8273      * takes as an argument an empty {@link AccessibilityEvent} and does not
8274      * perform a check whether accessibility is enabled.
8275      * <p>
8276      * If an {@link AccessibilityDelegate} has been specified via calling
8277      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8278      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8279      * is responsible for handling this call.
8280      * </p>
8281      *
8282      * @param event The event to send.
8283      *
8284      * @see #sendAccessibilityEvent(int)
8285      */
8286     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8287         if (mAccessibilityDelegate != null) {
8288             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8289         } else {
8290             sendAccessibilityEventUncheckedInternal(event);
8291         }
8292     }
8293 
8294     /**
8295      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8296      *
8297      * Note: Called from the default {@link AccessibilityDelegate}.
8298      *
8299      * @hide
8300      */
8301     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8302         // Panes disappearing are relevant even if though the view is no longer visible.
8303         boolean isWindowStateChanged =
8304                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8305         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8306                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8307         boolean detached = detached();
8308         if (!isShown() && !isWindowDisappearedEvent && !detached) {
8309             return;
8310         }
8311         onInitializeAccessibilityEvent(event);
8312         // Only a subset of accessibility events populates text content.
8313         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8314             dispatchPopulateAccessibilityEvent(event);
8315         }
8316         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
8317         if (throttle != null) {
8318             throttle.post(event);
8319         } else if (!isWindowDisappearedEvent && detached) {
8320             // Views could be attached soon later. Accessibility events during this temporarily
8321             // detached period should be sent too.
8322             postDelayed(() -> {
8323                 if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
8324                     requestParentSendAccessibilityEvent(event);
8325                 }
8326             }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8327         } else {
8328             requestParentSendAccessibilityEvent(event);
8329         }
8330     }
8331 
8332     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
8333         ViewParent parent = getParent();
8334         if (parent != null) {
8335             getParent().requestSendAccessibilityEvent(this, event);
8336         }
8337     }
8338 
8339     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
8340             AccessibilityEvent event) {
8341         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
8342             if (mSendViewScrolledAccessibilityEvent == null) {
8343                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8344             }
8345             return mSendViewScrolledAccessibilityEvent;
8346         }
8347         boolean isStateContentChanged = (event.getContentChangeTypes()
8348                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
8349         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
8350                 && isStateContentChanged) {
8351             if (mSendStateChangedAccessibilityEvent == null) {
8352                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
8353             }
8354             return mSendStateChangedAccessibilityEvent;
8355         }
8356         return null;
8357     }
8358 
8359     private void clearAccessibilityThrottles() {
8360         cancel(mSendViewScrolledAccessibilityEvent);
8361         cancel(mSendStateChangedAccessibilityEvent);
8362     }
8363 
8364     /**
8365      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8366      * to its children for adding their text content to the event. Note that the
8367      * event text is populated in a separate dispatch path since we add to the
8368      * event not only the text of the source but also the text of all its descendants.
8369      * A typical implementation will call
8370      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8371      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8372      * on each child. Override this method if custom population of the event text
8373      * content is required.
8374      * <p>
8375      * If an {@link AccessibilityDelegate} has been specified via calling
8376      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8377      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8378      * is responsible for handling this call.
8379      * </p>
8380      * <p>
8381      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8382      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8383      * </p>
8384      *
8385      * @param event The event.
8386      *
8387      * @return True if the event population was completed.
8388      */
8389     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8390         if (mAccessibilityDelegate != null) {
8391             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8392         } else {
8393             return dispatchPopulateAccessibilityEventInternal(event);
8394         }
8395     }
8396 
8397     /**
8398      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8399      *
8400      * Note: Called from the default {@link AccessibilityDelegate}.
8401      *
8402      * @hide
8403      */
8404     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8405         onPopulateAccessibilityEvent(event);
8406         return false;
8407     }
8408 
8409     /**
8410      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8411      * giving a chance to this View to populate the accessibility event with its
8412      * text content. While this method is free to modify event
8413      * attributes other than text content, doing so should normally be performed in
8414      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8415      * <p>
8416      * Example: Adding formatted date string to an accessibility event in addition
8417      *          to the text added by the super implementation:
8418      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8419      *     super.onPopulateAccessibilityEvent(event);
8420      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8421      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8422      *         mCurrentDate.getTimeInMillis(), flags);
8423      *     event.getText().add(selectedDateUtterance);
8424      * }</pre>
8425      * <p>
8426      * If an {@link AccessibilityDelegate} has been specified via calling
8427      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8428      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8429      * is responsible for handling this call.
8430      * </p>
8431      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8432      * information to the event, in case the default implementation has basic information to add.
8433      * </p>
8434      *
8435      * @param event The accessibility event which to populate.
8436      *
8437      * @see #sendAccessibilityEvent(int)
8438      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8439      */
8440     @CallSuper
8441     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8442         if (mAccessibilityDelegate != null) {
8443             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8444         } else {
8445             onPopulateAccessibilityEventInternal(event);
8446         }
8447     }
8448 
8449     /**
8450      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8451      *
8452      * Note: Called from the default {@link AccessibilityDelegate}.
8453      *
8454      * @hide
8455      */
8456     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8457         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8458                 && isAccessibilityPane()) {
8459             event.getText().add(getAccessibilityPaneTitle());
8460         }
8461     }
8462 
8463     /**
8464      * Initializes an {@link AccessibilityEvent} with information about
8465      * this View which is the event source. In other words, the source of
8466      * an accessibility event is the view whose state change triggered firing
8467      * the event.
8468      * <p>
8469      * Example: Setting the password property of an event in addition
8470      *          to properties set by the super implementation:
8471      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8472      *     super.onInitializeAccessibilityEvent(event);
8473      *     event.setPassword(true);
8474      * }</pre>
8475      * <p>
8476      * If an {@link AccessibilityDelegate} has been specified via calling
8477      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8478      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8479      * is responsible for handling this call.
8480      * </p>
8481      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8482      * information to the event, in case the default implementation has basic information to add.
8483      * </p>
8484      * @param event The event to initialize.
8485      *
8486      * @see #sendAccessibilityEvent(int)
8487      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8488      */
8489     @CallSuper
8490     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8491         if (mAccessibilityDelegate != null) {
8492             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8493         } else {
8494             onInitializeAccessibilityEventInternal(event);
8495         }
8496     }
8497 
8498     /**
8499      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8500      *
8501      * Note: Called from the default {@link AccessibilityDelegate}.
8502      *
8503      * @hide
8504      */
8505     @UnsupportedAppUsage
8506     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8507         event.setSource(this);
8508         event.setClassName(getAccessibilityClassName());
8509         event.setPackageName(getContext().getPackageName());
8510         event.setEnabled(isEnabled());
8511         event.setContentDescription(mContentDescription);
8512         event.setScrollX(getScrollX());
8513         event.setScrollY(getScrollY());
8514 
8515         switch (event.getEventType()) {
8516             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8517                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8518                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8519                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8520                 event.setItemCount(focusablesTempList.size());
8521                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8522                 if (mAttachInfo != null) {
8523                     focusablesTempList.clear();
8524                 }
8525             } break;
8526             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8527                 CharSequence text = getIterableTextForAccessibility();
8528                 if (text != null && text.length() > 0) {
8529                     event.setFromIndex(getAccessibilitySelectionStart());
8530                     event.setToIndex(getAccessibilitySelectionEnd());
8531                     event.setItemCount(text.length());
8532                 }
8533             } break;
8534         }
8535     }
8536 
8537     /**
8538      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8539      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8540      * This method is responsible for obtaining an accessibility node info from a
8541      * pool of reusable instances and calling
8542      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8543      * initialize the former.
8544      * <p>
8545      * Note: The client is responsible for recycling the obtained instance by calling
8546      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8547      * </p>
8548      *
8549      * @return A populated {@link AccessibilityNodeInfo}.
8550      *
8551      * @see AccessibilityNodeInfo
8552      */
8553     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8554         if (mAccessibilityDelegate != null) {
8555             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8556         } else {
8557             return createAccessibilityNodeInfoInternal();
8558         }
8559     }
8560 
8561     /**
8562      * @see #createAccessibilityNodeInfo()
8563      *
8564      * @hide
8565      */
8566     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8567         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8568         if (provider != null) {
8569             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8570         } else {
8571             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8572             onInitializeAccessibilityNodeInfo(info);
8573             return info;
8574         }
8575     }
8576 
8577     /**
8578      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8579      * The base implementation sets:
8580      * <ul>
8581      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8582      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8583      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8584      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8585      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8586      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8587      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8588      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8589      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8590      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8591      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8592      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8593      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8594      * </ul>
8595      * <p>
8596      * Subclasses should override this method, call the super implementation,
8597      * and set additional attributes.
8598      * </p>
8599      * <p>
8600      * If an {@link AccessibilityDelegate} has been specified via calling
8601      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8602      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8603      * is responsible for handling this call.
8604      * </p>
8605      *
8606      * @param info The instance to initialize.
8607      */
8608     @CallSuper
8609     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8610         if (mAccessibilityDelegate != null) {
8611             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8612         } else {
8613             onInitializeAccessibilityNodeInfoInternal(info);
8614         }
8615     }
8616 
8617     /**
8618      * Gets the location of this view in screen coordinates.
8619      *
8620      * @param outRect The output location
8621      * @hide
8622      */
8623     @UnsupportedAppUsage
8624     public void getBoundsOnScreen(Rect outRect) {
8625         getBoundsOnScreen(outRect, false);
8626     }
8627 
8628     /**
8629      * Gets the location of this view in screen coordinates.
8630      *
8631      * @param outRect The output location
8632      * @param clipToParent Whether to clip child bounds to the parent ones.
8633      * @hide
8634      */
8635     @UnsupportedAppUsage
8636     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
8637         if (mAttachInfo == null) {
8638             return;
8639         }
8640 
8641         RectF position = mAttachInfo.mTmpTransformRect;
8642         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8643         mapRectFromViewToScreenCoords(position, clipToParent);
8644         outRect.set(Math.round(position.left), Math.round(position.top),
8645                 Math.round(position.right), Math.round(position.bottom));
8646     }
8647 
8648     /**
8649      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8650      *
8651      * @param rect The rectangle to be mapped
8652      * @param clipToParent Whether to clip child bounds to the parent ones.
8653      * @hide
8654      */
8655     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8656         if (!hasIdentityMatrix()) {
8657             getMatrix().mapRect(rect);
8658         }
8659 
8660         rect.offset(mLeft, mTop);
8661 
8662         ViewParent parent = mParent;
8663         while (parent instanceof View) {
8664             View parentView = (View) parent;
8665 
8666             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
8667 
8668             if (clipToParent) {
8669                 rect.left = Math.max(rect.left, 0);
8670                 rect.top = Math.max(rect.top, 0);
8671                 rect.right = Math.min(rect.right, parentView.getWidth());
8672                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
8673             }
8674 
8675             if (!parentView.hasIdentityMatrix()) {
8676                 parentView.getMatrix().mapRect(rect);
8677             }
8678 
8679             rect.offset(parentView.mLeft, parentView.mTop);
8680 
8681             parent = parentView.mParent;
8682         }
8683 
8684         if (parent instanceof ViewRootImpl) {
8685             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
8686             rect.offset(0, -viewRootImpl.mCurScrollY);
8687         }
8688 
8689         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8690     }
8691 
8692     /**
8693      * Return the class name of this object to be used for accessibility purposes.
8694      * Subclasses should only override this if they are implementing something that
8695      * should be seen as a completely new class of view when used by accessibility,
8696      * unrelated to the class it is deriving from.  This is used to fill in
8697      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
8698      */
8699     public CharSequence getAccessibilityClassName() {
8700         return View.class.getName();
8701     }
8702 
8703     /**
8704      * Called when assist structure is being retrieved from a view as part of
8705      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
8706      * @param structure Fill in with structured view data.  The default implementation
8707      * fills in all data that can be inferred from the view itself.
8708      */
8709     public void onProvideStructure(ViewStructure structure) {
8710         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
8711     }
8712 
8713     /**
8714      * Populates a {@link ViewStructure} to fullfil an autofill request.
8715      *
8716      * <p>The structure should contain at least the following properties:
8717      * <ul>
8718      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
8719      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
8720      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
8721      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
8722      * </ul>
8723      *
8724      * <p>It's also recommended to set the following properties - the more properties the structure
8725      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
8726      * using the structure:
8727      *
8728      * <ul>
8729      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
8730      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
8731      *       view can only be filled with predefined values (typically used when the autofill type
8732      *       is {@link #AUTOFILL_TYPE_LIST}).
8733      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
8734      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
8735      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
8736      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
8737      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
8738      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
8739      *   <li>For views representing text fields, text properties such as the text itself
8740      *       ({@link ViewStructure#setText(CharSequence)}), text hints
8741      *       ({@link ViewStructure#setHint(CharSequence)}, input type
8742      *       ({@link ViewStructure#setInputType(int)}),
8743      *   <li>For views representing HTML nodes, its web domain
8744      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
8745      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
8746      * </ul>
8747      *
8748      * <p>The default implementation of this method already sets most of these properties based on
8749      * related {@link View} methods (for example, the autofill id is set using
8750      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
8751      * and views in the standard Android widgets library also override it to set their
8752      * relevant properties (for example, {@link android.widget.TextView} already sets the text
8753      * properties), so it's recommended to only override this method
8754      * (and call {@code super.onProvideAutofillStructure()}) when:
8755      *
8756      * <ul>
8757      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
8758      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
8759      *   <li>The view can only be autofilled with predefined options, so it can call
8760      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
8761      * </ul>
8762      *
8763      * <p><b>Note:</b> The {@code left} and {@code top} values set in
8764      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
8765      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
8766      *
8767      * <p>Views support the Autofill Framework mainly by:
8768      * <ul>
8769      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8770      *   <li>Notifying the Android System when the view value changed by calling
8771      *       {@link AutofillManager#notifyValueChanged(View)}.
8772      *   <li>Implementing the methods that autofill the view.
8773      * </ul>
8774      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
8775      * for the latter.
8776      *
8777      * @param structure fill in with structured view data for autofill purposes.
8778      * @param flags optional flags.
8779      *
8780      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8781      */
8782     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
8783         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
8784     }
8785 
8786     /**
8787      * Populates a {@link ViewStructure} for content capture.
8788      *
8789      * <p>This method is called after a view that is eligible for content capture
8790      * (for example, if it {@link #isImportantForContentCapture()}, an intelligence service is
8791      * enabled for the user, and the activity rendering the view is enabled for content capture)
8792      * is laid out and is visible. The populated structure is then passed to the service through
8793      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
8794      *
8795      * <p>The default implementation of this method sets the most relevant properties based on
8796      * related {@link View} methods, and views in the standard Android widgets library also
8797      * override it to set their relevant properties. Therefore, if overriding this method, it
8798      * is recommended to call {@code super.onProvideContentCaptureStructure()}.
8799      *
8800      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
8801      * the node representing this view and return right away, then asynchronously report (not
8802      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
8803      * changed by calling
8804      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
8805      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
8806      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
8807      * respectively. The structure for a child must be created using
8808      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
8809      * {@code autofillId} for a child can be obtained either through
8810      * {@code childStructure.getAutofillId()} or
8811      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
8812      *
8813      * <p>When the virtual view hierarchy represents a web page, you should also:
8814      *
8815      * <ul>
8816      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
8817      *   capture events should be generate for that URL.
8818      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
8819      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
8820      *   that subtree.
8821      * </ul>
8822      *
8823      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
8824      * <ul>
8825      *   <li>{@link ViewStructure#setChildCount(int)}
8826      *   <li>{@link ViewStructure#addChildCount(int)}
8827      *   <li>{@link ViewStructure#getChildCount()}
8828      *   <li>{@link ViewStructure#newChild(int)}
8829      *   <li>{@link ViewStructure#asyncNewChild(int)}
8830      *   <li>{@link ViewStructure#asyncCommit()}
8831      *   <li>{@link ViewStructure#setWebDomain(String)}
8832      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
8833      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
8834      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
8835      *   <li>{@link ViewStructure#setAlpha(float)}
8836      *   <li>{@link ViewStructure#setElevation(float)}
8837      *   <li>{@link ViewStructure#setTransformation(Matrix)}
8838      *
8839      * </ul>
8840      */
8841     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
8842         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
8843     }
8844 
8845     /** @hide */
8846     protected void onProvideStructure(@NonNull ViewStructure structure,
8847             @ViewStructureType int viewFor, int flags) {
8848         final int id = mID;
8849         if (id != NO_ID && !isViewIdGenerated(id)) {
8850             String pkg, type, entry;
8851             try {
8852                 final Resources res = getResources();
8853                 entry = res.getResourceEntryName(id);
8854                 type = res.getResourceTypeName(id);
8855                 pkg = res.getResourcePackageName(id);
8856             } catch (Resources.NotFoundException e) {
8857                 entry = type = pkg = null;
8858             }
8859             structure.setId(id, pkg, type, entry);
8860         } else {
8861             structure.setId(id, null, null, null);
8862         }
8863 
8864         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8865                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
8866             final @AutofillType int autofillType = getAutofillType();
8867             // Don't need to fill autofill info if view does not support it.
8868             // For example, only TextViews that are editable support autofill
8869             if (autofillType != AUTOFILL_TYPE_NONE) {
8870                 structure.setAutofillType(autofillType);
8871                 structure.setAutofillHints(getAutofillHints());
8872                 structure.setAutofillValue(getAutofillValue());
8873             }
8874             structure.setImportantForAutofill(getImportantForAutofill());
8875             structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
8876         }
8877 
8878         int ignoredParentLeft = 0;
8879         int ignoredParentTop = 0;
8880         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8881                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
8882             View parentGroup = null;
8883 
8884             ViewParent viewParent = getParent();
8885             if (viewParent instanceof View) {
8886                 parentGroup = (View) viewParent;
8887             }
8888 
8889             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
8890                 ignoredParentLeft += parentGroup.mLeft;
8891                 ignoredParentTop += parentGroup.mTop;
8892 
8893                 viewParent = parentGroup.getParent();
8894                 if (viewParent instanceof View) {
8895                     parentGroup = (View) viewParent;
8896                 } else {
8897                     break;
8898                 }
8899             }
8900         }
8901 
8902         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
8903                 mRight - mLeft, mBottom - mTop);
8904         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
8905             if (!hasIdentityMatrix()) {
8906                 structure.setTransformation(getMatrix());
8907             }
8908             structure.setElevation(getZ());
8909         }
8910         structure.setVisibility(getVisibility());
8911         structure.setEnabled(isEnabled());
8912         if (isClickable()) {
8913             structure.setClickable(true);
8914         }
8915         if (isFocusable()) {
8916             structure.setFocusable(true);
8917         }
8918         if (isFocused()) {
8919             structure.setFocused(true);
8920         }
8921         if (isAccessibilityFocused()) {
8922             structure.setAccessibilityFocused(true);
8923         }
8924         if (isSelected()) {
8925             structure.setSelected(true);
8926         }
8927         if (isActivated()) {
8928             structure.setActivated(true);
8929         }
8930         if (isLongClickable()) {
8931             structure.setLongClickable(true);
8932         }
8933         if (this instanceof Checkable) {
8934             structure.setCheckable(true);
8935             if (((Checkable)this).isChecked()) {
8936                 structure.setChecked(true);
8937             }
8938         }
8939         if (isOpaque()) {
8940             structure.setOpaque(true);
8941         }
8942         if (isContextClickable()) {
8943             structure.setContextClickable(true);
8944         }
8945         structure.setClassName(getAccessibilityClassName().toString());
8946         structure.setContentDescription(getContentDescription());
8947     }
8948 
8949     /**
8950      * Called when assist structure is being retrieved from a view as part of
8951      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
8952      * generate additional virtual structure under this view.  The default implementation
8953      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
8954      * view's virtual accessibility nodes, if any.  You can override this for a more
8955      * optimal implementation providing this data.
8956      */
8957     public void onProvideVirtualStructure(ViewStructure structure) {
8958         onProvideVirtualStructureCompat(structure, false);
8959     }
8960 
8961     /**
8962      * Fallback implementation to populate a ViewStructure from accessibility state.
8963      *
8964      * @param structure The structure to populate.
8965      * @param forAutofill Whether the structure is needed for autofill.
8966      */
8967     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
8968         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8969         if (provider != null) {
8970             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8971                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
8972             }
8973             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
8974             structure.setChildCount(1);
8975             final ViewStructure root = structure.newChild(0);
8976             populateVirtualStructure(root, provider, info, forAutofill);
8977             info.recycle();
8978         }
8979     }
8980 
8981     /**
8982      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
8983      * request.
8984      *
8985      * <p>This method should be used when the view manages a virtual structure under this view. For
8986      * example, a view that draws input fields using {@link #draw(Canvas)}.
8987      *
8988      * <p>When implementing this method, subclasses must follow the rules below:
8989      *
8990      * <ul>
8991      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
8992      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
8993      *       identifying the children in the virtual structure.
8994      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
8995      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
8996      *       autofill performance.
8997      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
8998      *       children.
8999      *   <li>Set the autofill properties of the child structure as defined by
9000      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
9001      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
9002      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
9003      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
9004      *       when the focused virtual child changed.
9005      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9006      *       whether a given virtual view is visible to the user in order to support triggering
9007      *       save when all views of interest go away.
9008      *   <li>Call
9009      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9010      *       when the value of a virtual child changed.
9011      *   <li>Call {@link
9012      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9013      *       when the visibility of a virtual child changed.
9014      *   <li>Call
9015      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9016      *       child is clicked.
9017      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9018      *       changed and the current context should be committed (for example, when the user tapped
9019      *       a {@code SUBMIT} button in an HTML page).
9020      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9021      *       changed and the current context should be canceled (for example, when the user tapped
9022      *       a {@code CANCEL} button in an HTML page).
9023      *   <li>Provide ways for users to manually request autofill by calling
9024      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9025      *   <li>The {@code left} and {@code top} values set in
9026      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9027      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9028      *       structure.
9029      * </ul>
9030      *
9031      * <p>Views with virtual children support the Autofill Framework mainly by:
9032      * <ul>
9033      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9034      *       autofilled.
9035      *   <li>Implementing the methods that autofill the virtual children.
9036      * </ul>
9037      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9038      * for the latter.
9039      *
9040      * @param structure fill in with virtual children data for autofill purposes.
9041      * @param flags optional flags.
9042      *
9043      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9044      */
9045     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9046         if (mContext.isAutofillCompatibilityEnabled()) {
9047             onProvideVirtualStructureCompat(structure, true);
9048         }
9049     }
9050 
9051     /**
9052      * Sets the listener to be {@link #performReceiveContent used} to handle insertion of
9053      * content into this view.
9054      *
9055      * <p>Depending on the type of view, this listener may be invoked for different scenarios. For
9056      * example, for an editable {@link android.widget.TextView}, this listener will be invoked for
9057      * the following scenarios:
9058      * <ol>
9059      *     <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
9060      *     insertion/selection menu)
9061      *     <li>Content insertion from the keyboard (from {@link InputConnection#commitContent})
9062      *     <li>Drag and drop (drop events from {@link #onDragEvent})
9063      *     <li>Autofill
9064      *     <li>Selection replacement via {@link Intent#ACTION_PROCESS_TEXT}
9065      * </ol>
9066      *
9067      * <p>When setting a listener, clients must also declare the accepted MIME types.
9068      * The listener will still be invoked even if the MIME type of the content is not one of the
9069      * declared MIME types (e.g. if the user pastes content whose type is not one of the declared
9070      * MIME types).
9071      * In that case, the listener may reject the content (defer to the default platform behavior)
9072      * or execute some other fallback logic (e.g. show an appropriate message to the user).
9073      * The declared MIME types serve as a hint to allow different features to optionally alter
9074      * their behavior. For example, a soft keyboard may optionally choose to hide its UI for
9075      * inserting GIFs for a particular input field if the MIME types set here for that field
9076      * don't include "image/gif" or "image/*".
9077      *
9078      * <p>Note: MIME type matching in the Android framework is case-sensitive, unlike formal RFC
9079      * MIME types. As a result, you should always write your MIME types with lowercase letters,
9080      * or use {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9081      * lowercase.
9082      *
9083      * @param mimeTypes The MIME types accepted by the given listener. These may use patterns
9084      *                  such as "image/*", but may not start with a wildcard. This argument must
9085      *                  not be null or empty if a non-null listener is passed in.
9086      * @param listener The listener to use. This can be null to reset to the default behavior.
9087      */
9088     public void setOnReceiveContentListener(
9089             @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
9090             @Nullable OnReceiveContentListener listener) {
9091         if (listener != null) {
9092             Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
9093                     "When the listener is set, MIME types must also be set");
9094         }
9095         if (mimeTypes != null) {
9096             Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
9097                     "A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
9098         }
9099         mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
9100         getListenerInfo().mOnReceiveContentListener = listener;
9101     }
9102 
9103     /**
9104      * Receives the given content. If no listener is set, invokes {@link #onReceiveContent}. If a
9105      * listener is {@link #setOnReceiveContentListener set}, invokes the listener instead; if the
9106      * listener returns a non-null result, invokes {@link #onReceiveContent} to handle it.
9107      *
9108      * @param payload The content to insert and related metadata.
9109      *
9110      * @return The portion of the passed-in content that was not accepted (may be all, some, or none
9111      * of the passed-in content).
9112      */
9113     @Nullable
performReceiveContent(@onNull ContentInfo payload)9114     public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
9115         final OnReceiveContentListener listener = (mListenerInfo == null) ? null
9116                 : getListenerInfo().mOnReceiveContentListener;
9117         if (listener != null) {
9118             final ContentInfo remaining = listener.onReceiveContent(this, payload);
9119             return (remaining == null) ? null : onReceiveContent(remaining);
9120         }
9121         return onReceiveContent(payload);
9122     }
9123 
9124     /**
9125      * Implements the default behavior for receiving content for this type of view. The default
9126      * view implementation is a no-op (returns the passed-in content without acting on it).
9127      *
9128      * <p>Widgets should override this method to define their default behavior for receiving
9129      * content. Apps should {@link #setOnReceiveContentListener set a listener} to provide
9130      * app-specific handling for receiving content.
9131      *
9132      * <p>See {@link #setOnReceiveContentListener} and {@link #performReceiveContent} for more info.
9133      *
9134      * @param payload The content to insert and related metadata.
9135      *
9136      * @return The portion of the passed-in content that was not handled (may be all, some, or none
9137      * of the passed-in content).
9138      */
9139     @Nullable
onReceiveContent(@onNull ContentInfo payload)9140     public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
9141         return payload;
9142     }
9143 
9144     /**
9145      * Returns the MIME types accepted by {@link #performReceiveContent} for this view, as
9146      * configured via {@link #setOnReceiveContentListener}. By default returns null.
9147      *
9148      * <p>Different features (e.g. pasting from the clipboard, inserting stickers from the soft
9149      * keyboard, etc) may optionally use this metadata to conditionally alter their behavior. For
9150      * example, a soft keyboard may choose to hide its UI for inserting GIFs for a particular
9151      * input field if the MIME types returned here for that field don't include "image/gif" or
9152      * "image/*".
9153      *
9154      * <p>Note: Comparisons of MIME types should be performed using utilities such as
9155      * {@link ClipDescription#compareMimeTypes} rather than simple string equality, in order to
9156      * correctly handle patterns such as "text/*", "image/*", etc. Note that MIME type matching
9157      * in the Android framework is case-sensitive, unlike formal RFC MIME types. As a result,
9158      * you should always write your MIME types with lowercase letters, or use
9159      * {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9160      * lowercase.
9161      *
9162      * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
9163      * include patterns such as "image/*").
9164      */
9165     @SuppressLint("NullableCollection")
9166     @Nullable
getReceiveContentMimeTypes()9167     public String[] getReceiveContentMimeTypes() {
9168         return mReceiveContentMimeTypes;
9169     }
9170 
9171     /**
9172      * Automatically fills the content of this view with the {@code value}.
9173      *
9174      * <p>Views support the Autofill Framework mainly by:
9175      * <ul>
9176      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9177      *   <li>Implementing the methods that autofill the view.
9178      * </ul>
9179      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
9180      * this method is responsible for latter.
9181      *
9182      * <p>This method does nothing by default, but when overridden it typically:
9183      * <ol>
9184      *   <li>Checks if the provided value matches the expected type (which is defined by
9185      *       {@link #getAutofillType()}).
9186      *   <li>Checks if the view is editable - if it isn't, it should return right away.
9187      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
9188      *   <li>Pass the actual value to the equivalent setter in the view.
9189      * </ol>
9190      *
9191      * <p>For example, a text-field view could implement the method this way:
9192      *
9193      * <pre class="prettyprint">
9194      * &#64;Override
9195      * public void autofill(AutofillValue value) {
9196      *   if (!value.isText() || !this.isEditable()) {
9197      *      return;
9198      *   }
9199      *   CharSequence text = value.getTextValue();
9200      *   if (text != null) {
9201      *     this.setText(text);
9202      *   }
9203      * }
9204      * </pre>
9205      *
9206      * <p>If the value is updated asynchronously, the next call to
9207      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
9208      * changed to the autofilled value. If not, the view will not be considered autofilled.
9209      *
9210      * <p><b>Note:</b> After this method is called, the value returned by
9211      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
9212      * view will not be highlighted as autofilled.
9213      *
9214      * @param value value to be autofilled.
9215      */
autofill(@uppressWarnings"unused") AutofillValue value)9216     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
9217     }
9218 
9219     /**
9220      * Automatically fills the content of the virtual children within this view.
9221      *
9222      * <p>Views with virtual children support the Autofill Framework mainly by:
9223      * <ul>
9224      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9225      *       autofilled.
9226      *   <li>Implementing the methods that autofill the virtual children.
9227      * </ul>
9228      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
9229      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
9230      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
9231      *
9232      * <p>If a child value is updated asynchronously, the next call to
9233      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
9234      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
9235      * considered autofilled.
9236      *
9237      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
9238      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
9239      * changes.
9240      *
9241      * @param values map of values to be autofilled, keyed by virtual child id.
9242      *
9243      * @attr ref android.R.styleable#Theme_autofilledHighlight
9244      */
autofill(@onNull @uppressWarnings"unused") SparseArray<AutofillValue> values)9245     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
9246         if (!mContext.isAutofillCompatibilityEnabled()) {
9247             return;
9248         }
9249         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9250         if (provider == null) {
9251             return;
9252         }
9253         final int valueCount = values.size();
9254         for (int i = 0; i < valueCount; i++) {
9255             final AutofillValue value = values.valueAt(i);
9256             if (value.isText()) {
9257                 final int virtualId = values.keyAt(i);
9258                 final CharSequence text = value.getTextValue();
9259                 final Bundle arguments = new Bundle();
9260                 arguments.putCharSequence(
9261                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
9262                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
9263             }
9264         }
9265     }
9266 
9267     /**
9268      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
9269      *
9270      * <p>The autofill id is created on demand, unless it is explicitly set by
9271      * {@link #setAutofillId(AutofillId)}.
9272      *
9273      * <p>See {@link #setAutofillId(AutofillId)} for more info.
9274      *
9275      * @return The View's autofill id.
9276      */
getAutofillId()9277     public final AutofillId getAutofillId() {
9278         if (mAutofillId == null) {
9279             // The autofill id needs to be unique, but its value doesn't matter,
9280             // so it's better to reuse the accessibility id to save space.
9281             mAutofillId = new AutofillId(getAutofillViewId());
9282         }
9283         return mAutofillId;
9284     }
9285 
9286     /**
9287      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
9288      *
9289      * <p>The autofill id is created on demand, and this method should only be called when a view is
9290      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
9291      * that method creates a snapshot of the view that is passed along to the autofill service.
9292      *
9293      * <p>This method is typically used when view subtrees are recycled to represent different
9294      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
9295      * out, and restored later when it's swapped back in. For example:
9296      *
9297      * <pre>
9298      * EditText reusableView = ...;
9299      * ViewGroup parentView = ...;
9300      * AutofillManager afm = ...;
9301      *
9302      * // Swap out the view and change its contents
9303      * AutofillId oldId = reusableView.getAutofillId();
9304      * CharSequence oldText = reusableView.getText();
9305      * parentView.removeView(reusableView);
9306      * AutofillId newId = afm.getNextAutofillId();
9307      * reusableView.setText("New I am");
9308      * reusableView.setAutofillId(newId);
9309      * parentView.addView(reusableView);
9310      *
9311      * // Later, swap the old content back in
9312      * parentView.removeView(reusableView);
9313      * reusableView.setAutofillId(oldId);
9314      * reusableView.setText(oldText);
9315      * parentView.addView(reusableView);
9316      * </pre>
9317      *
9318      * <p>NOTE: If this view is a descendant of an {@link android.widget.AdapterView}, the system
9319      * may reset its autofill id when this view is recycled. If the autofill ids need to be stable,
9320      * they should be set again in
9321      * {@link android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
9322      *
9323      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
9324      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
9325      * obtained through {@link #getAutofillId()}), or a new value obtained through
9326      * {@link AutofillManager#getNextAutofillId()}.
9327      *
9328      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
9329      * a window}.
9330      *
9331      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
9332      */
setAutofillId(@ullable AutofillId id)9333     public void setAutofillId(@Nullable AutofillId id) {
9334         // TODO(b/37566627): add unit / CTS test for all possible combinations below
9335         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9336             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
9337         }
9338         if (isAttachedToWindow()) {
9339             throw new IllegalStateException("Cannot set autofill id when view is attached");
9340         }
9341         if (id != null && !id.isNonVirtual()) {
9342             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
9343         }
9344         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
9345             // Ignore reset because it was never explicitly set before.
9346             return;
9347         }
9348         mAutofillId = id;
9349         if (id != null) {
9350             mAutofillViewId = id.getViewId();
9351             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9352         } else {
9353             mAutofillViewId = NO_ID;
9354             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9355         }
9356     }
9357 
9358     /**
9359      * Forces a reset of the autofill ids of the subtree rooted at this view. Like calling
9360      * {@link #setAutofillId(AutofillId) setAutofillId(null)} for each view, but works even if the
9361      * views are attached to a window.
9362      *
9363      * <p>This is useful if the views are being recycled, since an autofill id should uniquely
9364      * identify a particular piece of content.
9365      *
9366      * @hide
9367      */
resetSubtreeAutofillIds()9368     public void resetSubtreeAutofillIds() {
9369         if (mAutofillViewId == NO_ID) {
9370             return;
9371         }
9372         if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9373             Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9374         } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9375             Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9376         }
9377         mAutofillId = null;
9378         mAutofillViewId = NO_ID;
9379         mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9380     }
9381 
9382     /**
9383      * Describes the autofill type of this view, so an
9384      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
9385      * when autofilling the view.
9386      *
9387      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
9388      * support the Autofill Framework.
9389      *
9390      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
9391      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
9392      *
9393      * @see #onProvideAutofillStructure(ViewStructure, int)
9394      * @see #autofill(AutofillValue)
9395      */
getAutofillType()9396     public @AutofillType int getAutofillType() {
9397         return AUTOFILL_TYPE_NONE;
9398     }
9399 
9400     /**
9401      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
9402      * to autofill the view with the user's data.
9403      *
9404      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
9405      *
9406      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
9407      * {@code null} if no hints were set.
9408      *
9409      * @attr ref android.R.styleable#View_autofillHints
9410      */
9411     @ViewDebug.ExportedProperty()
9412     @InspectableProperty
getAutofillHints()9413     @Nullable public String[] getAutofillHints() {
9414         return mAutofillHints;
9415     }
9416 
9417     /**
9418      * @hide
9419      */
9420     @TestApi
isAutofilled()9421     public boolean isAutofilled() {
9422         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
9423     }
9424 
9425     /**
9426      * @hide
9427      */
hideAutofillHighlight()9428     public boolean hideAutofillHighlight() {
9429         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
9430     }
9431 
9432     /**
9433      * Gets the {@link View}'s current autofill value.
9434      *
9435      * <p>By default returns {@code null}, but subclasses should override it and return an
9436      * appropriate value to properly support the Autofill Framework.
9437      *
9438      * @see #onProvideAutofillStructure(ViewStructure, int)
9439      * @see #autofill(AutofillValue)
9440      */
9441     @Nullable
getAutofillValue()9442     public AutofillValue getAutofillValue() {
9443         return null;
9444     }
9445 
9446     /**
9447      * Gets the mode for determining whether this view is important for autofill.
9448      *
9449      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
9450      * info about this mode.
9451      *
9452      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
9453      * {@link #setImportantForAutofill(int)}.
9454      *
9455      * @attr ref android.R.styleable#View_importantForAutofill
9456      */
9457     @ViewDebug.ExportedProperty(mapping = {
9458             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
9459             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
9460             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
9461             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9462                 to = "yesExcludeDescendants"),
9463             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9464                 to = "noExcludeDescendants")})
9465     @InspectableProperty(enumMapping = {
9466             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
9467             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
9468             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
9469             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9470                     name = "yesExcludeDescendants"),
9471             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9472                     name = "noExcludeDescendants"),
9473     })
getImportantForAutofill()9474     public @AutofillImportance int getImportantForAutofill() {
9475         return (mPrivateFlags3
9476                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
9477     }
9478 
9479     /**
9480      * Sets the mode for determining whether this view is considered important for autofill.
9481      *
9482      * <p>The platform determines the importance for autofill automatically but you
9483      * can use this method to customize the behavior. For example:
9484      *
9485      * <ol>
9486      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
9487      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
9488      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
9489      *       view of an activity containing a spreadhseet editor), it should be
9490      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9491      *   <li>When the view content is relevant for autofill but its children aren't (for example,
9492      *       a credit card expiration date represented by a custom view that overrides the proper
9493      *       autofill methods and has 2 children representing the month and year), it should
9494      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
9495      * </ol>
9496      *
9497      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9498      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
9499      * children) will be always be considered not important; for example, when the user explicitly
9500      * makes an autofill request, all views are considered important. See
9501      * {@link #isImportantForAutofill()} for more details about how the View's importance for
9502      * autofill is used.
9503      *
9504      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
9505      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
9506      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9507      *
9508      * @attr ref android.R.styleable#View_importantForAutofill
9509      */
setImportantForAutofill(@utofillImportance int mode)9510     public void setImportantForAutofill(@AutofillImportance int mode) {
9511         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9512         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
9513                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9514     }
9515 
9516     /**
9517      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
9518      * associated with this view is considered important for autofill purposes.
9519      *
9520      * <p>Generally speaking, a view is important for autofill if:
9521      * <ol>
9522      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
9523      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
9524      *     determine how other views can be autofilled.
9525      * <ol>
9526      *
9527      * <p>For example, view containers should typically return {@code false} for performance reasons
9528      * (since the important info is provided by their children), but if its properties have relevant
9529      * information (for example, a resource id called {@code credentials}, it should return
9530      * {@code true}. On the other hand, views representing labels or editable fields should
9531      * typically return {@code true}, but in some cases they could return {@code false}
9532      * (for example, if they're part of a "Captcha" mechanism).
9533      *
9534      * <p>The value returned by this method depends on the value returned by
9535      * {@link #getImportantForAutofill()}:
9536      *
9537      * <ol>
9538      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
9539      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
9540      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9541      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
9542      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
9543      *       that can return {@code true} in some cases (like a container with a resource id),
9544      *       but {@code false} in most.
9545      *   <li>otherwise, it returns {@code false}.
9546      * </ol>
9547      *
9548      * <p>When a view is considered important for autofill:
9549      * <ul>
9550      *   <li>The view might automatically trigger an autofill request when focused on.
9551      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
9552      *       request.
9553      * </ul>
9554      *
9555      * <p>On the other hand, when a view is considered not important for autofill:
9556      * <ul>
9557      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
9558      *       request through {@link AutofillManager#requestAutofill(View)}.
9559      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
9560      *       autofill request, unless the request has the
9561      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9562      * </ul>
9563      *
9564      * @return whether the view is considered important for autofill.
9565      *
9566      * @see #setImportantForAutofill(int)
9567      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9568      * @see #IMPORTANT_FOR_AUTOFILL_YES
9569      * @see #IMPORTANT_FOR_AUTOFILL_NO
9570      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9571      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9572      * @see AutofillManager#requestAutofill(View)
9573      */
isImportantForAutofill()9574     public final boolean isImportantForAutofill() {
9575         // Check parent mode to ensure we're not hidden.
9576         ViewParent parent = mParent;
9577         while (parent instanceof View) {
9578             final int parentImportance = ((View) parent).getImportantForAutofill();
9579             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9580                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9581                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9582                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9583                             + "because parent " + parent + "'s importance is " + parentImportance);
9584                 }
9585                 return false;
9586             }
9587             parent = parent.getParent();
9588         }
9589 
9590         final int importance = getImportantForAutofill();
9591 
9592         // First, check the explicit states.
9593         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9594                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9595             return true;
9596         }
9597         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9598                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9599             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9600                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9601                         + "because its importance is " + importance);
9602             }
9603             return false;
9604         }
9605 
9606         // Then use some heuristics to handle AUTO.
9607         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9608             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9609                     + this);
9610             return false;
9611         }
9612 
9613         // Always include views that have an explicit resource id.
9614         final int id = mID;
9615         if (id != NO_ID && !isViewIdGenerated(id)) {
9616             final Resources res = getResources();
9617             String entry = null;
9618             String pkg = null;
9619             try {
9620                 entry = res.getResourceEntryName(id);
9621                 pkg = res.getResourcePackageName(id);
9622             } catch (Resources.NotFoundException e) {
9623                 // ignore
9624             }
9625             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9626                 return true;
9627             }
9628         }
9629 
9630         // If the app developer explicitly set hints for it, it's important.
9631         if (getAutofillHints() != null) {
9632             return true;
9633         }
9634 
9635         // Otherwise, assume it's not important...
9636         return false;
9637     }
9638 
9639     /**
9640      * Gets the mode for determining whether this view is important for content capture.
9641      *
9642      * <p>See {@link #setImportantForContentCapture(int)} and
9643      * {@link #isImportantForContentCapture()} for more info about this mode.
9644      *
9645      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
9646      * {@link #setImportantForContentCapture(int)}.
9647      *
9648      * @attr ref android.R.styleable#View_importantForContentCapture
9649      */
9650     @ViewDebug.ExportedProperty(mapping = {
9651             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
9652             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
9653             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
9654             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9655                 to = "yesExcludeDescendants"),
9656             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9657                 to = "noExcludeDescendants")})
9658     @InspectableProperty(enumMapping = {
9659             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
9660             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
9661             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
9662             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9663                     name = "yesExcludeDescendants"),
9664             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9665                     name = "noExcludeDescendants"),
9666     })
getImportantForContentCapture()9667     public @ContentCaptureImportance int getImportantForContentCapture() {
9668         // NOTE: the important for content capture values were the first flags added and are set in
9669         // the rightmost position, so we don't need to shift them
9670         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9671     }
9672 
9673     /**
9674      * Sets the mode for determining whether this view is considered important for content capture.
9675      *
9676      * <p>The platform determines the importance for autofill automatically but you
9677      * can use this method to customize the behavior. Typically, a view that provides text should
9678      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
9679      *
9680      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
9681      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
9682      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
9683      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
9684      *
9685      * @attr ref android.R.styleable#View_importantForContentCapture
9686      */
setImportantForContentCapture(@ontentCaptureImportance int mode)9687     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
9688         // Reset first
9689         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9690         // Then set again
9691         // NOTE: the important for content capture values were the first flags added and are set in
9692         // the rightmost position, so we don't need to shift them
9693         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
9694     }
9695 
9696     /**
9697      * Hints the Android System whether this view is considered important for content capture, based
9698      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
9699      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
9700      *
9701      * <p>See {@link ContentCaptureManager} for more info about content capture.
9702      *
9703      * @return whether the view is considered important for content capture.
9704      *
9705      * @see #setImportantForContentCapture(int)
9706      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
9707      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
9708      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
9709      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9710      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9711      */
isImportantForContentCapture()9712     public final boolean isImportantForContentCapture() {
9713         boolean isImportant;
9714         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
9715             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
9716             return isImportant;
9717         }
9718 
9719         isImportant = calculateIsImportantForContentCapture();
9720 
9721         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9722         if (isImportant) {
9723             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9724         }
9725         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
9726         return isImportant;
9727     }
9728 
9729     /**
9730      * Calculates whether the flag is important for content capture so it can be used by
9731      * {@link #isImportantForContentCapture()} while the tree is traversed.
9732      */
calculateIsImportantForContentCapture()9733     private boolean calculateIsImportantForContentCapture() {
9734         // Check parent mode to ensure we're important
9735         ViewParent parent = mParent;
9736         while (parent instanceof View) {
9737             final int parentImportance = ((View) parent).getImportantForContentCapture();
9738             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9739                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
9740                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9741                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
9742                             + "content capture because parent " + parent + "'s importance is "
9743                             + parentImportance);
9744                 }
9745                 return false;
9746             }
9747             parent = parent.getParent();
9748         }
9749 
9750         final int importance = getImportantForContentCapture();
9751 
9752         // First, check the explicit states.
9753         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9754                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
9755             return true;
9756         }
9757         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9758                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
9759             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9760                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
9761                         + "capture because its importance is " + importance);
9762             }
9763             return false;
9764         }
9765 
9766         // Then use some heuristics to handle AUTO.
9767         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
9768             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
9769                     + " on view " + this);
9770             return false;
9771         }
9772 
9773         // View group is important if at least one children also is
9774         if (this instanceof ViewGroup) {
9775             final ViewGroup group = (ViewGroup) this;
9776             for (int i = 0; i < group.getChildCount(); i++) {
9777                 final View child = group.getChildAt(i);
9778                 if (child.isImportantForContentCapture()) {
9779                     return true;
9780                 }
9781             }
9782         }
9783 
9784         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
9785         if (getAutofillHints() != null) {
9786             return true;
9787         }
9788 
9789         // Otherwise, assume it's not important...
9790         return false;
9791     }
9792 
9793     /**
9794      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
9795      * added, based on whether it's laid out and visible, and without knowing if the parent removed
9796      * it from the view hierarchy.
9797      *
9798      * <p>This method is called from many places (visibility changed, view laid out, view attached
9799      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
9800      * described below:
9801      *
9802      * <ol>
9803      *   <li>It should only be called when content capture is enabled for the view.
9804      *   <li>It must call viewAppeared() before viewDisappeared()
9805      *   <li>viewAppearead() can only be called when the view is visible and laidout
9806      *   <li>It should not call the same event twice.
9807      * </ol>
9808      */
notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared)9809     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
9810         AttachInfo ai = mAttachInfo;
9811         // Skip it while the view is being laid out for the first time
9812         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
9813 
9814         // First check if context has client, so it saves a service lookup when it doesn't
9815         if (mContext.getContentCaptureOptions() == null) return;
9816 
9817         if (appeared) {
9818             // The appeared event stops sending to AiAi.
9819             // 1. The view is hidden.
9820             // 2. The same event was sent.
9821             // 3. The view is not laid out, and it will be laid out in the future.
9822             //    Some recycled views cached its layout and a relayout is unnecessary. In this case,
9823             // system still needs to notify content capture the view appeared. When a view is
9824             // recycled, it will set the flag PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED.
9825             final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
9826                     && getVisibility() == VISIBLE
9827                     && !isLayoutRequested();
9828             if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
9829                     || !(isLaidOut() || isRecycledWithoutRelayout)) {
9830                 if (DEBUG_CONTENT_CAPTURE) {
9831                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
9832                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9833                             + ", visible=" + (getVisibility() == VISIBLE)
9834                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
9835                             + ", alreadyNotifiedDisappeared="
9836                             + getNotifiedContentCaptureDisappeared());
9837                 }
9838                 return;
9839             }
9840         } else {
9841             if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
9842                 if (DEBUG_CONTENT_CAPTURE) {
9843                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
9844                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9845                             + ", visible=" + (getVisibility() == VISIBLE)
9846                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
9847                             + ", alreadyNotifiedDisappeared="
9848                             + getNotifiedContentCaptureDisappeared());
9849                 }
9850                 return;
9851             }
9852         }
9853 
9854         ContentCaptureSession session = getContentCaptureSession();
9855         if (session == null) return;
9856 
9857         // ... and finally at the view level
9858         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
9859         if (!isImportantForContentCapture()) return;
9860 
9861         if (appeared) {
9862             setNotifiedContentCaptureAppeared();
9863 
9864             if (ai != null) {
9865                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9866             } else {
9867                 if (DEBUG_CONTENT_CAPTURE) {
9868                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
9869                 }
9870             }
9871         } else {
9872             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9873             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9874 
9875             if (ai != null) {
9876                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9877             } else {
9878                 if (DEBUG_CONTENT_CAPTURE) {
9879                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
9880                 }
9881             }
9882         }
9883     }
9884 
setNotifiedContentCaptureAppeared()9885     private void setNotifiedContentCaptureAppeared() {
9886         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9887         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9888     }
9889 
9890     /** @hide */
getNotifiedContentCaptureAppeared()9891     protected boolean getNotifiedContentCaptureAppeared() {
9892         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
9893     }
9894 
9895 
getNotifiedContentCaptureDisappeared()9896     private boolean getNotifiedContentCaptureDisappeared() {
9897         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
9898     }
9899 
9900     /**
9901      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
9902      *
9903      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
9904      * the content capture events associated with this view or its view hierarchy (if it's a
9905      * {@link ViewGroup}).
9906      *
9907      * <p>For example, if your activity is associated with a web domain, first you would need to
9908      * set the context for the main DOM:
9909      *
9910      * <pre>
9911      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
9912      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
9913      * </pre>
9914      *
9915      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
9916      *
9917      * <pre>
9918      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
9919      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
9920      *   iframeView.setContentCaptureSession(iframeSession);
9921      * </pre>
9922      *
9923      * @param contentCaptureSession a session created by
9924      * {@link ContentCaptureSession#createContentCaptureSession(
9925      *        android.view.contentcapture.ContentCaptureContext)}.
9926      */
setContentCaptureSession(@ullable ContentCaptureSession contentCaptureSession)9927     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
9928         mContentCaptureSession = contentCaptureSession;
9929     }
9930 
9931     /**
9932      * Gets the session used to notify content capture events.
9933      *
9934      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
9935      * inherited by ancestors, default session or {@code null} if content capture is disabled for
9936      * this view.
9937      */
9938     @Nullable
getContentCaptureSession()9939     public final ContentCaptureSession getContentCaptureSession() {
9940         if (mContentCaptureSessionCached) {
9941             return mContentCaptureSession;
9942         }
9943 
9944         mContentCaptureSession = getAndCacheContentCaptureSession();
9945         mContentCaptureSessionCached = true;
9946         return mContentCaptureSession;
9947     }
9948 
9949     @Nullable
getAndCacheContentCaptureSession()9950     private ContentCaptureSession getAndCacheContentCaptureSession() {
9951         // First try the session explicitly set by setContentCaptureSession()
9952         if (mContentCaptureSession != null) {
9953             return mContentCaptureSession;
9954         }
9955 
9956         // Then the session explicitly set in an ancestor
9957         ContentCaptureSession session = null;
9958         if (mParent instanceof View) {
9959             session = ((View) mParent).getContentCaptureSession();
9960         }
9961 
9962         // Finally, if no session was explicitly set, use the context's default session.
9963         if (session == null) {
9964             final ContentCaptureManager ccm = mContext
9965                     .getSystemService(ContentCaptureManager.class);
9966             return ccm == null ? null : ccm.getMainContentCaptureSession();
9967         }
9968         return session;
9969     }
9970 
9971     @Nullable
getAutofillManager()9972     private AutofillManager getAutofillManager() {
9973         return mContext.getSystemService(AutofillManager.class);
9974     }
9975 
isAutofillable()9976     private boolean isAutofillable() {
9977         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
9978 
9979         if (!isImportantForAutofill()) {
9980             // View is not important for "regular" autofill, so we must check if Augmented Autofill
9981             // is enabled for the activity
9982             final AutofillOptions options = mContext.getAutofillOptions();
9983             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
9984                 return false;
9985             }
9986             final AutofillManager afm = getAutofillManager();
9987             if (afm == null) return false;
9988             afm.notifyViewEnteredForAugmentedAutofill(this);
9989         }
9990 
9991         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
9992     }
9993 
9994     /** @hide */
canNotifyAutofillEnterExitEvent()9995     public boolean canNotifyAutofillEnterExitEvent() {
9996         return isAutofillable() && isAttachedToWindow();
9997     }
9998 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill)9999     private void populateVirtualStructure(ViewStructure structure,
10000             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
10001             boolean forAutofill) {
10002         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
10003                 null, null, info.getViewIdResourceName());
10004         Rect rect = structure.getTempRect();
10005         info.getBoundsInParent(rect);
10006         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
10007         structure.setVisibility(VISIBLE);
10008         structure.setEnabled(info.isEnabled());
10009         if (info.isClickable()) {
10010             structure.setClickable(true);
10011         }
10012         if (info.isFocusable()) {
10013             structure.setFocusable(true);
10014         }
10015         if (info.isFocused()) {
10016             structure.setFocused(true);
10017         }
10018         if (info.isAccessibilityFocused()) {
10019             structure.setAccessibilityFocused(true);
10020         }
10021         if (info.isSelected()) {
10022             structure.setSelected(true);
10023         }
10024         if (info.isLongClickable()) {
10025             structure.setLongClickable(true);
10026         }
10027         if (info.isCheckable()) {
10028             structure.setCheckable(true);
10029             if (info.isChecked()) {
10030                 structure.setChecked(true);
10031             }
10032         }
10033         if (info.isContextClickable()) {
10034             structure.setContextClickable(true);
10035         }
10036         if (forAutofill) {
10037             structure.setAutofillId(new AutofillId(getAutofillId(),
10038                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
10039         }
10040         CharSequence cname = info.getClassName();
10041         structure.setClassName(cname != null ? cname.toString() : null);
10042         structure.setContentDescription(info.getContentDescription());
10043         if (forAutofill) {
10044             final int maxTextLength = info.getMaxTextLength();
10045             if (maxTextLength != -1) {
10046                 structure.setMaxTextLength(maxTextLength);
10047             }
10048             structure.setHint(info.getHintText());
10049         }
10050         CharSequence text = info.getText();
10051         boolean hasText = text != null || info.getError() != null;
10052         if (hasText) {
10053             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
10054         }
10055         if (forAutofill) {
10056             if (info.isEditable()) {
10057                 structure.setDataIsSensitive(true);
10058                 if (hasText) {
10059                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
10060                     structure.setAutofillValue(AutofillValue.forText(text));
10061                 }
10062                 int inputType = info.getInputType();
10063                 if (inputType == 0 && info.isPassword()) {
10064                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
10065                 }
10066                 structure.setInputType(inputType);
10067             } else {
10068                 structure.setDataIsSensitive(false);
10069             }
10070         }
10071         final int NCHILDREN = info.getChildCount();
10072         if (NCHILDREN > 0) {
10073             structure.setChildCount(NCHILDREN);
10074             for (int i=0; i<NCHILDREN; i++) {
10075                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
10076                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
10077                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
10078                     continue;
10079                 }
10080                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
10081                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
10082                 if (cinfo != null) {
10083                     ViewStructure child = structure.newChild(i);
10084                     populateVirtualStructure(child, provider, cinfo, forAutofill);
10085                     cinfo.recycle();
10086                 }
10087             }
10088         }
10089     }
10090 
10091     /**
10092      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
10093      * implementation calls {@link #onProvideStructure} and
10094      * {@link #onProvideVirtualStructure}.
10095      */
dispatchProvideStructure(ViewStructure structure)10096     public void dispatchProvideStructure(ViewStructure structure) {
10097         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
10098     }
10099 
10100     /**
10101      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
10102      * when an Assist structure is being created as part of an autofill request.
10103      *
10104      * <p>The default implementation does the following:
10105      * <ul>
10106      *   <li>Sets the {@link AutofillId} in the structure.
10107      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
10108      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
10109      * </ul>
10110      *
10111      * <p>Typically, this method should only be overridden by subclasses that provide a view
10112      * hierarchy (such as {@link ViewGroup}) - other classes should override
10113      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
10114      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
10115      *
10116      * <p>When overridden, it must:
10117      *
10118      * <ul>
10119      *   <li>Either call
10120      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
10121      *       set the {@link AutofillId} in the structure (for example, by calling
10122      *       {@code structure.setAutofillId(getAutofillId())}).
10123      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
10124      *       set, all views in the structure should be considered important for autofill,
10125      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
10126      *       respect this flag to provide a better user experience - this flag is typically used
10127      *       when an user explicitly requested autofill. If the flag is not set,
10128      *       then only views marked as important for autofill should be included in the
10129      *       structure - skipping non-important views optimizes the overall autofill performance.
10130      * </ul>
10131      *
10132      * @param structure fill in with structured view data for autofill purposes.
10133      * @param flags optional flags.
10134      *
10135      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
10136      */
dispatchProvideAutofillStructure(@onNull ViewStructure structure, @AutofillFlags int flags)10137     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
10138             @AutofillFlags int flags) {
10139         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
10140     }
10141 
dispatchProvideStructure(@onNull ViewStructure structure, @ViewStructureType int viewFor, @AutofillFlags int flags)10142     private void dispatchProvideStructure(@NonNull ViewStructure structure,
10143             @ViewStructureType int viewFor, @AutofillFlags int flags) {
10144         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
10145             structure.setAutofillId(getAutofillId());
10146             onProvideAutofillStructure(structure, flags);
10147             onProvideAutofillVirtualStructure(structure, flags);
10148         } else if (!isAssistBlocked()) {
10149             onProvideStructure(structure);
10150             onProvideVirtualStructure(structure);
10151         } else {
10152             structure.setClassName(getAccessibilityClassName().toString());
10153             structure.setAssistBlocked(true);
10154         }
10155     }
10156 
10157     /**
10158      * Dispatches the initial content capture events for a view structure.
10159      *
10160      * @hide
10161      */
dispatchInitialProvideContentCaptureStructure()10162     public void dispatchInitialProvideContentCaptureStructure() {
10163         AttachInfo ai = mAttachInfo;
10164         if (ai == null) {
10165             Log.w(CONTENT_CAPTURE_LOG_TAG,
10166                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
10167             return;
10168         }
10169         ContentCaptureManager ccm = ai.mContentCaptureManager;
10170         if (ccm == null) {
10171             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
10172                     + "no ContentCaptureManager for " + this);
10173             return;
10174         }
10175 
10176         // We must set it before checkign if the view itself is important, because it might
10177         // initially not be (for example, if it's empty), although that might change later (for
10178         // example, if important views are added)
10179         ai.mReadyForContentCaptureUpdates = true;
10180 
10181         if (!isImportantForContentCapture()) {
10182             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10183                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10184                         "dispatchProvideContentCaptureStructure(): decorView is not important");
10185             }
10186             return;
10187         }
10188 
10189         ai.mContentCaptureManager = ccm;
10190 
10191         ContentCaptureSession session = getContentCaptureSession();
10192         if (session == null) {
10193             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10194                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10195                         "dispatchProvideContentCaptureStructure(): no session for " + this);
10196             }
10197             return;
10198         }
10199 
10200         session.internalNotifyViewTreeEvent(/* started= */ true);
10201         try {
10202             dispatchProvideContentCaptureStructure();
10203         } finally {
10204             session.internalNotifyViewTreeEvent(/* started= */ false);
10205         }
10206     }
10207 
10208     /** @hide */
dispatchProvideContentCaptureStructure()10209     void dispatchProvideContentCaptureStructure() {
10210         ContentCaptureSession session = getContentCaptureSession();
10211         if (session != null) {
10212             ViewStructure structure = session.newViewStructure(this);
10213             onProvideContentCaptureStructure(structure, /* flags= */ 0);
10214             setNotifiedContentCaptureAppeared();
10215             session.notifyViewAppeared(structure);
10216         }
10217     }
10218 
10219     /**
10220      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
10221      *
10222      * Note: Called from the default {@link AccessibilityDelegate}.
10223      *
10224      * @hide
10225      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)10226     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
10227         if (mAttachInfo == null) {
10228             return;
10229         }
10230 
10231         Rect bounds = mAttachInfo.mTmpInvalRect;
10232 
10233         getDrawingRect(bounds);
10234         info.setBoundsInParent(bounds);
10235 
10236         getBoundsOnScreen(bounds, true);
10237         info.setBoundsInScreen(bounds);
10238 
10239         ViewParent parent = getParentForAccessibility();
10240         if (parent instanceof View) {
10241             info.setParent((View) parent);
10242         }
10243 
10244         if (mID != View.NO_ID) {
10245             View rootView = getRootView();
10246             if (rootView == null) {
10247                 rootView = this;
10248             }
10249 
10250             View label = rootView.findLabelForView(this, mID);
10251             if (label != null) {
10252                 info.setLabeledBy(label);
10253             }
10254 
10255             if ((mAttachInfo.mAccessibilityFetchFlags
10256                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
10257                     && Resources.resourceHasPackage(mID)) {
10258                 try {
10259                     String viewId = getResources().getResourceName(mID);
10260                     info.setViewIdResourceName(viewId);
10261                 } catch (Resources.NotFoundException nfe) {
10262                     /* ignore */
10263                 }
10264             }
10265         }
10266 
10267         if (mLabelForId != View.NO_ID) {
10268             View rootView = getRootView();
10269             if (rootView == null) {
10270                 rootView = this;
10271             }
10272             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
10273             if (labeled != null) {
10274                 info.setLabelFor(labeled);
10275             }
10276         }
10277 
10278         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
10279             View rootView = getRootView();
10280             if (rootView == null) {
10281                 rootView = this;
10282             }
10283             View next = rootView.findViewInsideOutShouldExist(this,
10284                     mAccessibilityTraversalBeforeId);
10285             if (next != null && next.includeForAccessibility()) {
10286                 info.setTraversalBefore(next);
10287             }
10288         }
10289 
10290         if (mAccessibilityTraversalAfterId != View.NO_ID) {
10291             View rootView = getRootView();
10292             if (rootView == null) {
10293                 rootView = this;
10294             }
10295             View next = rootView.findViewInsideOutShouldExist(this,
10296                     mAccessibilityTraversalAfterId);
10297             if (next != null && next.includeForAccessibility()) {
10298                 info.setTraversalAfter(next);
10299             }
10300         }
10301 
10302         info.setVisibleToUser(isVisibleToUser());
10303 
10304         info.setImportantForAccessibility(isImportantForAccessibility());
10305         info.setPackageName(mContext.getPackageName());
10306         info.setClassName(getAccessibilityClassName());
10307         info.setStateDescription(getStateDescription());
10308         info.setContentDescription(getContentDescription());
10309 
10310         info.setEnabled(isEnabled());
10311         info.setClickable(isClickable());
10312         info.setFocusable(isFocusable());
10313         info.setScreenReaderFocusable(isScreenReaderFocusable());
10314         info.setFocused(isFocused());
10315         info.setAccessibilityFocused(isAccessibilityFocused());
10316         info.setSelected(isSelected());
10317         info.setLongClickable(isLongClickable());
10318         info.setContextClickable(isContextClickable());
10319         info.setLiveRegion(getAccessibilityLiveRegion());
10320         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
10321             info.setTooltipText(mTooltipInfo.mTooltipText);
10322             info.addAction((mTooltipInfo.mTooltipPopup == null)
10323                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
10324                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
10325         }
10326 
10327         // TODO: These make sense only if we are in an AdapterView but all
10328         // views can be selected. Maybe from accessibility perspective
10329         // we should report as selectable view in an AdapterView.
10330         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
10331         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
10332 
10333         if (isFocusable()) {
10334             if (isFocused()) {
10335                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
10336             } else {
10337                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
10338             }
10339         }
10340 
10341         if (!isAccessibilityFocused()) {
10342             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
10343         } else {
10344             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
10345         }
10346 
10347         if (isClickable() && isEnabled()) {
10348             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
10349         }
10350 
10351         if (isLongClickable() && isEnabled()) {
10352             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
10353         }
10354 
10355         if (isContextClickable() && isEnabled()) {
10356             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
10357         }
10358 
10359         CharSequence text = getIterableTextForAccessibility();
10360         if (text != null && text.length() > 0) {
10361             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
10362 
10363             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
10364             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
10365             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
10366             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
10367                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
10368                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
10369         }
10370 
10371         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
10372         populateAccessibilityNodeInfoDrawingOrderInParent(info);
10373         info.setPaneTitle(mAccessibilityPaneTitle);
10374         info.setHeading(isAccessibilityHeading());
10375 
10376         if (mTouchDelegate != null) {
10377             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
10378         }
10379     }
10380 
10381     /**
10382      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
10383      * additional data.
10384      * <p>
10385      * This method only needs overloading if the node is marked as having extra data available.
10386      * </p>
10387      *
10388      * @param info The info to which to add the extra data. Never {@code null}.
10389      * @param extraDataKey A key specifying the type of extra data to add to the info. The
10390      *                     extra data should be added to the {@link Bundle} returned by
10391      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
10392      *                     {@code null}.
10393      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
10394      *                  {@code null} if the service provided no arguments.
10395      *
10396      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
10397      */
addExtraDataToAccessibilityNodeInfo( @onNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)10398     public void addExtraDataToAccessibilityNodeInfo(
10399             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
10400             @Nullable Bundle arguments) {
10401     }
10402 
10403     /**
10404      * Determine the order in which this view will be drawn relative to its siblings for a11y
10405      *
10406      * @param info The info whose drawing order should be populated
10407      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)10408     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
10409         /*
10410          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
10411          * drawing order may not be well-defined, and some Views with custom drawing order may
10412          * not be initialized sufficiently to respond properly getChildDrawingOrder.
10413          */
10414         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
10415             info.setDrawingOrder(0);
10416             return;
10417         }
10418         int drawingOrderInParent = 1;
10419         // Iterate up the hierarchy if parents are not important for a11y
10420         View viewAtDrawingLevel = this;
10421         final ViewParent parent = getParentForAccessibility();
10422         while (viewAtDrawingLevel != parent) {
10423             final ViewParent currentParent = viewAtDrawingLevel.getParent();
10424             if (!(currentParent instanceof ViewGroup)) {
10425                 // Should only happen for the Decor
10426                 drawingOrderInParent = 0;
10427                 break;
10428             } else {
10429                 final ViewGroup parentGroup = (ViewGroup) currentParent;
10430                 final int childCount = parentGroup.getChildCount();
10431                 if (childCount > 1) {
10432                     List<View> preorderedList = parentGroup.buildOrderedChildList();
10433                     if (preorderedList != null) {
10434                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
10435                         for (int i = 0; i < childDrawIndex; i++) {
10436                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
10437                         }
10438                         preorderedList.clear();
10439                     } else {
10440                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
10441                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
10442                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
10443                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
10444                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
10445                         if (childDrawIndex != 0) {
10446                             for (int i = 0; i < numChildrenToIterate; i++) {
10447                                 final int otherDrawIndex = (customOrder ?
10448                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
10449                                 if (otherDrawIndex < childDrawIndex) {
10450                                     drawingOrderInParent +=
10451                                             numViewsForAccessibility(parentGroup.getChildAt(i));
10452                                 }
10453                             }
10454                         }
10455                     }
10456                 }
10457             }
10458             viewAtDrawingLevel = (View) currentParent;
10459         }
10460         info.setDrawingOrder(drawingOrderInParent);
10461     }
10462 
numViewsForAccessibility(View view)10463     private static int numViewsForAccessibility(View view) {
10464         if (view != null) {
10465             if (view.includeForAccessibility()) {
10466                 return 1;
10467             } else if (view instanceof ViewGroup) {
10468                 return ((ViewGroup) view).getNumChildrenForAccessibility();
10469             }
10470         }
10471         return 0;
10472     }
10473 
findLabelForView(View view, int labeledId)10474     private View findLabelForView(View view, int labeledId) {
10475         if (mMatchLabelForPredicate == null) {
10476             mMatchLabelForPredicate = new MatchLabelForPredicate();
10477         }
10478         mMatchLabelForPredicate.mLabeledId = labeledId;
10479         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
10480     }
10481 
10482     /**
10483      * Computes whether this virtual autofill view is visible to the user.
10484      *
10485      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
10486      * view must override it.
10487      *
10488      * @return Whether the view is visible on the screen.
10489      */
isVisibleToUserForAutofill(int virtualId)10490     public boolean isVisibleToUserForAutofill(int virtualId) {
10491         if (mContext.isAutofillCompatibilityEnabled()) {
10492             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10493             if (provider != null) {
10494                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
10495                 if (node != null) {
10496                     return node.isVisibleToUser();
10497                 }
10498                 // if node is null, assume it's not visible anymore
10499             } else {
10500                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
10501             }
10502             return false;
10503         }
10504         return true;
10505     }
10506 
10507     /**
10508      * Computes whether this view is visible to the user. Such a view is
10509      * attached, visible, all its predecessors are visible, it is not clipped
10510      * entirely by its predecessors, and has an alpha greater than zero.
10511      *
10512      * @return Whether the view is visible on the screen.
10513      *
10514      * @hide
10515      */
10516     @UnsupportedAppUsage
isVisibleToUser()10517     public boolean isVisibleToUser() {
10518         return isVisibleToUser(null);
10519     }
10520 
10521     /**
10522      * Computes whether the given portion of this view is visible to the user.
10523      * Such a view is attached, visible, all its predecessors are visible,
10524      * has an alpha greater than zero, and the specified portion is not
10525      * clipped entirely by its predecessors.
10526      *
10527      * @param boundInView the portion of the view to test; coordinates should be relative; may be
10528      *                    <code>null</code>, and the entire view will be tested in this case.
10529      *                    When <code>true</code> is returned by the function, the actual visible
10530      *                    region will be stored in this parameter; that is, if boundInView is fully
10531      *                    contained within the view, no modification will be made, otherwise regions
10532      *                    outside of the visible area of the view will be clipped.
10533      *
10534      * @return Whether the specified portion of the view is visible on the screen.
10535      *
10536      * @hide
10537      */
10538     @UnsupportedAppUsage(trackingBug = 171933273)
isVisibleToUser(Rect boundInView)10539     protected boolean isVisibleToUser(Rect boundInView) {
10540         if (mAttachInfo != null) {
10541             // Attached to invisible window means this view is not visible.
10542             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
10543                 return false;
10544             }
10545             // An invisible predecessor or one with alpha zero means
10546             // that this view is not visible to the user.
10547             Object current = this;
10548             while (current instanceof View) {
10549                 View view = (View) current;
10550                 // We have attach info so this view is attached and there is no
10551                 // need to check whether we reach to ViewRootImpl on the way up.
10552                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
10553                         view.getVisibility() != VISIBLE) {
10554                     return false;
10555                 }
10556                 current = view.mParent;
10557             }
10558             // Check if the view is entirely covered by its predecessors.
10559             Rect visibleRect = mAttachInfo.mTmpInvalRect;
10560             Point offset = mAttachInfo.mPoint;
10561             if (!getGlobalVisibleRect(visibleRect, offset)) {
10562                 return false;
10563             }
10564             // Check if the visible portion intersects the rectangle of interest.
10565             if (boundInView != null) {
10566                 visibleRect.offset(-offset.x, -offset.y);
10567                 return boundInView.intersect(visibleRect);
10568             }
10569             return true;
10570         }
10571         return false;
10572     }
10573 
10574     /**
10575      * Returns the delegate for implementing accessibility support via
10576      * composition. For more details see {@link AccessibilityDelegate}.
10577      *
10578      * @return The delegate, or null if none set.
10579      */
getAccessibilityDelegate()10580     public AccessibilityDelegate getAccessibilityDelegate() {
10581         return mAccessibilityDelegate;
10582     }
10583 
10584     /**
10585      * Sets a delegate for implementing accessibility support via composition
10586      * (as opposed to inheritance). For more details, see
10587      * {@link AccessibilityDelegate}.
10588      * <p>
10589      * <strong>Note:</strong> On platform versions prior to
10590      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
10591      * views in the {@code android.widget.*} package are called <i>before</i>
10592      * host methods. This prevents certain properties such as class name from
10593      * being modified by overriding
10594      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
10595      * as any changes will be overwritten by the host class.
10596      * <p>
10597      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
10598      * methods are called <i>after</i> host methods, which all properties to be
10599      * modified without being overwritten by the host class.
10600      *
10601      * @param delegate the object to which accessibility method calls should be
10602      *                 delegated
10603      * @see AccessibilityDelegate
10604      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)10605     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
10606         mAccessibilityDelegate = delegate;
10607     }
10608 
10609     /**
10610      * Gets the provider for managing a virtual view hierarchy rooted at this View
10611      * and reported to {@link android.accessibilityservice.AccessibilityService}s
10612      * that explore the window content.
10613      * <p>
10614      * If this method returns an instance, this instance is responsible for managing
10615      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
10616      * View including the one representing the View itself. Similarly the returned
10617      * instance is responsible for performing accessibility actions on any virtual
10618      * view or the root view itself.
10619      * </p>
10620      * <p>
10621      * If an {@link AccessibilityDelegate} has been specified via calling
10622      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10623      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
10624      * is responsible for handling this call.
10625      * </p>
10626      *
10627      * @return The provider.
10628      *
10629      * @see AccessibilityNodeProvider
10630      */
getAccessibilityNodeProvider()10631     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
10632         if (mAccessibilityDelegate != null) {
10633             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
10634         } else {
10635             return null;
10636         }
10637     }
10638 
10639     /**
10640      * Gets the unique identifier of this view on the screen for accessibility purposes.
10641      *
10642      * @return The view accessibility id.
10643      *
10644      * @hide
10645      */
10646     @UnsupportedAppUsage
getAccessibilityViewId()10647     public int getAccessibilityViewId() {
10648         if (mAccessibilityViewId == NO_ID) {
10649             mAccessibilityViewId = sNextAccessibilityViewId++;
10650         }
10651         return mAccessibilityViewId;
10652     }
10653 
10654     /**
10655      * Gets the unique identifier of this view on the screen for autofill purposes.
10656      *
10657      * @return The view autofill id.
10658      *
10659      * @hide
10660      */
getAutofillViewId()10661     public int getAutofillViewId() {
10662         if (mAutofillViewId == NO_ID) {
10663             mAutofillViewId = mContext.getNextAutofillId();
10664         }
10665         return mAutofillViewId;
10666     }
10667 
10668     /**
10669      * Gets the unique identifier of the window in which this View resides.
10670      *
10671      * @return The window accessibility id.
10672      *
10673      * @hide
10674      */
getAccessibilityWindowId()10675     public int getAccessibilityWindowId() {
10676         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
10677                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
10678     }
10679 
10680     /**
10681      * Returns the {@link View}'s state description.
10682      * <p>
10683      * <strong>Note:</strong> Do not override this method, as it will have no
10684      * effect on the state description presented to accessibility services.
10685      * You must call {@link #setStateDescription(CharSequence)} to modify the
10686      * state description.
10687      *
10688      * @return the state description
10689      * @see #setStateDescription(CharSequence)
10690      */
10691     @ViewDebug.ExportedProperty(category = "accessibility")
getStateDescription()10692     public final @Nullable CharSequence getStateDescription() {
10693         return mStateDescription;
10694     }
10695 
10696     /**
10697      * Returns the {@link View}'s content description.
10698      * <p>
10699      * <strong>Note:</strong> Do not override this method, as it will have no
10700      * effect on the content description presented to accessibility services.
10701      * You must call {@link #setContentDescription(CharSequence)} to modify the
10702      * content description.
10703      *
10704      * @return the content description
10705      * @see #setContentDescription(CharSequence)
10706      * @attr ref android.R.styleable#View_contentDescription
10707      */
10708     @ViewDebug.ExportedProperty(category = "accessibility")
10709     @InspectableProperty
getContentDescription()10710     public CharSequence getContentDescription() {
10711         return mContentDescription;
10712     }
10713 
10714     /**
10715      * Sets the {@link View}'s state description.
10716      * <p>
10717      * A state description briefly describes the states of the view and is primarily used
10718      * for accessibility support to determine how the states of a view should be presented to
10719      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
10720      * it is used for customized state description (for example, "wifi, connected, three bars").
10721      * State description changes frequently while content description should change less often.
10722      * State description should be localized. For android widgets which have default state
10723      * descriptions, app developers can call this method to override the state descriptions.
10724      * Setting state description to null restores the default behavior.
10725      *
10726      * @param stateDescription The state description.
10727      * @see #getStateDescription()
10728      */
10729     @RemotableViewMethod
setStateDescription(@ullable CharSequence stateDescription)10730     public void setStateDescription(@Nullable CharSequence stateDescription) {
10731         if (mStateDescription == null) {
10732             if (stateDescription == null) {
10733                 return;
10734             }
10735         } else if (mStateDescription.equals(stateDescription)) {
10736             return;
10737         }
10738         mStateDescription = stateDescription;
10739         if (!TextUtils.isEmpty(stateDescription)
10740                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10741             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10742         }
10743         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10744             AccessibilityEvent event = AccessibilityEvent.obtain();
10745             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
10746             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
10747             sendAccessibilityEventUnchecked(event);
10748         }
10749     }
10750 
10751     /**
10752      * Sets the {@link View}'s content description.
10753      * <p>
10754      * A content description briefly describes the view and is primarily used
10755      * for accessibility support to determine how a view should be presented to
10756      * the user. In the case of a view with no textual representation, such as
10757      * {@link android.widget.ImageButton}, a useful content description
10758      * explains what the view does. For example, an image button with a phone
10759      * icon that is used to place a call may use "Call" as its content
10760      * description. An image of a floppy disk that is used to save a file may
10761      * use "Save".
10762      *
10763      * @param contentDescription The content description.
10764      * @see #getContentDescription()
10765      * @attr ref android.R.styleable#View_contentDescription
10766      */
10767     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)10768     public void setContentDescription(CharSequence contentDescription) {
10769         if (mContentDescription == null) {
10770             if (contentDescription == null) {
10771                 return;
10772             }
10773         } else if (mContentDescription.equals(contentDescription)) {
10774             return;
10775         }
10776         mContentDescription = contentDescription;
10777         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
10778         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10779             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10780             notifySubtreeAccessibilityStateChangedIfNeeded();
10781         } else {
10782             notifyViewAccessibilityStateChangedIfNeeded(
10783                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
10784         }
10785     }
10786 
10787     /**
10788      * Sets the id of a view before which this one is visited in accessibility traversal.
10789      * A screen-reader must visit the content of this view before the content of the one
10790      * it precedes. For example, if view B is set to be before view A, then a screen-reader
10791      * will traverse the entire content of B before traversing the entire content of A,
10792      * regardles of what traversal strategy it is using.
10793      * <p>
10794      * Views that do not have specified before/after relationships are traversed in order
10795      * determined by the screen-reader.
10796      * </p>
10797      * <p>
10798      * Setting that this view is before a view that is not important for accessibility
10799      * or if this view is not important for accessibility will have no effect as the
10800      * screen-reader is not aware of unimportant views.
10801      * </p>
10802      *
10803      * @param beforeId The id of a view this one precedes in accessibility traversal.
10804      *
10805      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
10806      *
10807      * @see #setImportantForAccessibility(int)
10808      */
10809     @RemotableViewMethod
setAccessibilityTraversalBefore(@dRes int beforeId)10810     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
10811         if (mAccessibilityTraversalBeforeId == beforeId) {
10812             return;
10813         }
10814         mAccessibilityTraversalBeforeId = beforeId;
10815         notifyViewAccessibilityStateChangedIfNeeded(
10816                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10817     }
10818 
10819     /**
10820      * Gets the id of a view before which this one is visited in accessibility traversal.
10821      *
10822      * @return The id of a view this one precedes in accessibility traversal if
10823      *         specified, otherwise {@link #NO_ID}.
10824      *
10825      * @see #setAccessibilityTraversalBefore(int)
10826      */
10827     @IdRes
10828     @InspectableProperty
getAccessibilityTraversalBefore()10829     public int getAccessibilityTraversalBefore() {
10830         return mAccessibilityTraversalBeforeId;
10831     }
10832 
10833     /**
10834      * Sets the id of a view after which this one is visited in accessibility traversal.
10835      * A screen-reader must visit the content of the other view before the content of this
10836      * one. For example, if view B is set to be after view A, then a screen-reader
10837      * will traverse the entire content of A before traversing the entire content of B,
10838      * regardles of what traversal strategy it is using.
10839      * <p>
10840      * Views that do not have specified before/after relationships are traversed in order
10841      * determined by the screen-reader.
10842      * </p>
10843      * <p>
10844      * Setting that this view is after a view that is not important for accessibility
10845      * or if this view is not important for accessibility will have no effect as the
10846      * screen-reader is not aware of unimportant views.
10847      * </p>
10848      *
10849      * @param afterId The id of a view this one succedees in accessibility traversal.
10850      *
10851      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
10852      *
10853      * @see #setImportantForAccessibility(int)
10854      */
10855     @RemotableViewMethod
setAccessibilityTraversalAfter(@dRes int afterId)10856     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
10857         if (mAccessibilityTraversalAfterId == afterId) {
10858             return;
10859         }
10860         mAccessibilityTraversalAfterId = afterId;
10861         notifyViewAccessibilityStateChangedIfNeeded(
10862                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10863     }
10864 
10865     /**
10866      * Gets the id of a view after which this one is visited in accessibility traversal.
10867      *
10868      * @return The id of a view this one succeedes in accessibility traversal if
10869      *         specified, otherwise {@link #NO_ID}.
10870      *
10871      * @see #setAccessibilityTraversalAfter(int)
10872      */
10873     @IdRes
10874     @InspectableProperty
getAccessibilityTraversalAfter()10875     public int getAccessibilityTraversalAfter() {
10876         return mAccessibilityTraversalAfterId;
10877     }
10878 
10879     /**
10880      * Gets the id of a view for which this view serves as a label for
10881      * accessibility purposes.
10882      *
10883      * @return The labeled view id.
10884      */
10885     @IdRes
10886     @ViewDebug.ExportedProperty(category = "accessibility")
10887     @InspectableProperty
getLabelFor()10888     public int getLabelFor() {
10889         return mLabelForId;
10890     }
10891 
10892     /**
10893      * Sets the id of a view for which this view serves as a label for
10894      * accessibility purposes.
10895      *
10896      * @param id The labeled view id.
10897      */
10898     @RemotableViewMethod
setLabelFor(@dRes int id)10899     public void setLabelFor(@IdRes int id) {
10900         if (mLabelForId == id) {
10901             return;
10902         }
10903         mLabelForId = id;
10904         if (mLabelForId != View.NO_ID
10905                 && mID == View.NO_ID) {
10906             mID = generateViewId();
10907         }
10908         notifyViewAccessibilityStateChangedIfNeeded(
10909                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10910     }
10911 
10912     /**
10913      * Invoked whenever this view loses focus, either by losing window focus or by losing
10914      * focus within its window. This method can be used to clear any state tied to the
10915      * focus. For instance, if a button is held pressed with the trackball and the window
10916      * loses focus, this method can be used to cancel the press.
10917      *
10918      * Subclasses of View overriding this method should always call super.onFocusLost().
10919      *
10920      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
10921      * @see #onWindowFocusChanged(boolean)
10922      *
10923      * @hide pending API council approval
10924      */
10925     @CallSuper
10926     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onFocusLost()10927     protected void onFocusLost() {
10928         resetPressedState();
10929     }
10930 
resetPressedState()10931     private void resetPressedState() {
10932         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10933             return;
10934         }
10935 
10936         if (isPressed()) {
10937             setPressed(false);
10938 
10939             if (!mHasPerformedLongPress) {
10940                 removeLongPressCallback();
10941             }
10942         }
10943     }
10944 
10945     /**
10946      * Returns true if this view has focus
10947      *
10948      * @return True if this view has focus, false otherwise.
10949      */
10950     @ViewDebug.ExportedProperty(category = "focus")
10951     @InspectableProperty(hasAttributeId = false)
isFocused()10952     public boolean isFocused() {
10953         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
10954     }
10955 
10956     /**
10957      * Find the view in the hierarchy rooted at this view that currently has
10958      * focus.
10959      *
10960      * @return The view that currently has focus, or null if no focused view can
10961      *         be found.
10962      */
findFocus()10963     public View findFocus() {
10964         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
10965     }
10966 
10967     /**
10968      * Indicates whether this view is one of the set of scrollable containers in
10969      * its window.
10970      *
10971      * @return whether this view is one of the set of scrollable containers in
10972      * its window
10973      *
10974      * @attr ref android.R.styleable#View_isScrollContainer
10975      */
10976     @InspectableProperty(name = "isScrollContainer")
isScrollContainer()10977     public boolean isScrollContainer() {
10978         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
10979     }
10980 
10981     /**
10982      * Change whether this view is one of the set of scrollable containers in
10983      * its window.  This will be used to determine whether the window can
10984      * resize or must pan when a soft input area is open -- scrollable
10985      * containers allow the window to use resize mode since the container
10986      * will appropriately shrink.
10987      *
10988      * @attr ref android.R.styleable#View_isScrollContainer
10989      */
setScrollContainer(boolean isScrollContainer)10990     public void setScrollContainer(boolean isScrollContainer) {
10991         if (isScrollContainer) {
10992             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
10993                 mAttachInfo.mScrollContainers.add(this);
10994                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
10995             }
10996             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
10997         } else {
10998             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
10999                 mAttachInfo.mScrollContainers.remove(this);
11000             }
11001             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
11002         }
11003     }
11004 
11005     /**
11006      * Returns the quality of the drawing cache.
11007      *
11008      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11009      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11010      *
11011      * @see #setDrawingCacheQuality(int)
11012      * @see #setDrawingCacheEnabled(boolean)
11013      * @see #isDrawingCacheEnabled()
11014      *
11015      * @attr ref android.R.styleable#View_drawingCacheQuality
11016      *
11017      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11018      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11019      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11020      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11021      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11022      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11023      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11024      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11025      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11026      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11027      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11028      * reports or unit testing the {@link PixelCopy} API is recommended.
11029      */
11030     @Deprecated
11031     @DrawingCacheQuality
11032     @InspectableProperty(enumMapping = {
11033             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
11034             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
11035             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
11036     })
getDrawingCacheQuality()11037     public int getDrawingCacheQuality() {
11038         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
11039     }
11040 
11041     /**
11042      * Set the drawing cache quality of this view. This value is used only when the
11043      * drawing cache is enabled
11044      *
11045      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11046      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11047      *
11048      * @see #getDrawingCacheQuality()
11049      * @see #setDrawingCacheEnabled(boolean)
11050      * @see #isDrawingCacheEnabled()
11051      *
11052      * @attr ref android.R.styleable#View_drawingCacheQuality
11053      *
11054      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11055      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11056      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11057      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11058      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11059      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11060      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11061      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11062      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11063      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11064      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11065      * reports or unit testing the {@link PixelCopy} API is recommended.
11066      */
11067     @Deprecated
setDrawingCacheQuality(@rawingCacheQuality int quality)11068     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
11069         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
11070     }
11071 
11072     /**
11073      * Returns whether the screen should remain on, corresponding to the current
11074      * value of {@link #KEEP_SCREEN_ON}.
11075      *
11076      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
11077      *
11078      * @see #setKeepScreenOn(boolean)
11079      *
11080      * @attr ref android.R.styleable#View_keepScreenOn
11081      */
11082     @InspectableProperty
getKeepScreenOn()11083     public boolean getKeepScreenOn() {
11084         return (mViewFlags & KEEP_SCREEN_ON) != 0;
11085     }
11086 
11087     /**
11088      * Controls whether the screen should remain on, modifying the
11089      * value of {@link #KEEP_SCREEN_ON}.
11090      *
11091      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
11092      *
11093      * @see #getKeepScreenOn()
11094      *
11095      * @attr ref android.R.styleable#View_keepScreenOn
11096      */
setKeepScreenOn(boolean keepScreenOn)11097     public void setKeepScreenOn(boolean keepScreenOn) {
11098         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
11099     }
11100 
11101     /**
11102      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11103      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11104      *
11105      * @attr ref android.R.styleable#View_nextFocusLeft
11106      */
11107     @IdRes
11108     @InspectableProperty(name = "nextFocusLeft")
getNextFocusLeftId()11109     public int getNextFocusLeftId() {
11110         return mNextFocusLeftId;
11111     }
11112 
11113     /**
11114      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11115      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
11116      * decide automatically.
11117      *
11118      * @attr ref android.R.styleable#View_nextFocusLeft
11119      */
setNextFocusLeftId(@dRes int nextFocusLeftId)11120     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
11121         mNextFocusLeftId = nextFocusLeftId;
11122     }
11123 
11124     /**
11125      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11126      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11127      *
11128      * @attr ref android.R.styleable#View_nextFocusRight
11129      */
11130     @IdRes
11131     @InspectableProperty(name = "nextFocusRight")
getNextFocusRightId()11132     public int getNextFocusRightId() {
11133         return mNextFocusRightId;
11134     }
11135 
11136     /**
11137      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11138      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
11139      * decide automatically.
11140      *
11141      * @attr ref android.R.styleable#View_nextFocusRight
11142      */
setNextFocusRightId(@dRes int nextFocusRightId)11143     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
11144         mNextFocusRightId = nextFocusRightId;
11145     }
11146 
11147     /**
11148      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11149      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11150      *
11151      * @attr ref android.R.styleable#View_nextFocusUp
11152      */
11153     @IdRes
11154     @InspectableProperty(name = "nextFocusUp")
getNextFocusUpId()11155     public int getNextFocusUpId() {
11156         return mNextFocusUpId;
11157     }
11158 
11159     /**
11160      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11161      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
11162      * decide automatically.
11163      *
11164      * @attr ref android.R.styleable#View_nextFocusUp
11165      */
setNextFocusUpId(@dRes int nextFocusUpId)11166     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
11167         mNextFocusUpId = nextFocusUpId;
11168     }
11169 
11170     /**
11171      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11172      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11173      *
11174      * @attr ref android.R.styleable#View_nextFocusDown
11175      */
11176     @IdRes
11177     @InspectableProperty(name = "nextFocusDown")
getNextFocusDownId()11178     public int getNextFocusDownId() {
11179         return mNextFocusDownId;
11180     }
11181 
11182     /**
11183      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11184      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
11185      * decide automatically.
11186      *
11187      * @attr ref android.R.styleable#View_nextFocusDown
11188      */
setNextFocusDownId(@dRes int nextFocusDownId)11189     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
11190         mNextFocusDownId = nextFocusDownId;
11191     }
11192 
11193     /**
11194      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11195      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11196      *
11197      * @attr ref android.R.styleable#View_nextFocusForward
11198      */
11199     @IdRes
11200     @InspectableProperty(name = "nextFocusForward")
getNextFocusForwardId()11201     public int getNextFocusForwardId() {
11202         return mNextFocusForwardId;
11203     }
11204 
11205     /**
11206      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11207      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
11208      * decide automatically.
11209      *
11210      * @attr ref android.R.styleable#View_nextFocusForward
11211      */
setNextFocusForwardId(@dRes int nextFocusForwardId)11212     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
11213         mNextFocusForwardId = nextFocusForwardId;
11214     }
11215 
11216     /**
11217      * Gets the id of the root of the next keyboard navigation cluster.
11218      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
11219      * decide automatically.
11220      *
11221      * @attr ref android.R.styleable#View_nextClusterForward
11222      */
11223     @IdRes
11224     @InspectableProperty(name = "nextClusterForward")
getNextClusterForwardId()11225     public int getNextClusterForwardId() {
11226         return mNextClusterForwardId;
11227     }
11228 
11229     /**
11230      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
11231      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
11232      * decide automatically.
11233      *
11234      * @attr ref android.R.styleable#View_nextClusterForward
11235      */
setNextClusterForwardId(@dRes int nextClusterForwardId)11236     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
11237         mNextClusterForwardId = nextClusterForwardId;
11238     }
11239 
11240     /**
11241      * Returns the visibility of this view and all of its ancestors
11242      *
11243      * @return True if this view and all of its ancestors are {@link #VISIBLE}
11244      */
isShown()11245     public boolean isShown() {
11246         View current = this;
11247         //noinspection ConstantConditions
11248         do {
11249             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
11250                 return false;
11251             }
11252             ViewParent parent = current.mParent;
11253             if (parent == null) {
11254                 return false; // We are not attached to the view root
11255             }
11256             if (!(parent instanceof View)) {
11257                 return true;
11258             }
11259             current = (View) parent;
11260         } while (current != null);
11261 
11262         return false;
11263     }
11264 
detached()11265     private boolean detached() {
11266         View current = this;
11267         //noinspection ConstantConditions
11268         do {
11269             if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
11270                 return true;
11271             }
11272             ViewParent parent = current.mParent;
11273             if (parent == null) {
11274                 return false;
11275             }
11276             if (!(parent instanceof View)) {
11277                 return false;
11278             }
11279             current = (View) parent;
11280         } while (current != null);
11281 
11282         return false;
11283     }
11284 
11285     /**
11286      * Called by the view hierarchy when the content insets for a window have
11287      * changed, to allow it to adjust its content to fit within those windows.
11288      * The content insets tell you the space that the status bar, input method,
11289      * and other system windows infringe on the application's window.
11290      *
11291      * <p>You do not normally need to deal with this function, since the default
11292      * window decoration given to applications takes care of applying it to the
11293      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
11294      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
11295      * and your content can be placed under those system elements.  You can then
11296      * use this method within your view hierarchy if you have parts of your UI
11297      * which you would like to ensure are not being covered.
11298      *
11299      * <p>The default implementation of this method simply applies the content
11300      * insets to the view's padding, consuming that content (modifying the
11301      * insets to be 0), and returning true.  This behavior is off by default, but can
11302      * be enabled through {@link #setFitsSystemWindows(boolean)}.
11303      *
11304      * <p>This function's traversal down the hierarchy is depth-first.  The same content
11305      * insets object is propagated down the hierarchy, so any changes made to it will
11306      * be seen by all following views (including potentially ones above in
11307      * the hierarchy since this is a depth-first traversal).  The first view
11308      * that returns true will abort the entire traversal.
11309      *
11310      * <p>The default implementation works well for a situation where it is
11311      * used with a container that covers the entire window, allowing it to
11312      * apply the appropriate insets to its content on all edges.  If you need
11313      * a more complicated layout (such as two different views fitting system
11314      * windows, one on the top of the window, and one on the bottom),
11315      * you can override the method and handle the insets however you would like.
11316      * Note that the insets provided by the framework are always relative to the
11317      * far edges of the window, not accounting for the location of the called view
11318      * within that window.  (In fact when this method is called you do not yet know
11319      * where the layout will place the view, as it is done before layout happens.)
11320      *
11321      * <p>Note: unlike many View methods, there is no dispatch phase to this
11322      * call.  If you are overriding it in a ViewGroup and want to allow the
11323      * call to continue to your children, you must be sure to call the super
11324      * implementation.
11325      *
11326      * <p>Here is a sample layout that makes use of fitting system windows
11327      * to have controls for a video view placed inside of the window decorations
11328      * that it hides and shows.  This can be used with code like the second
11329      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
11330      *
11331      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
11332      *
11333      * @param insets Current content insets of the window.  Prior to
11334      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
11335      * the insets or else you and Android will be unhappy.
11336      *
11337      * @return {@code true} if this view applied the insets and it should not
11338      * continue propagating further down the hierarchy, {@code false} otherwise.
11339      * @see #getFitsSystemWindows()
11340      * @see #setFitsSystemWindows(boolean)
11341      * @see #setSystemUiVisibility(int)
11342      *
11343      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
11344      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
11345      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
11346      * to implement handling their own insets.
11347      */
11348     @Deprecated
fitSystemWindows(Rect insets)11349     protected boolean fitSystemWindows(Rect insets) {
11350         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
11351             if (insets == null) {
11352                 // Null insets by definition have already been consumed.
11353                 // This call cannot apply insets since there are none to apply,
11354                 // so return false.
11355                 return false;
11356             }
11357             // If we're not in the process of dispatching the newer apply insets call,
11358             // that means we're not in the compatibility path. Dispatch into the newer
11359             // apply insets path and take things from there.
11360             try {
11361                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
11362                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
11363             } finally {
11364                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
11365             }
11366         } else {
11367             // We're being called from the newer apply insets path.
11368             // Perform the standard fallback behavior.
11369             return fitSystemWindowsInt(insets);
11370         }
11371     }
11372 
fitSystemWindowsInt(Rect insets)11373     private boolean fitSystemWindowsInt(Rect insets) {
11374         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
11375             Rect localInsets = sThreadLocal.get();
11376             boolean res = computeFitSystemWindows(insets, localInsets);
11377             applyInsets(localInsets);
11378             return res;
11379         }
11380         return false;
11381     }
11382 
applyInsets(Rect insets)11383     private void applyInsets(Rect insets) {
11384         mUserPaddingStart = UNDEFINED_PADDING;
11385         mUserPaddingEnd = UNDEFINED_PADDING;
11386         mUserPaddingLeftInitial = insets.left;
11387         mUserPaddingRightInitial = insets.right;
11388         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
11389     }
11390 
11391     /**
11392      * Called when the view should apply {@link WindowInsets} according to its internal policy.
11393      *
11394      * <p>This method should be overridden by views that wish to apply a policy different from or
11395      * in addition to the default behavior. Clients that wish to force a view subtree
11396      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
11397      *
11398      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
11399      * it will be called during dispatch instead of this method. The listener may optionally
11400      * call this method from its own implementation if it wishes to apply the view's default
11401      * insets policy in addition to its own.</p>
11402      *
11403      * <p>Implementations of this method should either return the insets parameter unchanged
11404      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
11405      * that this view applied itself. This allows new inset types added in future platform
11406      * versions to pass through existing implementations unchanged without being erroneously
11407      * consumed.</p>
11408      *
11409      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
11410      * property is set then the view will consume the system window insets and apply them
11411      * as padding for the view.</p>
11412      *
11413      * @param insets Insets to apply
11414      * @return The supplied insets with any applied insets consumed
11415      */
onApplyWindowInsets(WindowInsets insets)11416     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
11417         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11418                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
11419             return onApplyFrameworkOptionalFitSystemWindows(insets);
11420         }
11421         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
11422             // We weren't called from within a direct call to fitSystemWindows,
11423             // call into it as a fallback in case we're in a class that overrides it
11424             // and has logic to perform.
11425             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
11426                 return insets.consumeSystemWindowInsets();
11427             }
11428         } else {
11429             // We were called from within a direct call to fitSystemWindows.
11430             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
11431                 return insets.consumeSystemWindowInsets();
11432             }
11433         }
11434         return insets;
11435     }
11436 
onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets)11437     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
11438         Rect localInsets = sThreadLocal.get();
11439         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
11440         applyInsets(localInsets);
11441         return result;
11442     }
11443 
11444     /**
11445      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
11446      * window insets to this view. The listener's
11447      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
11448      * method will be called instead of the view's
11449      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
11450      *
11451      * @param listener Listener to set
11452      *
11453      * @see #onApplyWindowInsets(WindowInsets)
11454      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)11455     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
11456         getListenerInfo().mOnApplyWindowInsetsListener = listener;
11457     }
11458 
11459     /**
11460      * Request to apply the given window insets to this view or another view in its subtree.
11461      *
11462      * <p>This method should be called by clients wishing to apply insets corresponding to areas
11463      * obscured by window decorations or overlays. This can include the status and navigation bars,
11464      * action bars, input methods and more. New inset categories may be added in the future.
11465      * The method returns the insets provided minus any that were applied by this view or its
11466      * children.</p>
11467      *
11468      * <p>Clients wishing to provide custom behavior should override the
11469      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
11470      * {@link OnApplyWindowInsetsListener} via the
11471      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
11472      * method.</p>
11473      *
11474      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
11475      * </p>
11476      *
11477      * @param insets Insets to apply
11478      * @return The provided insets minus the insets that were consumed
11479      */
dispatchApplyWindowInsets(WindowInsets insets)11480     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
11481         try {
11482             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
11483             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
11484                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
11485             } else {
11486                 return onApplyWindowInsets(insets);
11487             }
11488         } finally {
11489             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
11490         }
11491     }
11492 
11493     /**
11494      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
11495      * cause insets.
11496      * <p>
11497      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
11498      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
11499      * this view.
11500      * </p>
11501      * @param callback The callback to set.
11502      */
setWindowInsetsAnimationCallback( @ullable WindowInsetsAnimation.Callback callback)11503     public void setWindowInsetsAnimationCallback(
11504             @Nullable WindowInsetsAnimation.Callback callback) {
11505         getListenerInfo().mWindowInsetsAnimationCallback = callback;
11506     }
11507 
11508     /**
11509      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
11510      *         or view tree of the sub-hierarchy {@code false} otherwise.
11511      * @hide
11512      */
hasWindowInsetsAnimationCallback()11513     public boolean hasWindowInsetsAnimationCallback() {
11514         return getListenerInfo().mWindowInsetsAnimationCallback != null;
11515     }
11516 
11517     /**
11518      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
11519      * when Window Insets animation is being prepared.
11520      * @param animation current animation
11521      *
11522      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
11523      */
dispatchWindowInsetsAnimationPrepare( @onNull WindowInsetsAnimation animation)11524     public void dispatchWindowInsetsAnimationPrepare(
11525             @NonNull WindowInsetsAnimation animation) {
11526         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11527             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
11528         }
11529     }
11530 
11531     /**
11532      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
11533      * when Window Insets animation is started.
11534      * @param animation current animation
11535      * @param bounds the upper and lower {@link Bounds} that provides range of
11536      *  {@link WindowInsetsAnimation}.
11537      * @return the upper and lower {@link Bounds}.
11538      */
11539     @NonNull
dispatchWindowInsetsAnimationStart( @onNull WindowInsetsAnimation animation, @NonNull Bounds bounds)11540     public Bounds dispatchWindowInsetsAnimationStart(
11541             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
11542         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11543             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
11544         }
11545         return bounds;
11546     }
11547 
11548     /**
11549      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
11550      * when Window Insets animation makes progress.
11551      * @param insets The current {@link WindowInsets}.
11552      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
11553      * @return current {@link WindowInsets}.
11554      */
11555     @NonNull
dispatchWindowInsetsAnimationProgress(@onNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations)11556     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
11557             @NonNull List<WindowInsetsAnimation> runningAnimations) {
11558         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11559             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
11560                     runningAnimations);
11561         } else {
11562             return insets;
11563         }
11564     }
11565 
11566     /**
11567      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
11568      * when Window Insets animation ends.
11569      * @param animation The current ongoing {@link WindowInsetsAnimation}.
11570      */
dispatchWindowInsetsAnimationEnd(@onNull WindowInsetsAnimation animation)11571     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
11572         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11573             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
11574         }
11575     }
11576 
11577     /**
11578      * Sets a list of areas within this view's post-layout coordinate space where the system
11579      * should not intercept touch or other pointing device gestures. <em>This method should
11580      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
11581      *
11582      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
11583      * input in order to function correctly in the presence of global system gestures that may
11584      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
11585      * to provide system-level navigation functionality, a view such as a navigation drawer
11586      * container can mark the left (or starting) edge of itself as requiring gesture capture
11587      * priority using this API. The system may then choose to relax its own gesture recognition
11588      * to allow the app to consume the user's gesture. It is not necessary for an app to register
11589      * exclusion rects for broadly spanning regions such as the entirety of a
11590      * <code>ScrollView</code> or for simple press and release click targets such as
11591      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
11592      * a precision touch gesture in a small area in either the X or Y dimension, such as
11593      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
11594      *
11595      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
11596      * exclusions it takes into account. The limit does not apply while the navigation
11597      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
11598      * {@link android.inputmethodservice.InputMethodService input method} and
11599      * {@link Intent#CATEGORY_HOME home activity}.
11600      * </p>
11601      *
11602      * @param rects A list of precision gesture regions that this view needs to function correctly
11603      */
setSystemGestureExclusionRects(@onNull List<Rect> rects)11604     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
11605         if (rects.isEmpty() && mListenerInfo == null) return;
11606 
11607         final ListenerInfo info = getListenerInfo();
11608         if (info.mSystemGestureExclusionRects != null) {
11609             info.mSystemGestureExclusionRects.clear();
11610             info.mSystemGestureExclusionRects.addAll(rects);
11611         } else {
11612             info.mSystemGestureExclusionRects = new ArrayList<>(rects);
11613         }
11614         if (rects.isEmpty()) {
11615             if (info.mPositionUpdateListener != null) {
11616                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
11617             }
11618         } else {
11619             if (info.mPositionUpdateListener == null) {
11620                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
11621                     @Override
11622                     public void positionChanged(long n, int l, int t, int r, int b) {
11623                         postUpdateSystemGestureExclusionRects();
11624                     }
11625 
11626                     @Override
11627                     public void positionLost(long frameNumber) {
11628                         postUpdateSystemGestureExclusionRects();
11629                     }
11630                 };
11631                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
11632             }
11633         }
11634         postUpdateSystemGestureExclusionRects();
11635     }
11636 
11637     /**
11638      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
11639      */
postUpdateSystemGestureExclusionRects()11640     void postUpdateSystemGestureExclusionRects() {
11641         // Potentially racey from a background thread. It's ok if it's not perfect.
11642         final Handler h = getHandler();
11643         if (h != null) {
11644             h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects);
11645         }
11646     }
11647 
updateSystemGestureExclusionRects()11648     void updateSystemGestureExclusionRects() {
11649         final AttachInfo ai = mAttachInfo;
11650         if (ai != null) {
11651             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
11652         }
11653     }
11654 
11655     /**
11656      * Retrieve the list of areas within this view's post-layout coordinate space where the system
11657      * should not intercept touch or other pointing device gestures.
11658      *
11659      * <p>Do not modify the returned list.</p>
11660      *
11661      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
11662      */
11663     @NonNull
getSystemGestureExclusionRects()11664     public List<Rect> getSystemGestureExclusionRects() {
11665         final ListenerInfo info = mListenerInfo;
11666         if (info != null) {
11667             final List<Rect> list = info.mSystemGestureExclusionRects;
11668             if (list != null) {
11669                 return list;
11670             }
11671         }
11672         return Collections.emptyList();
11673     }
11674 
11675     /**
11676      * Compute the view's coordinate within the surface.
11677      *
11678      * <p>Computes the coordinates of this view in its surface. The argument
11679      * must be an array of two integers. After the method returns, the array
11680      * contains the x and y location in that order.</p>
11681      *
11682      * @param location an array of two integers in which to hold the coordinates
11683      */
getLocationInSurface(@onNull @ize2) int[] location)11684     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
11685         getLocationInWindow(location);
11686         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
11687             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
11688             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
11689         }
11690     }
11691 
11692     /**
11693      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
11694      * only available if the view is attached.
11695      *
11696      * @return WindowInsets from the top of the view hierarchy or null if View is detached
11697      */
getRootWindowInsets()11698     public WindowInsets getRootWindowInsets() {
11699         if (mAttachInfo != null) {
11700             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
11701         }
11702         return null;
11703     }
11704 
11705     /**
11706      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
11707      *
11708      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
11709      *         a window nor a view tree with a decor.
11710      * @see Window#getInsetsController()
11711      */
getWindowInsetsController()11712     public @Nullable WindowInsetsController getWindowInsetsController() {
11713         if (mAttachInfo != null) {
11714             return mAttachInfo.mViewRootImpl.getInsetsController();
11715         }
11716         ViewParent parent = getParent();
11717         if (parent instanceof View) {
11718             return ((View) parent).getWindowInsetsController();
11719         } else if (parent instanceof ViewRootImpl) {
11720             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
11721             return ((ViewRootImpl) parent).getInsetsController();
11722         }
11723         return null;
11724     }
11725 
11726     /**
11727      * @hide Compute the insets that should be consumed by this view and the ones
11728      * that should propagate to those under it.
11729      *
11730      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
11731      *
11732      * @param inoutInsets the insets given to this view
11733      * @param outLocalInsets the insets that should be applied to this view
11734      * @deprecated use {@link #computeSystemWindowInsets}
11735      * @return
11736      */
11737     @Deprecated
11738     @UnsupportedAppUsage
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)11739     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
11740         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
11741                 outLocalInsets);
11742         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
11743         return innerInsets.isSystemWindowInsetsConsumed();
11744     }
11745 
11746     /**
11747      * Compute insets that should be consumed by this view and the ones that should propagate
11748      * to those under it.
11749      *
11750      * @param in Insets currently being processed by this View, likely received as a parameter
11751      *           to {@link #onApplyWindowInsets(WindowInsets)}.
11752      * @param outLocalInsets A Rect that will receive the insets that should be consumed
11753      *                       by this view
11754      * @return Insets that should be passed along to views under this one
11755      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)11756     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
11757         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11758                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
11759         if (isOptionalFitSystemWindows && mAttachInfo != null) {
11760             OnContentApplyWindowInsetsListener listener =
11761                     mAttachInfo.mContentOnApplyWindowInsetsListener;
11762             if (listener == null) {
11763                 // The application wants to take care of fitting system window for
11764                 // the content.
11765                 outLocalInsets.setEmpty();
11766                 return in;
11767             }
11768             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
11769             outLocalInsets.set(result.first.toRect());
11770             return result.second;
11771         } else {
11772             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
11773             return in.consumeSystemWindowInsets().inset(outLocalInsets);
11774         }
11775     }
11776 
11777     /**
11778      * Sets whether or not this view should account for system screen decorations
11779      * such as the status bar and inset its content; that is, controlling whether
11780      * the default implementation of {@link #fitSystemWindows(Rect)} will be
11781      * executed.  See that method for more details.
11782      *
11783      * <p>Note that if you are providing your own implementation of
11784      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
11785      * flag to true -- your implementation will be overriding the default
11786      * implementation that checks this flag.
11787      *
11788      * @param fitSystemWindows If true, then the default implementation of
11789      * {@link #fitSystemWindows(Rect)} will be executed.
11790      *
11791      * @attr ref android.R.styleable#View_fitsSystemWindows
11792      * @see #getFitsSystemWindows()
11793      * @see #fitSystemWindows(Rect)
11794      * @see #setSystemUiVisibility(int)
11795      */
setFitsSystemWindows(boolean fitSystemWindows)11796     public void setFitsSystemWindows(boolean fitSystemWindows) {
11797         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
11798     }
11799 
11800     /**
11801      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
11802      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
11803      * will be executed.
11804      *
11805      * @return {@code true} if the default implementation of
11806      * {@link #fitSystemWindows(Rect)} will be executed.
11807      *
11808      * @attr ref android.R.styleable#View_fitsSystemWindows
11809      * @see #setFitsSystemWindows(boolean)
11810      * @see #fitSystemWindows(Rect)
11811      * @see #setSystemUiVisibility(int)
11812      */
11813     @ViewDebug.ExportedProperty
11814     @InspectableProperty
getFitsSystemWindows()11815     public boolean getFitsSystemWindows() {
11816         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
11817     }
11818 
11819     /** @hide */
11820     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
fitsSystemWindows()11821     public boolean fitsSystemWindows() {
11822         return getFitsSystemWindows();
11823     }
11824 
11825     /**
11826      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
11827      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
11828      */
11829     @Deprecated
requestFitSystemWindows()11830     public void requestFitSystemWindows() {
11831         if (mParent != null) {
11832             mParent.requestFitSystemWindows();
11833         }
11834     }
11835 
11836     /**
11837      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
11838      */
requestApplyInsets()11839     public void requestApplyInsets() {
11840         requestFitSystemWindows();
11841     }
11842 
11843     /**
11844      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
11845      * @hide
11846      */
11847     @UnsupportedAppUsage
makeOptionalFitsSystemWindows()11848     public void makeOptionalFitsSystemWindows() {
11849         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
11850     }
11851 
11852     /**
11853      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
11854      * @hide
11855      */
makeFrameworkOptionalFitsSystemWindows()11856     public void makeFrameworkOptionalFitsSystemWindows() {
11857         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
11858     }
11859 
11860     /**
11861      * @hide
11862      */
isFrameworkOptionalFitsSystemWindows()11863     public boolean isFrameworkOptionalFitsSystemWindows() {
11864         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
11865     }
11866 
11867     /**
11868      * Returns the visibility status for this view.
11869      *
11870      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11871      * @attr ref android.R.styleable#View_visibility
11872      */
11873     @ViewDebug.ExportedProperty(mapping = {
11874         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
11875         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
11876         @ViewDebug.IntToString(from = GONE,      to = "GONE")
11877     })
11878     @InspectableProperty(enumMapping = {
11879             @EnumEntry(value = VISIBLE, name = "visible"),
11880             @EnumEntry(value = INVISIBLE, name = "invisible"),
11881             @EnumEntry(value = GONE, name = "gone")
11882     })
11883     @Visibility
getVisibility()11884     public int getVisibility() {
11885         return mViewFlags & VISIBILITY_MASK;
11886     }
11887 
11888     /**
11889      * Set the visibility state of this view.
11890      *
11891      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11892      * @attr ref android.R.styleable#View_visibility
11893      */
11894     @RemotableViewMethod
setVisibility(@isibility int visibility)11895     public void setVisibility(@Visibility int visibility) {
11896         setFlags(visibility, VISIBILITY_MASK);
11897     }
11898 
11899     /**
11900      * Returns the enabled status for this view. The interpretation of the
11901      * enabled state varies by subclass.
11902      *
11903      * @return True if this view is enabled, false otherwise.
11904      */
11905     @ViewDebug.ExportedProperty
11906     @InspectableProperty
isEnabled()11907     public boolean isEnabled() {
11908         return (mViewFlags & ENABLED_MASK) == ENABLED;
11909     }
11910 
11911     /**
11912      * Set the enabled state of this view. The interpretation of the enabled
11913      * state varies by subclass.
11914      *
11915      * @param enabled True if this view is enabled, false otherwise.
11916      */
11917     @RemotableViewMethod
setEnabled(boolean enabled)11918     public void setEnabled(boolean enabled) {
11919         if (enabled == isEnabled()) return;
11920 
11921         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
11922 
11923         /*
11924          * The View most likely has to change its appearance, so refresh
11925          * the drawable state.
11926          */
11927         refreshDrawableState();
11928 
11929         // Invalidate too, since the default behavior for views is to be
11930         // be drawn at 50% alpha rather than to change the drawable.
11931         invalidate(true);
11932 
11933         if (!enabled) {
11934             cancelPendingInputEvents();
11935         }
11936     }
11937 
11938     /**
11939      * Set whether this view can receive the focus.
11940      * <p>
11941      * Setting this to false will also ensure that this view is not focusable
11942      * in touch mode.
11943      *
11944      * @param focusable If true, this view can receive the focus.
11945      *
11946      * @see #setFocusableInTouchMode(boolean)
11947      * @see #setFocusable(int)
11948      * @attr ref android.R.styleable#View_focusable
11949      */
11950     @RemotableViewMethod
setFocusable(boolean focusable)11951     public void setFocusable(boolean focusable) {
11952         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
11953     }
11954 
11955     /**
11956      * Sets whether this view can receive focus.
11957      * <p>
11958      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
11959      * automatically based on the view's interactivity. This is the default.
11960      * <p>
11961      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
11962      * in touch mode.
11963      *
11964      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
11965      *                  or {@link #FOCUSABLE_AUTO}.
11966      * @see #setFocusableInTouchMode(boolean)
11967      * @attr ref android.R.styleable#View_focusable
11968      */
11969     @RemotableViewMethod
setFocusable(@ocusable int focusable)11970     public void setFocusable(@Focusable int focusable) {
11971         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
11972             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
11973         }
11974         setFlags(focusable, FOCUSABLE_MASK);
11975     }
11976 
11977     /**
11978      * Set whether this view can receive focus while in touch mode.
11979      *
11980      * Setting this to true will also ensure that this view is focusable.
11981      *
11982      * @param focusableInTouchMode If true, this view can receive the focus while
11983      *   in touch mode.
11984      *
11985      * @see #setFocusable(boolean)
11986      * @attr ref android.R.styleable#View_focusableInTouchMode
11987      */
11988     @RemotableViewMethod
setFocusableInTouchMode(boolean focusableInTouchMode)11989     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
11990         // Focusable in touch mode should always be set before the focusable flag
11991         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
11992         // which, in touch mode, will not successfully request focus on this view
11993         // because the focusable in touch mode flag is not set
11994         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
11995 
11996         // Clear FOCUSABLE_AUTO if set.
11997         if (focusableInTouchMode) {
11998             // Clears FOCUSABLE_AUTO if set.
11999             setFlags(FOCUSABLE, FOCUSABLE_MASK);
12000         }
12001     }
12002 
12003     /**
12004      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
12005      * to autofill the view with the user's data.
12006      *
12007      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
12008      * For example, if the application accepts either an username or email address to identify
12009      * an user.
12010      *
12011      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
12012      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
12013      * constants such as:
12014      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
12015      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
12016      * {@link #AUTOFILL_HINT_NAME},
12017      * {@link #AUTOFILL_HINT_PHONE},
12018      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
12019      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
12020      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
12021      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
12022      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
12023      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
12024      *
12025      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
12026      * @attr ref android.R.styleable#View_autofillHints
12027      */
setAutofillHints(@ullable String... autofillHints)12028     public void setAutofillHints(@Nullable String... autofillHints) {
12029         if (autofillHints == null || autofillHints.length == 0) {
12030             mAutofillHints = null;
12031         } else {
12032             mAutofillHints = autofillHints;
12033         }
12034     }
12035 
12036     /**
12037      * @hide
12038      */
12039     @TestApi
setAutofilled(boolean isAutofilled, boolean hideHighlight)12040     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
12041         boolean wasChanged = isAutofilled != isAutofilled();
12042 
12043         if (wasChanged) {
12044             if (isAutofilled) {
12045                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
12046             } else {
12047                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
12048             }
12049 
12050             if (hideHighlight) {
12051                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
12052             } else {
12053                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
12054             }
12055 
12056             invalidate();
12057         }
12058     }
12059 
12060     /**
12061      * Set whether this view should have sound effects enabled for events such as
12062      * clicking and touching.
12063      *
12064      * <p>You may wish to disable sound effects for a view if you already play sounds,
12065      * for instance, a dial key that plays dtmf tones.
12066      *
12067      * @param soundEffectsEnabled whether sound effects are enabled for this view.
12068      * @see #isSoundEffectsEnabled()
12069      * @see #playSoundEffect(int)
12070      * @attr ref android.R.styleable#View_soundEffectsEnabled
12071      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)12072     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
12073         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
12074     }
12075 
12076     /**
12077      * @return whether this view should have sound effects enabled for events such as
12078      *     clicking and touching.
12079      *
12080      * @see #setSoundEffectsEnabled(boolean)
12081      * @see #playSoundEffect(int)
12082      * @attr ref android.R.styleable#View_soundEffectsEnabled
12083      */
12084     @ViewDebug.ExportedProperty
12085     @InspectableProperty
isSoundEffectsEnabled()12086     public boolean isSoundEffectsEnabled() {
12087         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
12088     }
12089 
12090     /**
12091      * Set whether this view should have haptic feedback for events such as
12092      * long presses.
12093      *
12094      * <p>You may wish to disable haptic feedback if your view already controls
12095      * its own haptic feedback.
12096      *
12097      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
12098      * @see #isHapticFeedbackEnabled()
12099      * @see #performHapticFeedback(int)
12100      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
12101      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)12102     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
12103         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
12104     }
12105 
12106     /**
12107      * @return whether this view should have haptic feedback enabled for events
12108      * long presses.
12109      *
12110      * @see #setHapticFeedbackEnabled(boolean)
12111      * @see #performHapticFeedback(int)
12112      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
12113      */
12114     @ViewDebug.ExportedProperty
12115     @InspectableProperty
isHapticFeedbackEnabled()12116     public boolean isHapticFeedbackEnabled() {
12117         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
12118     }
12119 
12120     /**
12121      * Returns the layout direction for this view.
12122      *
12123      * @return One of {@link #LAYOUT_DIRECTION_LTR},
12124      *   {@link #LAYOUT_DIRECTION_RTL},
12125      *   {@link #LAYOUT_DIRECTION_INHERIT} or
12126      *   {@link #LAYOUT_DIRECTION_LOCALE}.
12127      *
12128      * @attr ref android.R.styleable#View_layoutDirection
12129      *
12130      * @hide
12131      */
12132     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12133         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
12134         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
12135         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
12136         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
12137     })
12138     @InspectableProperty(hasAttributeId = false, enumMapping = {
12139             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12140             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
12141             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
12142             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
12143     })
12144     @LayoutDir
getRawLayoutDirection()12145     public int getRawLayoutDirection() {
12146         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
12147     }
12148 
12149     /**
12150      * Set the layout direction for this view. This will propagate a reset of layout direction
12151      * resolution to the view's children and resolve layout direction for this view.
12152      *
12153      * @param layoutDirection the layout direction to set. Should be one of:
12154      *
12155      * {@link #LAYOUT_DIRECTION_LTR},
12156      * {@link #LAYOUT_DIRECTION_RTL},
12157      * {@link #LAYOUT_DIRECTION_INHERIT},
12158      * {@link #LAYOUT_DIRECTION_LOCALE}.
12159      *
12160      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
12161      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
12162      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
12163      *
12164      * @attr ref android.R.styleable#View_layoutDirection
12165      */
12166     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)12167     public void setLayoutDirection(@LayoutDir int layoutDirection) {
12168         if (getRawLayoutDirection() != layoutDirection) {
12169             // Reset the current layout direction and the resolved one
12170             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
12171             resetRtlProperties();
12172             // Set the new layout direction (filtered)
12173             mPrivateFlags2 |=
12174                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
12175             // We need to resolve all RTL properties as they all depend on layout direction
12176             resolveRtlPropertiesIfNeeded();
12177             requestLayout();
12178             invalidate(true);
12179         }
12180     }
12181 
12182     /**
12183      * Returns the resolved layout direction for this view.
12184      *
12185      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
12186      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
12187      *
12188      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
12189      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
12190      *
12191      * @attr ref android.R.styleable#View_layoutDirection
12192      */
12193     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12194         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
12195         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
12196     })
12197     @InspectableProperty(enumMapping = {
12198             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12199             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
12200     })
12201     @ResolvedLayoutDir
getLayoutDirection()12202     public int getLayoutDirection() {
12203         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12204         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
12205             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12206             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
12207         }
12208         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
12209                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
12210     }
12211 
12212     /**
12213      * Indicates whether or not this view's layout is right-to-left. This is resolved from
12214      * layout attribute and/or the inherited value from the parent
12215      *
12216      * @return true if the layout is right-to-left.
12217      *
12218      * @hide
12219      */
12220     @ViewDebug.ExportedProperty(category = "layout")
12221     @UnsupportedAppUsage
isLayoutRtl()12222     public boolean isLayoutRtl() {
12223         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
12224     }
12225 
12226     /**
12227      * Indicates whether the view is currently tracking transient state that the
12228      * app should not need to concern itself with saving and restoring, but that
12229      * the framework should take special note to preserve when possible.
12230      *
12231      * <p>A view with transient state cannot be trivially rebound from an external
12232      * data source, such as an adapter binding item views in a list. This may be
12233      * because the view is performing an animation, tracking user selection
12234      * of content, or similar.</p>
12235      *
12236      * @return true if the view has transient state
12237      */
12238     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()12239     public boolean hasTransientState() {
12240         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
12241     }
12242 
12243     /**
12244      * Set whether this view is currently tracking transient state that the
12245      * framework should attempt to preserve when possible. This flag is reference counted,
12246      * so every call to setHasTransientState(true) should be paired with a later call
12247      * to setHasTransientState(false).
12248      *
12249      * <p>A view with transient state cannot be trivially rebound from an external
12250      * data source, such as an adapter binding item views in a list. This may be
12251      * because the view is performing an animation, tracking user selection
12252      * of content, or similar.</p>
12253      *
12254      * @param hasTransientState true if this view has transient state
12255      */
setHasTransientState(boolean hasTransientState)12256     public void setHasTransientState(boolean hasTransientState) {
12257         final boolean oldHasTransientState = hasTransientState();
12258         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
12259                 mTransientStateCount - 1;
12260         if (mTransientStateCount < 0) {
12261             mTransientStateCount = 0;
12262             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
12263                     "unmatched pair of setHasTransientState calls");
12264         } else if ((hasTransientState && mTransientStateCount == 1) ||
12265                 (!hasTransientState && mTransientStateCount == 0)) {
12266             // update flag if we've just incremented up from 0 or decremented down to 0
12267             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
12268                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
12269             final boolean newHasTransientState = hasTransientState();
12270             if (mParent != null && newHasTransientState != oldHasTransientState) {
12271                 try {
12272                     mParent.childHasTransientStateChanged(this, newHasTransientState);
12273                 } catch (AbstractMethodError e) {
12274                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12275                             " does not fully implement ViewParent", e);
12276                 }
12277             }
12278         }
12279     }
12280 
12281     /**
12282      * Set the view is tracking translation transient state. This flag is used to check if the view
12283      * need to call setHasTransientState(false) to reset transient state that set when starting
12284      * translation.
12285      *
12286      * @param hasTranslationTransientState true if this view has translation transient state
12287      * @hide
12288      */
setHasTranslationTransientState(boolean hasTranslationTransientState)12289     public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
12290         if (hasTranslationTransientState) {
12291             mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12292         } else {
12293             mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12294         }
12295     }
12296 
12297     /**
12298      * @hide
12299      */
hasTranslationTransientState()12300     public boolean hasTranslationTransientState() {
12301         return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
12302                 == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
12303     }
12304 
12305     /**
12306      * Returns true if this view is currently attached to a window.
12307      */
isAttachedToWindow()12308     public boolean isAttachedToWindow() {
12309         return mAttachInfo != null;
12310     }
12311 
12312     /**
12313      * Returns true if this view has been through at least one layout since it
12314      * was last attached to or detached from a window.
12315      */
isLaidOut()12316     public boolean isLaidOut() {
12317         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
12318     }
12319 
12320     /**
12321      * @return {@code true} if laid-out and not about to do another layout.
12322      */
isLayoutValid()12323     boolean isLayoutValid() {
12324         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
12325     }
12326 
12327     /**
12328      * If this view doesn't do any drawing on its own, set this flag to
12329      * allow further optimizations. By default, this flag is not set on
12330      * View, but could be set on some View subclasses such as ViewGroup.
12331      *
12332      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
12333      * you should clear this flag.
12334      *
12335      * @param willNotDraw whether or not this View draw on its own
12336      */
setWillNotDraw(boolean willNotDraw)12337     public void setWillNotDraw(boolean willNotDraw) {
12338         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
12339     }
12340 
12341     /**
12342      * Returns whether or not this View draws on its own.
12343      *
12344      * @return true if this view has nothing to draw, false otherwise
12345      */
12346     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()12347     public boolean willNotDraw() {
12348         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
12349     }
12350 
12351     /**
12352      * When a View's drawing cache is enabled, drawing is redirected to an
12353      * offscreen bitmap. Some views, like an ImageView, must be able to
12354      * bypass this mechanism if they already draw a single bitmap, to avoid
12355      * unnecessary usage of the memory.
12356      *
12357      * @param willNotCacheDrawing true if this view does not cache its
12358      *        drawing, false otherwise
12359      *
12360      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12361      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12362      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12363      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12364      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12365      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12366      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12367      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12368      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12369      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12370      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12371      * reports or unit testing the {@link PixelCopy} API is recommended.
12372      */
12373     @Deprecated
setWillNotCacheDrawing(boolean willNotCacheDrawing)12374     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
12375         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
12376     }
12377 
12378     /**
12379      * Returns whether or not this View can cache its drawing or not.
12380      *
12381      * @return true if this view does not cache its 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     @ViewDebug.ExportedProperty(category = "drawing")
12397     @Deprecated
willNotCacheDrawing()12398     public boolean willNotCacheDrawing() {
12399         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
12400     }
12401 
12402     /**
12403      * Indicates whether this view reacts to click events or not.
12404      *
12405      * @return true if the view is clickable, false otherwise
12406      *
12407      * @see #setClickable(boolean)
12408      * @attr ref android.R.styleable#View_clickable
12409      */
12410     @ViewDebug.ExportedProperty
12411     @InspectableProperty
isClickable()12412     public boolean isClickable() {
12413         return (mViewFlags & CLICKABLE) == CLICKABLE;
12414     }
12415 
12416     /**
12417      * Enables or disables click events for this view. When a view
12418      * is clickable it will change its state to "pressed" on every click.
12419      * Subclasses should set the view clickable to visually react to
12420      * user's clicks.
12421      *
12422      * @param clickable true to make the view clickable, false otherwise
12423      *
12424      * @see #isClickable()
12425      * @attr ref android.R.styleable#View_clickable
12426      */
setClickable(boolean clickable)12427     public void setClickable(boolean clickable) {
12428         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
12429     }
12430 
12431     /**
12432      * Enables or disables click events for this view when disabled.
12433      *
12434      * @param clickableWhenDisabled true to make the view clickable, false otherwise
12435      *
12436      * @attr ref android.R.styleable#View_allowClickWhenDisabled
12437      */
setAllowClickWhenDisabled(boolean clickableWhenDisabled)12438     public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
12439         if (clickableWhenDisabled) {
12440             mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
12441         } else {
12442             mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
12443         }
12444     }
12445 
12446     /**
12447      * Indicates whether this view reacts to long click events or not.
12448      *
12449      * @return true if the view is long clickable, false otherwise
12450      *
12451      * @see #setLongClickable(boolean)
12452      * @attr ref android.R.styleable#View_longClickable
12453      */
12454     @InspectableProperty
isLongClickable()12455     public boolean isLongClickable() {
12456         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12457     }
12458 
12459     /**
12460      * Enables or disables long click events for this view. When a view is long
12461      * clickable it reacts to the user holding down the button for a longer
12462      * duration than a tap. This event can either launch the listener or a
12463      * context menu.
12464      *
12465      * @param longClickable true to make the view long clickable, false otherwise
12466      * @see #isLongClickable()
12467      * @attr ref android.R.styleable#View_longClickable
12468      */
setLongClickable(boolean longClickable)12469     public void setLongClickable(boolean longClickable) {
12470         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
12471     }
12472 
12473     /**
12474      * Indicates whether this view reacts to context clicks or not.
12475      *
12476      * @return true if the view is context clickable, false otherwise
12477      * @see #setContextClickable(boolean)
12478      * @attr ref android.R.styleable#View_contextClickable
12479      */
12480     @InspectableProperty
isContextClickable()12481     public boolean isContextClickable() {
12482         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12483     }
12484 
12485     /**
12486      * Enables or disables context clicking for this view. This event can launch the listener.
12487      *
12488      * @param contextClickable true to make the view react to a context click, false otherwise
12489      * @see #isContextClickable()
12490      * @attr ref android.R.styleable#View_contextClickable
12491      */
setContextClickable(boolean contextClickable)12492     public void setContextClickable(boolean contextClickable) {
12493         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
12494     }
12495 
12496     /**
12497      * Sets the pressed state for this view and provides a touch coordinate for
12498      * animation hinting.
12499      *
12500      * @param pressed Pass true to set the View's internal state to "pressed",
12501      *            or false to reverts the View's internal state from a
12502      *            previously set "pressed" state.
12503      * @param x The x coordinate of the touch that caused the press
12504      * @param y The y coordinate of the touch that caused the press
12505      */
setPressed(boolean pressed, float x, float y)12506     private void setPressed(boolean pressed, float x, float y) {
12507         if (pressed) {
12508             drawableHotspotChanged(x, y);
12509         }
12510 
12511         setPressed(pressed);
12512     }
12513 
12514     /**
12515      * Sets the pressed state for this view.
12516      *
12517      * @see #isClickable()
12518      * @see #setClickable(boolean)
12519      *
12520      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
12521      *        the View's internal state from a previously set "pressed" state.
12522      */
setPressed(boolean pressed)12523     public void setPressed(boolean pressed) {
12524         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
12525 
12526         if (pressed) {
12527             mPrivateFlags |= PFLAG_PRESSED;
12528         } else {
12529             mPrivateFlags &= ~PFLAG_PRESSED;
12530         }
12531 
12532         if (needsRefresh) {
12533             refreshDrawableState();
12534         }
12535         dispatchSetPressed(pressed);
12536     }
12537 
12538     /**
12539      * Dispatch setPressed to all of this View's children.
12540      *
12541      * @see #setPressed(boolean)
12542      *
12543      * @param pressed The new pressed state
12544      */
dispatchSetPressed(boolean pressed)12545     protected void dispatchSetPressed(boolean pressed) {
12546     }
12547 
12548     /**
12549      * Indicates whether the view is currently in pressed state. Unless
12550      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
12551      * the pressed state.
12552      *
12553      * @see #setPressed(boolean)
12554      * @see #isClickable()
12555      * @see #setClickable(boolean)
12556      *
12557      * @return true if the view is currently pressed, false otherwise
12558      */
12559     @ViewDebug.ExportedProperty
12560     @InspectableProperty(hasAttributeId = false)
isPressed()12561     public boolean isPressed() {
12562         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
12563     }
12564 
12565     /**
12566      * @hide
12567      * Indicates whether this view will participate in data collection through
12568      * {@link ViewStructure}.  If true, it will not provide any data
12569      * for itself or its children.  If false, the normal data collection will be allowed.
12570      *
12571      * @return Returns false if assist data collection is not blocked, else true.
12572      *
12573      * @see #setAssistBlocked(boolean)
12574      * @attr ref android.R.styleable#View_assistBlocked
12575      */
isAssistBlocked()12576     public boolean isAssistBlocked() {
12577         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
12578     }
12579 
12580     /**
12581      * @hide
12582      * Controls whether assist data collection from this view and its children is enabled
12583      * (that is, whether {@link #onProvideStructure} and
12584      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
12585      * allowing normal assist collection.  Setting this to false will disable assist collection.
12586      *
12587      * @param enabled Set to true to <em>disable</em> assist data collection, or false
12588      * (the default) to allow it.
12589      *
12590      * @see #isAssistBlocked()
12591      * @see #onProvideStructure
12592      * @see #onProvideVirtualStructure
12593      * @attr ref android.R.styleable#View_assistBlocked
12594      */
12595     @UnsupportedAppUsage
setAssistBlocked(boolean enabled)12596     public void setAssistBlocked(boolean enabled) {
12597         if (enabled) {
12598             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
12599         } else {
12600             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
12601         }
12602     }
12603 
12604     /**
12605      * Indicates whether this view will save its state (that is,
12606      * whether its {@link #onSaveInstanceState} method will be called).
12607      *
12608      * @return Returns true if the view state saving is enabled, else false.
12609      *
12610      * @see #setSaveEnabled(boolean)
12611      * @attr ref android.R.styleable#View_saveEnabled
12612      */
12613     @InspectableProperty
isSaveEnabled()12614     public boolean isSaveEnabled() {
12615         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
12616     }
12617 
12618     /**
12619      * Controls whether the saving of this view's state is
12620      * enabled (that is, whether its {@link #onSaveInstanceState} method
12621      * will be called).  Note that even if freezing is enabled, the
12622      * view still must have an id assigned to it (via {@link #setId(int)})
12623      * for its state to be saved.  This flag can only disable the
12624      * saving of this view; any child views may still have their state saved.
12625      *
12626      * @param enabled Set to false to <em>disable</em> state saving, or true
12627      * (the default) to allow it.
12628      *
12629      * @see #isSaveEnabled()
12630      * @see #setId(int)
12631      * @see #onSaveInstanceState()
12632      * @attr ref android.R.styleable#View_saveEnabled
12633      */
setSaveEnabled(boolean enabled)12634     public void setSaveEnabled(boolean enabled) {
12635         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
12636     }
12637 
12638     /**
12639      * Gets whether the framework should discard touches when the view's
12640      * window is obscured by another visible window.
12641      * Refer to the {@link View} security documentation for more details.
12642      *
12643      * @return True if touch filtering is enabled.
12644      *
12645      * @see #setFilterTouchesWhenObscured(boolean)
12646      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12647      */
12648     @ViewDebug.ExportedProperty
12649     @InspectableProperty
getFilterTouchesWhenObscured()12650     public boolean getFilterTouchesWhenObscured() {
12651         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
12652     }
12653 
12654     /**
12655      * Sets whether the framework should discard touches when the view's
12656      * window is obscured by another visible window.
12657      * Refer to the {@link View} security documentation for more details.
12658      *
12659      * @param enabled True if touch filtering should be enabled.
12660      *
12661      * @see #getFilterTouchesWhenObscured
12662      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12663      */
setFilterTouchesWhenObscured(boolean enabled)12664     public void setFilterTouchesWhenObscured(boolean enabled) {
12665         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
12666                 FILTER_TOUCHES_WHEN_OBSCURED);
12667     }
12668 
12669     /**
12670      * Indicates whether the entire hierarchy under this view will save its
12671      * state when a state saving traversal occurs from its parent.  The default
12672      * is true; if false, these views will not be saved unless
12673      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12674      *
12675      * @return Returns true if the view state saving from parent is enabled, else false.
12676      *
12677      * @see #setSaveFromParentEnabled(boolean)
12678      */
isSaveFromParentEnabled()12679     public boolean isSaveFromParentEnabled() {
12680         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
12681     }
12682 
12683     /**
12684      * Controls whether the entire hierarchy under this view will save its
12685      * state when a state saving traversal occurs from its parent.  The default
12686      * is true; if false, these views will not be saved unless
12687      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12688      *
12689      * @param enabled Set to false to <em>disable</em> state saving, or true
12690      * (the default) to allow it.
12691      *
12692      * @see #isSaveFromParentEnabled()
12693      * @see #setId(int)
12694      * @see #onSaveInstanceState()
12695      */
setSaveFromParentEnabled(boolean enabled)12696     public void setSaveFromParentEnabled(boolean enabled) {
12697         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
12698     }
12699 
12700 
12701     /**
12702      * Returns whether this View is currently able to take focus.
12703      *
12704      * @return True if this view can take focus, or false otherwise.
12705      */
12706     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()12707     public final boolean isFocusable() {
12708         return FOCUSABLE == (mViewFlags & FOCUSABLE);
12709     }
12710 
12711     /**
12712      * Returns the focusable setting for this view.
12713      *
12714      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
12715      * @attr ref android.R.styleable#View_focusable
12716      */
12717     @ViewDebug.ExportedProperty(mapping = {
12718             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
12719             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
12720             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
12721             }, category = "focus")
12722     @InspectableProperty(enumMapping = {
12723             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
12724             @EnumEntry(value = FOCUSABLE, name = "true"),
12725             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
12726     })
12727     @Focusable
getFocusable()12728     public int getFocusable() {
12729         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
12730     }
12731 
12732     /**
12733      * When a view is focusable, it may not want to take focus when in touch mode.
12734      * For example, a button would like focus when the user is navigating via a D-pad
12735      * so that the user can click on it, but once the user starts touching the screen,
12736      * the button shouldn't take focus
12737      * @return Whether the view is focusable in touch mode.
12738      * @attr ref android.R.styleable#View_focusableInTouchMode
12739      */
12740     @ViewDebug.ExportedProperty(category = "focus")
12741     @InspectableProperty
isFocusableInTouchMode()12742     public final boolean isFocusableInTouchMode() {
12743         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
12744     }
12745 
12746     /**
12747      * Returns whether the view should be treated as a focusable unit by screen reader
12748      * accessibility tools.
12749      * @see #setScreenReaderFocusable(boolean)
12750      *
12751      * @return Whether the view should be treated as a focusable unit by screen reader.
12752      *
12753      * @attr ref android.R.styleable#View_screenReaderFocusable
12754      */
12755     @InspectableProperty
isScreenReaderFocusable()12756     public boolean isScreenReaderFocusable() {
12757         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
12758     }
12759 
12760     /**
12761      * Sets whether this View should be a focusable element for screen readers
12762      * and include non-focusable Views from its subtree when providing feedback.
12763      * <p>
12764      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
12765      * but does not impact input focus behavior.
12766      *
12767      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
12768      *                              accessibility tools.
12769      *
12770      * @attr ref android.R.styleable#View_screenReaderFocusable
12771      */
setScreenReaderFocusable(boolean screenReaderFocusable)12772     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
12773         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
12774     }
12775 
12776     /**
12777      * Gets whether this view is a heading for accessibility purposes.
12778      *
12779      * @return {@code true} if the view is a heading, {@code false} otherwise.
12780      *
12781      * @attr ref android.R.styleable#View_accessibilityHeading
12782      */
12783     @InspectableProperty
isAccessibilityHeading()12784     public boolean isAccessibilityHeading() {
12785         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
12786     }
12787 
12788     /**
12789      * Set if view is a heading for a section of content for accessibility purposes.
12790      *
12791      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
12792      *
12793      * @attr ref android.R.styleable#View_accessibilityHeading
12794      */
setAccessibilityHeading(boolean isHeading)12795     public void setAccessibilityHeading(boolean isHeading) {
12796         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
12797     }
12798 
updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue)12799     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
12800         int pflags3 = mPrivateFlags3;
12801         if (newValue) {
12802             pflags3 |= mask;
12803         } else {
12804             pflags3 &= ~mask;
12805         }
12806 
12807         if (pflags3 != mPrivateFlags3) {
12808             mPrivateFlags3 = pflags3;
12809             notifyViewAccessibilityStateChangedIfNeeded(
12810                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12811         }
12812     }
12813 
12814     /**
12815      * Find the nearest view in the specified direction that can take focus.
12816      * This does not actually give focus to that view.
12817      *
12818      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12819      *
12820      * @return The nearest focusable in the specified direction, or null if none
12821      *         can be found.
12822      */
focusSearch(@ocusRealDirection int direction)12823     public View focusSearch(@FocusRealDirection int direction) {
12824         if (mParent != null) {
12825             return mParent.focusSearch(this, direction);
12826         } else {
12827             return null;
12828         }
12829     }
12830 
12831     /**
12832      * Returns whether this View is a root of a keyboard navigation cluster.
12833      *
12834      * @return True if this view is a root of a cluster, or false otherwise.
12835      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12836      */
12837     @ViewDebug.ExportedProperty(category = "focus")
12838     @InspectableProperty
isKeyboardNavigationCluster()12839     public final boolean isKeyboardNavigationCluster() {
12840         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
12841     }
12842 
12843     /**
12844      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
12845      * will be ignored.
12846      *
12847      * @return the keyboard navigation cluster that this view is in (can be this view)
12848      *         or {@code null} if not in one
12849      */
findKeyboardNavigationCluster()12850     View findKeyboardNavigationCluster() {
12851         if (mParent instanceof View) {
12852             View cluster = ((View) mParent).findKeyboardNavigationCluster();
12853             if (cluster != null) {
12854                 return cluster;
12855             } else if (isKeyboardNavigationCluster()) {
12856                 return this;
12857             }
12858         }
12859         return null;
12860     }
12861 
12862     /**
12863      * Set whether this view is a root of a keyboard navigation cluster.
12864      *
12865      * @param isCluster If true, this view is a root of a cluster.
12866      *
12867      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12868      */
setKeyboardNavigationCluster(boolean isCluster)12869     public void setKeyboardNavigationCluster(boolean isCluster) {
12870         if (isCluster) {
12871             mPrivateFlags3 |= PFLAG3_CLUSTER;
12872         } else {
12873             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
12874         }
12875     }
12876 
12877     /**
12878      * Sets this View as the one which receives focus the next time cluster navigation jumps
12879      * to the cluster containing this View. This does NOT change focus even if the cluster
12880      * containing this view is current.
12881      *
12882      * @hide
12883      */
12884     @TestApi
setFocusedInCluster()12885     public final void setFocusedInCluster() {
12886         setFocusedInCluster(findKeyboardNavigationCluster());
12887     }
12888 
setFocusedInCluster(View cluster)12889     private void setFocusedInCluster(View cluster) {
12890         if (this instanceof ViewGroup) {
12891             ((ViewGroup) this).mFocusedInCluster = null;
12892         }
12893         if (cluster == this) {
12894             return;
12895         }
12896         ViewParent parent = mParent;
12897         View child = this;
12898         while (parent instanceof ViewGroup) {
12899             ((ViewGroup) parent).mFocusedInCluster = child;
12900             if (parent == cluster) {
12901                 break;
12902             }
12903             child = (View) parent;
12904             parent = parent.getParent();
12905         }
12906     }
12907 
updateFocusedInCluster(View oldFocus, @FocusDirection int direction)12908     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
12909         if (oldFocus != null) {
12910             View oldCluster = oldFocus.findKeyboardNavigationCluster();
12911             View cluster = findKeyboardNavigationCluster();
12912             if (oldCluster != cluster) {
12913                 // Going from one cluster to another, so save last-focused.
12914                 // This covers cluster jumps because they are always FOCUS_DOWN
12915                 oldFocus.setFocusedInCluster(oldCluster);
12916                 if (!(oldFocus.mParent instanceof ViewGroup)) {
12917                     return;
12918                 }
12919                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
12920                     // This is a result of ordered navigation so consider navigation through
12921                     // the previous cluster "complete" and clear its last-focused memory.
12922                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12923                 } else if (oldFocus instanceof ViewGroup
12924                         && ((ViewGroup) oldFocus).getDescendantFocusability()
12925                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
12926                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
12927                     // This means oldFocus is not focusable since it obviously has a focusable
12928                     // child (this). Don't restore focus to it in the future.
12929                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12930                 }
12931             }
12932         }
12933     }
12934 
12935     /**
12936      * Returns whether this View should receive focus when the focus is restored for the view
12937      * hierarchy containing this view.
12938      * <p>
12939      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12940      * window or serves as a target of cluster navigation.
12941      *
12942      * @see #restoreDefaultFocus()
12943      *
12944      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
12945      * @attr ref android.R.styleable#View_focusedByDefault
12946      */
12947     @ViewDebug.ExportedProperty(category = "focus")
12948     @InspectableProperty
isFocusedByDefault()12949     public final boolean isFocusedByDefault() {
12950         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
12951     }
12952 
12953     /**
12954      * Sets whether this View should receive focus when the focus is restored for the view
12955      * hierarchy containing this view.
12956      * <p>
12957      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12958      * window or serves as a target of cluster navigation.
12959      *
12960      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
12961      *                           {@code false} otherwise.
12962      *
12963      * @see #restoreDefaultFocus()
12964      *
12965      * @attr ref android.R.styleable#View_focusedByDefault
12966      */
12967     @RemotableViewMethod
setFocusedByDefault(boolean isFocusedByDefault)12968     public void setFocusedByDefault(boolean isFocusedByDefault) {
12969         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
12970             return;
12971         }
12972 
12973         if (isFocusedByDefault) {
12974             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
12975         } else {
12976             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
12977         }
12978 
12979         if (mParent instanceof ViewGroup) {
12980             if (isFocusedByDefault) {
12981                 ((ViewGroup) mParent).setDefaultFocus(this);
12982             } else {
12983                 ((ViewGroup) mParent).clearDefaultFocus(this);
12984             }
12985         }
12986     }
12987 
12988     /**
12989      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
12990      *
12991      * @return {@code true} if this view has default focus, {@code false} otherwise
12992      */
hasDefaultFocus()12993     boolean hasDefaultFocus() {
12994         return isFocusedByDefault();
12995     }
12996 
12997     /**
12998      * Find the nearest keyboard navigation cluster in the specified direction.
12999      * This does not actually give focus to that cluster.
13000      *
13001      * @param currentCluster The starting point of the search. Null means the current cluster is not
13002      *                       found yet
13003      * @param direction Direction to look
13004      *
13005      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
13006      *         can be found
13007      */
keyboardNavigationClusterSearch(View currentCluster, @FocusDirection int direction)13008     public View keyboardNavigationClusterSearch(View currentCluster,
13009             @FocusDirection int direction) {
13010         if (isKeyboardNavigationCluster()) {
13011             currentCluster = this;
13012         }
13013         if (isRootNamespace()) {
13014             // Root namespace means we should consider ourselves the top of the
13015             // tree for group searching; otherwise we could be group searching
13016             // into other tabs.  see LocalActivityManager and TabHost for more info.
13017             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
13018                     this, currentCluster, direction);
13019         } else if (mParent != null) {
13020             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
13021         }
13022         return null;
13023     }
13024 
13025     /**
13026      * This method is the last chance for the focused view and its ancestors to
13027      * respond to an arrow key. This is called when the focused view did not
13028      * consume the key internally, nor could the view system find a new view in
13029      * the requested direction to give focus to.
13030      *
13031      * @param focused The currently focused view.
13032      * @param direction The direction focus wants to move. One of FOCUS_UP,
13033      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
13034      * @return True if the this view consumed this unhandled move.
13035      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)13036     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
13037         return false;
13038     }
13039 
13040     /**
13041      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
13042      * have {@link android.R.attr#state_focused} defined in its background.
13043      *
13044      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
13045      *                                      highlight, {@code false} otherwise.
13046      *
13047      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
13048      */
setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled)13049     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
13050         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
13051     }
13052 
13053     /**
13054 
13055     /**
13056      * Returns whether this View should use a default focus highlight when it gets focused but
13057      * doesn't have {@link android.R.attr#state_focused} defined in its background.
13058      *
13059      * @return True if this View should use a default focus highlight.
13060      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
13061      */
13062     @ViewDebug.ExportedProperty(category = "focus")
13063     @InspectableProperty
getDefaultFocusHighlightEnabled()13064     public final boolean getDefaultFocusHighlightEnabled() {
13065         return mDefaultFocusHighlightEnabled;
13066     }
13067 
13068     /**
13069      * If a user manually specified the next view id for a particular direction,
13070      * use the root to look up the view.
13071      * @param root The root view of the hierarchy containing this view.
13072      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
13073      * or FOCUS_BACKWARD.
13074      * @return The user specified next view, or null if there is none.
13075      */
findUserSetNextFocus(View root, @FocusDirection int direction)13076     View findUserSetNextFocus(View root, @FocusDirection int direction) {
13077         switch (direction) {
13078             case FOCUS_LEFT:
13079                 if (mNextFocusLeftId == View.NO_ID) return null;
13080                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
13081             case FOCUS_RIGHT:
13082                 if (mNextFocusRightId == View.NO_ID) return null;
13083                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
13084             case FOCUS_UP:
13085                 if (mNextFocusUpId == View.NO_ID) return null;
13086                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
13087             case FOCUS_DOWN:
13088                 if (mNextFocusDownId == View.NO_ID) return null;
13089                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
13090             case FOCUS_FORWARD:
13091                 if (mNextFocusForwardId == View.NO_ID) return null;
13092                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
13093             case FOCUS_BACKWARD: {
13094                 if (mID == View.NO_ID) return null;
13095                 final View rootView = root;
13096                 final View startView = this;
13097                 // Since we have forward links but no backward links, we need to find the view that
13098                 // forward links to this view. We can't just find the view with the specified ID
13099                 // because view IDs need not be unique throughout the tree.
13100                 return root.findViewByPredicateInsideOut(startView,
13101                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
13102                             == startView);
13103             }
13104         }
13105         return null;
13106     }
13107 
13108     /**
13109      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
13110      * use the root to look up the view.
13111      *
13112      * @param root the root view of the hierarchy containing this view
13113      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
13114      * @return the user-specified next cluster, or {@code null} if there is none
13115      */
findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction)13116     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
13117         switch (direction) {
13118             case FOCUS_FORWARD:
13119                 if (mNextClusterForwardId == View.NO_ID) return null;
13120                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
13121             case FOCUS_BACKWARD: {
13122                 if (mID == View.NO_ID) return null;
13123                 final int id = mID;
13124                 return root.findViewByPredicateInsideOut(this,
13125                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
13126             }
13127         }
13128         return null;
13129     }
13130 
findViewInsideOutShouldExist(View root, int id)13131     private View findViewInsideOutShouldExist(View root, int id) {
13132         return findViewInsideOutShouldExist(root, this, id);
13133     }
13134 
findViewInsideOutShouldExist(View root, View start, int id)13135     private View findViewInsideOutShouldExist(View root, View start, int id) {
13136         if (mMatchIdPredicate == null) {
13137             mMatchIdPredicate = new MatchIdPredicate();
13138         }
13139         mMatchIdPredicate.mId = id;
13140         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
13141         if (result == null) {
13142             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
13143         }
13144         return result;
13145     }
13146 
13147     /**
13148      * Find and return all focusable views that are descendants of this view,
13149      * possibly including this view if it is focusable itself.
13150      *
13151      * @param direction The direction of the focus
13152      * @return A list of focusable views
13153      */
getFocusables(@ocusDirection int direction)13154     public ArrayList<View> getFocusables(@FocusDirection int direction) {
13155         ArrayList<View> result = new ArrayList<View>(24);
13156         addFocusables(result, direction);
13157         return result;
13158     }
13159 
13160     /**
13161      * Add any focusable views that are descendants of this view (possibly
13162      * including this view if it is focusable itself) to views.  If we are in touch mode,
13163      * only add views that are also focusable in touch mode.
13164      *
13165      * @param views Focusable views found so far
13166      * @param direction The direction of the focus
13167      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)13168     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
13169         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
13170     }
13171 
13172     /**
13173      * Adds any focusable views that are descendants of this view (possibly
13174      * including this view if it is focusable itself) to views. This method
13175      * adds all focusable views regardless if we are in touch mode or
13176      * only views focusable in touch mode if we are in touch mode or
13177      * only views that can take accessibility focus if accessibility is enabled
13178      * depending on the focusable mode parameter.
13179      *
13180      * @param views Focusable views found so far or null if all we are interested is
13181      *        the number of focusables.
13182      * @param direction The direction of the focus.
13183      * @param focusableMode The type of focusables to be added.
13184      *
13185      * @see #FOCUSABLES_ALL
13186      * @see #FOCUSABLES_TOUCH_MODE
13187      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)13188     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
13189             @FocusableMode int focusableMode) {
13190         if (views == null) {
13191             return;
13192         }
13193         if (!canTakeFocus()) {
13194             return;
13195         }
13196         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
13197                 && !isFocusableInTouchMode()) {
13198             return;
13199         }
13200         views.add(this);
13201     }
13202 
13203     /**
13204      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
13205      * including this view if it is a cluster root itself) to views.
13206      *
13207      * @param views Keyboard navigation cluster roots found so far
13208      * @param direction Direction to look
13209      */
addKeyboardNavigationClusters( @onNull Collection<View> views, int direction)13210     public void addKeyboardNavigationClusters(
13211             @NonNull Collection<View> views,
13212             int direction) {
13213         if (!isKeyboardNavigationCluster()) {
13214             return;
13215         }
13216         if (!hasFocusable()) {
13217             return;
13218         }
13219         views.add(this);
13220     }
13221 
13222     /**
13223      * Finds the Views that contain given text. The containment is case insensitive.
13224      * The search is performed by either the text that the View renders or the content
13225      * description that describes the view for accessibility purposes and the view does
13226      * not render or both. Clients can specify how the search is to be performed via
13227      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
13228      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
13229      *
13230      * @param outViews The output list of matching Views.
13231      * @param searched The text to match against.
13232      *
13233      * @see #FIND_VIEWS_WITH_TEXT
13234      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
13235      * @see #setContentDescription(CharSequence)
13236      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)13237     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
13238             @FindViewFlags int flags) {
13239         if (getAccessibilityNodeProvider() != null) {
13240             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
13241                 outViews.add(this);
13242             }
13243         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
13244                 && (searched != null && searched.length() > 0)
13245                 && (mContentDescription != null && mContentDescription.length() > 0)) {
13246             String searchedLowerCase = searched.toString().toLowerCase();
13247             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
13248             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
13249                 outViews.add(this);
13250             }
13251         }
13252     }
13253 
13254     /**
13255      * Find and return all touchable views that are descendants of this view,
13256      * possibly including this view if it is touchable itself.
13257      *
13258      * @return A list of touchable views
13259      */
getTouchables()13260     public ArrayList<View> getTouchables() {
13261         ArrayList<View> result = new ArrayList<View>();
13262         addTouchables(result);
13263         return result;
13264     }
13265 
13266     /**
13267      * Add any touchable views that are descendants of this view (possibly
13268      * including this view if it is touchable itself) to views.
13269      *
13270      * @param views Touchable views found so far
13271      */
addTouchables(ArrayList<View> views)13272     public void addTouchables(ArrayList<View> views) {
13273         final int viewFlags = mViewFlags;
13274 
13275         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
13276                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
13277                 && (viewFlags & ENABLED_MASK) == ENABLED) {
13278             views.add(this);
13279         }
13280     }
13281 
13282     /**
13283      * Returns whether this View is accessibility focused.
13284      *
13285      * @return True if this View is accessibility focused.
13286      */
13287     @InspectableProperty(hasAttributeId = false)
isAccessibilityFocused()13288     public boolean isAccessibilityFocused() {
13289         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
13290     }
13291 
13292     /**
13293      * Call this to try to give accessibility focus to this view.
13294      *
13295      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
13296      * returns false or the view is no visible or the view already has accessibility
13297      * focus.
13298      *
13299      * See also {@link #focusSearch(int)}, which is what you call to say that you
13300      * have focus, and you want your parent to look for the next one.
13301      *
13302      * @return Whether this view actually took accessibility focus.
13303      *
13304      * @hide
13305      */
13306     @UnsupportedAppUsage
requestAccessibilityFocus()13307     public boolean requestAccessibilityFocus() {
13308         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
13309         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
13310             return false;
13311         }
13312         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
13313             return false;
13314         }
13315         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
13316             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
13317             ViewRootImpl viewRootImpl = getViewRootImpl();
13318             if (viewRootImpl != null) {
13319                 viewRootImpl.setAccessibilityFocus(this, null);
13320             }
13321             invalidate();
13322             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
13323             return true;
13324         }
13325         return false;
13326     }
13327 
13328     /**
13329      * Call this to try to clear accessibility focus of this view.
13330      *
13331      * See also {@link #focusSearch(int)}, which is what you call to say that you
13332      * have focus, and you want your parent to look for the next one.
13333      *
13334      * @hide
13335      */
13336     @UnsupportedAppUsage
clearAccessibilityFocus()13337     public void clearAccessibilityFocus() {
13338         clearAccessibilityFocusNoCallbacks(0);
13339 
13340         // Clear the global reference of accessibility focus if this view or
13341         // any of its descendants had accessibility focus. This will NOT send
13342         // an event or update internal state if focus is cleared from a
13343         // descendant view, which may leave views in inconsistent states.
13344         final ViewRootImpl viewRootImpl = getViewRootImpl();
13345         if (viewRootImpl != null) {
13346             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
13347             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13348                 viewRootImpl.setAccessibilityFocus(null, null);
13349             }
13350         }
13351     }
13352 
sendAccessibilityHoverEvent(int eventType)13353     private void sendAccessibilityHoverEvent(int eventType) {
13354         // Since we are not delivering to a client accessibility events from not
13355         // important views (unless the clinet request that) we need to fire the
13356         // event from the deepest view exposed to the client. As a consequence if
13357         // the user crosses a not exposed view the client will see enter and exit
13358         // of the exposed predecessor followed by and enter and exit of that same
13359         // predecessor when entering and exiting the not exposed descendant. This
13360         // is fine since the client has a clear idea which view is hovered at the
13361         // price of a couple more events being sent. This is a simple and
13362         // working solution.
13363         View source = this;
13364         while (true) {
13365             if (source.includeForAccessibility()) {
13366                 source.sendAccessibilityEvent(eventType);
13367                 return;
13368             }
13369             ViewParent parent = source.getParent();
13370             if (parent instanceof View) {
13371                 source = (View) parent;
13372             } else {
13373                 return;
13374             }
13375         }
13376     }
13377 
13378     /**
13379      * Clears accessibility focus without calling any callback methods
13380      * normally invoked in {@link #clearAccessibilityFocus()}. This method
13381      * is used separately from that one for clearing accessibility focus when
13382      * giving this focus to another view.
13383      *
13384      * @param action The action, if any, that led to focus being cleared. Set to
13385      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
13386      * the window.
13387      */
clearAccessibilityFocusNoCallbacks(int action)13388     void clearAccessibilityFocusNoCallbacks(int action) {
13389         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
13390             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
13391             invalidate();
13392             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13393                 AccessibilityEvent event = AccessibilityEvent.obtain(
13394                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
13395                 event.setAction(action);
13396                 if (mAccessibilityDelegate != null) {
13397                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
13398                 } else {
13399                     sendAccessibilityEventUnchecked(event);
13400                 }
13401             }
13402         }
13403     }
13404 
13405     /**
13406      * Call this to try to give focus to a specific view or to one of its
13407      * descendants.
13408      *
13409      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13410      * false), or if it can't be focused due to other conditions (not focusable in touch mode
13411      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
13412      * enabled, or has no size).
13413      *
13414      * See also {@link #focusSearch(int)}, which is what you call to say that you
13415      * have focus, and you want your parent to look for the next one.
13416      *
13417      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
13418      * {@link #FOCUS_DOWN} and <code>null</code>.
13419      *
13420      * @return Whether this view or one of its descendants actually took focus.
13421      */
requestFocus()13422     public final boolean requestFocus() {
13423         return requestFocus(View.FOCUS_DOWN);
13424     }
13425 
13426     /**
13427      * This will request focus for whichever View was last focused within this
13428      * cluster before a focus-jump out of it.
13429      *
13430      * @hide
13431      */
13432     @TestApi
restoreFocusInCluster(@ocusRealDirection int direction)13433     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
13434         // Prioritize focusableByDefault over algorithmic focus selection.
13435         if (restoreDefaultFocus()) {
13436             return true;
13437         }
13438         return requestFocus(direction);
13439     }
13440 
13441     /**
13442      * This will request focus for whichever View not in a cluster was last focused before a
13443      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
13444      * the "first" focusable view it finds.
13445      *
13446      * @hide
13447      */
13448     @TestApi
restoreFocusNotInCluster()13449     public boolean restoreFocusNotInCluster() {
13450         return requestFocus(View.FOCUS_DOWN);
13451     }
13452 
13453     /**
13454      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
13455      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
13456      *
13457      * @return Whether this view or one of its descendants actually took focus
13458      */
restoreDefaultFocus()13459     public boolean restoreDefaultFocus() {
13460         return requestFocus(View.FOCUS_DOWN);
13461     }
13462 
13463     /**
13464      * Call this to try to give focus to a specific view or to one of its
13465      * descendants and give it a hint about what direction focus is heading.
13466      *
13467      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13468      * false), or if it is focusable and it is not focusable in touch mode
13469      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13470      *
13471      * See also {@link #focusSearch(int)}, which is what you call to say that you
13472      * have focus, and you want your parent to look for the next one.
13473      *
13474      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
13475      * <code>null</code> set for the previously focused rectangle.
13476      *
13477      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13478      * @return Whether this view or one of its descendants actually took focus.
13479      */
requestFocus(int direction)13480     public final boolean requestFocus(int direction) {
13481         return requestFocus(direction, null);
13482     }
13483 
13484     /**
13485      * Call this to try to give focus to a specific view or to one of its descendants
13486      * and give it hints about the direction and a specific rectangle that the focus
13487      * is coming from.  The rectangle can help give larger views a finer grained hint
13488      * about where focus is coming from, and therefore, where to show selection, or
13489      * forward focus change internally.
13490      *
13491      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13492      * false), or if it is focusable and it is not focusable in touch mode
13493      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13494      *
13495      * A View will not take focus if it is not visible.
13496      *
13497      * A View will not take focus if one of its parents has
13498      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
13499      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
13500      *
13501      * See also {@link #focusSearch(int)}, which is what you call to say that you
13502      * have focus, and you want your parent to look for the next one.
13503      *
13504      * You may wish to override this method if your custom {@link View} has an internal
13505      * {@link View} that it wishes to forward the request to.
13506      *
13507      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13508      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
13509      *        to give a finer grained hint about where focus is coming from.  May be null
13510      *        if there is no hint.
13511      * @return Whether this view or one of its descendants actually took focus.
13512      */
requestFocus(int direction, Rect previouslyFocusedRect)13513     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
13514         return requestFocusNoSearch(direction, previouslyFocusedRect);
13515     }
13516 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)13517     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
13518         // need to be focusable
13519         if (!canTakeFocus()) {
13520             return false;
13521         }
13522 
13523         // need to be focusable in touch mode if in touch mode
13524         if (isInTouchMode() &&
13525             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
13526                return false;
13527         }
13528 
13529         // need to not have any parents blocking us
13530         if (hasAncestorThatBlocksDescendantFocus()) {
13531             return false;
13532         }
13533 
13534         if (!isLayoutValid()) {
13535             mPrivateFlags |= PFLAG_WANTS_FOCUS;
13536         } else {
13537             clearParentsWantFocus();
13538         }
13539 
13540         handleFocusGainInternal(direction, previouslyFocusedRect);
13541         return true;
13542     }
13543 
clearParentsWantFocus()13544     void clearParentsWantFocus() {
13545         if (mParent instanceof View) {
13546             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
13547             ((View) mParent).clearParentsWantFocus();
13548         }
13549     }
13550 
13551     /**
13552      * Call this to try to give focus to a specific view or to one of its descendants. This is a
13553      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
13554      * touch mode to request focus when they are touched.
13555      *
13556      * @return Whether this view or one of its descendants actually took focus.
13557      *
13558      * @see #isInTouchMode()
13559      *
13560      */
requestFocusFromTouch()13561     public final boolean requestFocusFromTouch() {
13562         // Leave touch mode if we need to
13563         if (isInTouchMode()) {
13564             ViewRootImpl viewRoot = getViewRootImpl();
13565             if (viewRoot != null) {
13566                 viewRoot.ensureTouchMode(false);
13567             }
13568         }
13569         return requestFocus(View.FOCUS_DOWN);
13570     }
13571 
13572     /**
13573      * @return Whether any ancestor of this view blocks descendant focus.
13574      */
hasAncestorThatBlocksDescendantFocus()13575     private boolean hasAncestorThatBlocksDescendantFocus() {
13576         final boolean focusableInTouchMode = isFocusableInTouchMode();
13577         ViewParent ancestor = mParent;
13578         while (ancestor instanceof ViewGroup) {
13579             final ViewGroup vgAncestor = (ViewGroup) ancestor;
13580             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
13581                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
13582                 return true;
13583             } else {
13584                 ancestor = vgAncestor.getParent();
13585             }
13586         }
13587         return false;
13588     }
13589 
13590     /**
13591      * Gets the mode for determining whether this View is important for accessibility.
13592      * A view is important for accessibility if it fires accessibility events and if it
13593      * is reported to accessibility services that query the screen.
13594      *
13595      * @return The mode for determining whether a view is important for accessibility, one
13596      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
13597      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
13598      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
13599      *
13600      * @attr ref android.R.styleable#View_importantForAccessibility
13601      *
13602      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13603      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13604      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13605      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13606      */
13607     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
13608             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
13609             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
13610             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
13611             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13612                     to = "noHideDescendants")
13613         })
13614     @InspectableProperty(enumMapping = {
13615             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
13616             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
13617             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
13618             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13619                     name = "noHideDescendants"),
13620     })
getImportantForAccessibility()13621     public int getImportantForAccessibility() {
13622         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
13623                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
13624     }
13625 
13626     /**
13627      * Sets the live region mode for this view. This indicates to accessibility
13628      * services whether they should automatically notify the user about changes
13629      * to the view's content description or text, or to the content descriptions
13630      * or text of the view's children (where applicable).
13631      * <p>
13632      * For example, in a login screen with a TextView that displays an "incorrect
13633      * password" notification, that view should be marked as a live region with
13634      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13635      * <p>
13636      * To disable change notifications for this view, use
13637      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
13638      * mode for most views.
13639      * <p>
13640      * To indicate that the user should be notified of changes, use
13641      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13642      * <p>
13643      * If the view's changes should interrupt ongoing speech and notify the user
13644      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
13645      *
13646      * @param mode The live region mode for this view, one of:
13647      *        <ul>
13648      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
13649      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
13650      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
13651      *        </ul>
13652      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13653      */
setAccessibilityLiveRegion(int mode)13654     public void setAccessibilityLiveRegion(int mode) {
13655         if (mode != getAccessibilityLiveRegion()) {
13656             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13657             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
13658                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13659             notifyViewAccessibilityStateChangedIfNeeded(
13660                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13661         }
13662     }
13663 
13664     /**
13665      * Gets the live region mode for this View.
13666      *
13667      * @return The live region mode for the view.
13668      *
13669      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13670      *
13671      * @see #setAccessibilityLiveRegion(int)
13672      */
13673     @InspectableProperty(enumMapping = {
13674             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
13675             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
13676             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
13677     })
getAccessibilityLiveRegion()13678     public int getAccessibilityLiveRegion() {
13679         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
13680                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
13681     }
13682 
13683     /**
13684      * Sets how to determine whether this view is important for accessibility
13685      * which is if it fires accessibility events and if it is reported to
13686      * accessibility services that query the screen.
13687      *
13688      * @param mode How to determine whether this view is important for accessibility.
13689      *
13690      * @attr ref android.R.styleable#View_importantForAccessibility
13691      *
13692      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13693      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13694      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13695      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13696      */
setImportantForAccessibility(int mode)13697     public void setImportantForAccessibility(int mode) {
13698         final int oldMode = getImportantForAccessibility();
13699         if (mode != oldMode) {
13700             final boolean hideDescendants =
13701                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
13702 
13703             // If this node or its descendants are no longer important, try to
13704             // clear accessibility focus.
13705             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
13706                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
13707                 if (focusHost != null) {
13708                     focusHost.clearAccessibilityFocus();
13709                 }
13710             }
13711 
13712             // If we're moving between AUTO and another state, we might not need
13713             // to send a subtree changed notification. We'll store the computed
13714             // importance, since we'll need to check it later to make sure.
13715             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
13716                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
13717             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
13718             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13719             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
13720                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13721             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
13722                 notifySubtreeAccessibilityStateChangedIfNeeded();
13723             } else {
13724                 notifyViewAccessibilityStateChangedIfNeeded(
13725                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13726             }
13727         }
13728     }
13729 
13730     /**
13731      * Returns the view within this view's hierarchy that is hosting
13732      * accessibility focus.
13733      *
13734      * @param searchDescendants whether to search for focus in descendant views
13735      * @return the view hosting accessibility focus, or {@code null}
13736      */
findAccessibilityFocusHost(boolean searchDescendants)13737     private View findAccessibilityFocusHost(boolean searchDescendants) {
13738         if (isAccessibilityFocusedViewOrHost()) {
13739             return this;
13740         }
13741 
13742         if (searchDescendants) {
13743             final ViewRootImpl viewRoot = getViewRootImpl();
13744             if (viewRoot != null) {
13745                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
13746                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13747                     return focusHost;
13748                 }
13749             }
13750         }
13751 
13752         return null;
13753     }
13754 
13755     /**
13756      * Computes whether this view should be exposed for accessibility. In
13757      * general, views that are interactive or provide information are exposed
13758      * while views that serve only as containers are hidden.
13759      * <p>
13760      * If an ancestor of this view has importance
13761      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
13762      * returns <code>false</code>.
13763      * <p>
13764      * Otherwise, the value is computed according to the view's
13765      * {@link #getImportantForAccessibility()} value:
13766      * <ol>
13767      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
13768      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
13769      * </code>
13770      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
13771      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
13772      * view satisfies any of the following:
13773      * <ul>
13774      * <li>Is actionable, e.g. {@link #isClickable()},
13775      * {@link #isLongClickable()}, or {@link #isFocusable()}
13776      * <li>Has an {@link AccessibilityDelegate}
13777      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
13778      * {@link OnKeyListener}, etc.
13779      * <li>Is an accessibility live region, e.g.
13780      * {@link #getAccessibilityLiveRegion()} is not
13781      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
13782      * </ul>
13783      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
13784      * </ol>
13785      *
13786      * @return Whether the view is exposed for accessibility.
13787      * @see #setImportantForAccessibility(int)
13788      * @see #getImportantForAccessibility()
13789      */
isImportantForAccessibility()13790     public boolean isImportantForAccessibility() {
13791         final int mode = getImportantForAccessibility();
13792         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
13793                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13794             return false;
13795         }
13796 
13797         // Check parent mode to ensure we're not hidden.
13798         ViewParent parent = mParent;
13799         while (parent instanceof View) {
13800             if (((View) parent).getImportantForAccessibility()
13801                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13802                 return false;
13803             }
13804             parent = parent.getParent();
13805         }
13806 
13807         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
13808                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
13809                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
13810                 || isAccessibilityPane();
13811     }
13812 
13813     /**
13814      * Gets the parent for accessibility purposes. Note that the parent for
13815      * accessibility is not necessary the immediate parent. It is the first
13816      * predecessor that is important for accessibility.
13817      *
13818      * @return The parent for accessibility purposes.
13819      */
getParentForAccessibility()13820     public ViewParent getParentForAccessibility() {
13821         if (mParent instanceof View) {
13822             View parentView = (View) mParent;
13823             if (parentView.includeForAccessibility()) {
13824                 return mParent;
13825             } else {
13826                 return mParent.getParentForAccessibility();
13827             }
13828         }
13829         return null;
13830     }
13831 
13832     /** @hide */
getSelfOrParentImportantForA11y()13833     View getSelfOrParentImportantForA11y() {
13834         if (isImportantForAccessibility()) return this;
13835         ViewParent parent = getParentForAccessibility();
13836         if (parent instanceof View) return (View) parent;
13837         return null;
13838     }
13839 
13840     /**
13841      * Adds the children of this View relevant for accessibility to the given list
13842      * as output. Since some Views are not important for accessibility the added
13843      * child views are not necessarily direct children of this view, rather they are
13844      * the first level of descendants important for accessibility.
13845      *
13846      * @param outChildren The output list that will receive children for accessibility.
13847      */
addChildrenForAccessibility(ArrayList<View> outChildren)13848     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
13849 
13850     }
13851 
13852     /**
13853      * Whether to regard this view for accessibility. A view is regarded for
13854      * accessibility if it is important for accessibility or the querying
13855      * accessibility service has explicitly requested that view not
13856      * important for accessibility are regarded.
13857      *
13858      * @return Whether to regard the view for accessibility.
13859      *
13860      * @hide
13861      */
13862     @UnsupportedAppUsage
includeForAccessibility()13863     public boolean includeForAccessibility() {
13864         if (mAttachInfo != null) {
13865             return (mAttachInfo.mAccessibilityFetchFlags
13866                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
13867                     || isImportantForAccessibility();
13868         }
13869         return false;
13870     }
13871 
13872     /**
13873      * Returns whether the View is considered actionable from
13874      * accessibility perspective. Such view are important for
13875      * accessibility.
13876      *
13877      * @return True if the view is actionable for accessibility.
13878      *
13879      * @hide
13880      */
isActionableForAccessibility()13881     public boolean isActionableForAccessibility() {
13882         return (isClickable() || isLongClickable() || isFocusable());
13883     }
13884 
13885     /**
13886      * Returns whether the View has registered callbacks which makes it
13887      * important for accessibility.
13888      *
13889      * @return True if the view is actionable for accessibility.
13890      */
hasListenersForAccessibility()13891     private boolean hasListenersForAccessibility() {
13892         ListenerInfo info = getListenerInfo();
13893         return mTouchDelegate != null || info.mOnKeyListener != null
13894                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
13895                 || info.mOnHoverListener != null || info.mOnDragListener != null;
13896     }
13897 
13898     /**
13899      * Notifies that the accessibility state of this view changed. The change
13900      * is local to this view and does not represent structural changes such
13901      * as children and parent. For example, the view became focusable. The
13902      * notification is at at most once every
13903      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13904      * to avoid unnecessary load to the system. Also once a view has a pending
13905      * notification this method is a NOP until the notification has been sent.
13906      *
13907      * @hide
13908      */
13909     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyViewAccessibilityStateChangedIfNeeded(int changeType)13910     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
13911         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13912             return;
13913         }
13914 
13915         // Changes to views with a pane title count as window state changes, as the pane title
13916         // marks them as significant parts of the UI.
13917         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
13918                 && isAccessibilityPane()) {
13919             // If the pane isn't visible, content changed events are sufficient unless we're
13920             // reporting that the view just disappeared
13921             if ((getVisibility() == VISIBLE)
13922                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
13923                 final AccessibilityEvent event = AccessibilityEvent.obtain();
13924                 onInitializeAccessibilityEvent(event);
13925                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
13926                 event.setContentChangeTypes(changeType);
13927                 event.setSource(this);
13928                 onPopulateAccessibilityEvent(event);
13929                 if (mParent != null) {
13930                     try {
13931                         mParent.requestSendAccessibilityEvent(this, event);
13932                     } catch (AbstractMethodError e) {
13933                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
13934                                 + " does not fully implement ViewParent", e);
13935                     }
13936                 }
13937                 return;
13938             }
13939         }
13940 
13941         // If this is a live region, we should send a subtree change event
13942         // from this view immediately. Otherwise, we can let it propagate up.
13943         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
13944             final AccessibilityEvent event = AccessibilityEvent.obtain();
13945             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
13946             event.setContentChangeTypes(changeType);
13947             sendAccessibilityEventUnchecked(event);
13948         } else if (mParent != null) {
13949             try {
13950                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
13951             } catch (AbstractMethodError e) {
13952                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13953                         " does not fully implement ViewParent", e);
13954             }
13955         }
13956     }
13957 
13958     /**
13959      * Notifies that the accessibility state of this view changed. The change
13960      * is *not* local to this view and does represent structural changes such
13961      * as children and parent. For example, the view size changed. The
13962      * notification is at at most once every
13963      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13964      * to avoid unnecessary load to the system. Also once a view has a pending
13965      * notification this method is a NOP until the notification has been sent.
13966      *
13967      * @hide
13968      */
13969     @UnsupportedAppUsage
notifySubtreeAccessibilityStateChangedIfNeeded()13970     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
13971         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13972             return;
13973         }
13974 
13975         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
13976             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
13977             if (mParent != null) {
13978                 try {
13979                     mParent.notifySubtreeAccessibilityStateChanged(
13980                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
13981                 } catch (AbstractMethodError e) {
13982                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13983                             " does not fully implement ViewParent", e);
13984                 }
13985             }
13986         }
13987     }
13988 
notifySubtreeAccessibilityStateChangedByParentIfNeeded()13989     private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
13990         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
13991             return;
13992         }
13993 
13994         final View sendA11yEventView = (View) getParentForAccessibility();
13995         if (sendA11yEventView != null && sendA11yEventView.isShown()) {
13996             sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
13997         }
13998     }
13999 
14000     /**
14001      * Changes the visibility of this View without triggering any other changes. This should only
14002      * be used by animation frameworks, such as {@link android.transition.Transition}, where
14003      * visibility changes should not adjust focus or trigger a new layout. Application developers
14004      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
14005      *
14006      * <p>Only call this method when a temporary visibility must be applied during an
14007      * animation and the original visibility value is guaranteed to be reset after the
14008      * animation completes. Use {@link #setVisibility} in all other cases.</p>
14009      *
14010      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
14011      * @see #setVisibility(int)
14012      */
setTransitionVisibility(@isibility int visibility)14013     public void setTransitionVisibility(@Visibility int visibility) {
14014         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
14015     }
14016 
14017     /**
14018      * Reset the flag indicating the accessibility state of the subtree rooted
14019      * at this view changed.
14020      */
resetSubtreeAccessibilityStateChanged()14021     void resetSubtreeAccessibilityStateChanged() {
14022         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
14023     }
14024 
14025     /**
14026      * Report an accessibility action to this view's parents for delegated processing.
14027      *
14028      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
14029      * call this method to delegate an accessibility action to a supporting parent. If the parent
14030      * returns true from its
14031      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
14032      * method this method will return true to signify that the action was consumed.</p>
14033      *
14034      * <p>This method is useful for implementing nested scrolling child views. If
14035      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
14036      * a custom view implementation may invoke this method to allow a parent to consume the
14037      * scroll first. If this method returns true the custom view should skip its own scrolling
14038      * behavior.</p>
14039      *
14040      * @param action Accessibility action to delegate
14041      * @param arguments Optional action arguments
14042      * @return true if the action was consumed by a parent
14043      */
dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)14044     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
14045         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
14046             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
14047                 return true;
14048             }
14049         }
14050         return false;
14051     }
14052 
14053     /**
14054      * Performs the specified accessibility action on the view. For
14055      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
14056      * <p>
14057      * If an {@link AccessibilityDelegate} has been specified via calling
14058      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
14059      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
14060      * is responsible for handling this call.
14061      * </p>
14062      *
14063      * <p>The default implementation will delegate
14064      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
14065      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
14066      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
14067      *
14068      * @param action The action to perform.
14069      * @param arguments Optional action arguments.
14070      * @return Whether the action was performed.
14071      */
performAccessibilityAction(int action, Bundle arguments)14072     public boolean performAccessibilityAction(int action, Bundle arguments) {
14073       if (mAccessibilityDelegate != null) {
14074           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
14075       } else {
14076           return performAccessibilityActionInternal(action, arguments);
14077       }
14078     }
14079 
14080    /**
14081     * @see #performAccessibilityAction(int, Bundle)
14082     *
14083     * Note: Called from the default {@link AccessibilityDelegate}.
14084     *
14085     * @hide
14086     */
14087     @UnsupportedAppUsage
performAccessibilityActionInternal(int action, Bundle arguments)14088     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
14089         if (isNestedScrollingEnabled()
14090                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
14091                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
14092                 || action == R.id.accessibilityActionScrollUp
14093                 || action == R.id.accessibilityActionScrollLeft
14094                 || action == R.id.accessibilityActionScrollDown
14095                 || action == R.id.accessibilityActionScrollRight)) {
14096             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
14097                 return true;
14098             }
14099         }
14100 
14101         switch (action) {
14102             case AccessibilityNodeInfo.ACTION_CLICK: {
14103                 if (isClickable()) {
14104                     performClickInternal();
14105                     return true;
14106                 }
14107             } break;
14108             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
14109                 if (isLongClickable()) {
14110                     performLongClick();
14111                     return true;
14112                 }
14113             } break;
14114             case AccessibilityNodeInfo.ACTION_FOCUS: {
14115                 if (!hasFocus()) {
14116                     // Get out of touch mode since accessibility
14117                     // wants to move focus around.
14118                     getViewRootImpl().ensureTouchMode(false);
14119                     return requestFocus();
14120                 }
14121             } break;
14122             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
14123                 if (hasFocus()) {
14124                     clearFocus();
14125                     return !isFocused();
14126                 }
14127             } break;
14128             case AccessibilityNodeInfo.ACTION_SELECT: {
14129                 if (!isSelected()) {
14130                     setSelected(true);
14131                     return isSelected();
14132                 }
14133             } break;
14134             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
14135                 if (isSelected()) {
14136                     setSelected(false);
14137                     return !isSelected();
14138                 }
14139             } break;
14140             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
14141                 if (!isAccessibilityFocused()) {
14142                     return requestAccessibilityFocus();
14143                 }
14144             } break;
14145             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
14146                 if (isAccessibilityFocused()) {
14147                     clearAccessibilityFocus();
14148                     return true;
14149                 }
14150             } break;
14151             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
14152                 if (arguments != null) {
14153                     final int granularity = arguments.getInt(
14154                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
14155                     final boolean extendSelection = arguments.getBoolean(
14156                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
14157                     return traverseAtGranularity(granularity, true, extendSelection);
14158                 }
14159             } break;
14160             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
14161                 if (arguments != null) {
14162                     final int granularity = arguments.getInt(
14163                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
14164                     final boolean extendSelection = arguments.getBoolean(
14165                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
14166                     return traverseAtGranularity(granularity, false, extendSelection);
14167                 }
14168             } break;
14169             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
14170                 CharSequence text = getIterableTextForAccessibility();
14171                 if (text == null) {
14172                     return false;
14173                 }
14174                 final int start = (arguments != null) ? arguments.getInt(
14175                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
14176                 final int end = (arguments != null) ? arguments.getInt(
14177                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
14178                 // Only cursor position can be specified (selection length == 0)
14179                 if ((getAccessibilitySelectionStart() != start
14180                         || getAccessibilitySelectionEnd() != end)
14181                         && (start == end)) {
14182                     setAccessibilitySelection(start, end);
14183                     notifyViewAccessibilityStateChangedIfNeeded(
14184                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14185                     return true;
14186                 }
14187             } break;
14188             case R.id.accessibilityActionShowOnScreen: {
14189                 if (mAttachInfo != null) {
14190                     final Rect r = mAttachInfo.mTmpInvalRect;
14191                     getDrawingRect(r);
14192                     return requestRectangleOnScreen(r, true);
14193                 }
14194             } break;
14195             case R.id.accessibilityActionContextClick: {
14196                 if (isContextClickable()) {
14197                     performContextClick();
14198                     return true;
14199                 }
14200             } break;
14201             case R.id.accessibilityActionShowTooltip: {
14202                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
14203                     // Tooltip already showing
14204                     return false;
14205                 }
14206                 return showLongClickTooltip(0, 0);
14207             }
14208             case R.id.accessibilityActionHideTooltip: {
14209                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
14210                     // No tooltip showing
14211                     return false;
14212                 }
14213                 hideTooltip();
14214                 return true;
14215             }
14216         }
14217         return false;
14218     }
14219 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)14220     private boolean traverseAtGranularity(int granularity, boolean forward,
14221             boolean extendSelection) {
14222         CharSequence text = getIterableTextForAccessibility();
14223         if (text == null || text.length() == 0) {
14224             return false;
14225         }
14226         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
14227         if (iterator == null) {
14228             return false;
14229         }
14230         int current = getAccessibilitySelectionEnd();
14231         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14232             current = forward ? 0 : text.length();
14233         }
14234         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
14235         if (range == null) {
14236             return false;
14237         }
14238         final int segmentStart = range[0];
14239         final int segmentEnd = range[1];
14240         int selectionStart;
14241         int selectionEnd;
14242         if (extendSelection && isAccessibilitySelectionExtendable()) {
14243             selectionStart = getAccessibilitySelectionStart();
14244             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14245                 selectionStart = forward ? segmentStart : segmentEnd;
14246             }
14247             selectionEnd = forward ? segmentEnd : segmentStart;
14248         } else {
14249             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
14250         }
14251         setAccessibilitySelection(selectionStart, selectionEnd);
14252         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
14253                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
14254         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
14255         return true;
14256     }
14257 
14258     /**
14259      * Gets the text reported for accessibility purposes.
14260      *
14261      * @return The accessibility text.
14262      *
14263      * @hide
14264      */
14265     @UnsupportedAppUsage
getIterableTextForAccessibility()14266     public CharSequence getIterableTextForAccessibility() {
14267         return getContentDescription();
14268     }
14269 
14270     /**
14271      * Gets whether accessibility selection can be extended.
14272      *
14273      * @return If selection is extensible.
14274      *
14275      * @hide
14276      */
isAccessibilitySelectionExtendable()14277     public boolean isAccessibilitySelectionExtendable() {
14278         return false;
14279     }
14280 
14281     /**
14282      * @hide
14283      */
getAccessibilitySelectionStart()14284     public int getAccessibilitySelectionStart() {
14285         return mAccessibilityCursorPosition;
14286     }
14287 
14288     /**
14289      * @hide
14290      */
getAccessibilitySelectionEnd()14291     public int getAccessibilitySelectionEnd() {
14292         return getAccessibilitySelectionStart();
14293     }
14294 
14295     /**
14296      * @hide
14297      */
setAccessibilitySelection(int start, int end)14298     public void setAccessibilitySelection(int start, int end) {
14299         if (start ==  end && end == mAccessibilityCursorPosition) {
14300             return;
14301         }
14302         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
14303             mAccessibilityCursorPosition = start;
14304         } else {
14305             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
14306         }
14307         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
14308     }
14309 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)14310     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
14311             int fromIndex, int toIndex) {
14312         if (mParent == null) {
14313             return;
14314         }
14315         AccessibilityEvent event = AccessibilityEvent.obtain(
14316                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
14317         onInitializeAccessibilityEvent(event);
14318         onPopulateAccessibilityEvent(event);
14319         event.setFromIndex(fromIndex);
14320         event.setToIndex(toIndex);
14321         event.setAction(action);
14322         event.setMovementGranularity(granularity);
14323         mParent.requestSendAccessibilityEvent(this, event);
14324     }
14325 
14326     /**
14327      * @hide
14328      */
14329     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getIteratorForGranularity(int granularity)14330     public TextSegmentIterator getIteratorForGranularity(int granularity) {
14331         switch (granularity) {
14332             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
14333                 CharSequence text = getIterableTextForAccessibility();
14334                 if (text != null && text.length() > 0) {
14335                     CharacterTextSegmentIterator iterator =
14336                         CharacterTextSegmentIterator.getInstance(
14337                                 mContext.getResources().getConfiguration().locale);
14338                     iterator.initialize(text.toString());
14339                     return iterator;
14340                 }
14341             } break;
14342             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
14343                 CharSequence text = getIterableTextForAccessibility();
14344                 if (text != null && text.length() > 0) {
14345                     WordTextSegmentIterator iterator =
14346                         WordTextSegmentIterator.getInstance(
14347                                 mContext.getResources().getConfiguration().locale);
14348                     iterator.initialize(text.toString());
14349                     return iterator;
14350                 }
14351             } break;
14352             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
14353                 CharSequence text = getIterableTextForAccessibility();
14354                 if (text != null && text.length() > 0) {
14355                     ParagraphTextSegmentIterator iterator =
14356                         ParagraphTextSegmentIterator.getInstance();
14357                     iterator.initialize(text.toString());
14358                     return iterator;
14359                 }
14360             } break;
14361         }
14362         return null;
14363     }
14364 
14365     /**
14366      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
14367      * and {@link #onFinishTemporaryDetach()}.
14368      *
14369      * <p>This method always returns {@code true} when called directly or indirectly from
14370      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
14371      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
14372      * <ul>
14373      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
14374      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
14375      * </ul>
14376      * </p>
14377      *
14378      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
14379      * and {@link #onFinishTemporaryDetach()}.
14380      */
isTemporarilyDetached()14381     public final boolean isTemporarilyDetached() {
14382         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
14383     }
14384 
14385     /**
14386      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
14387      * a container View.
14388      */
14389     @CallSuper
dispatchStartTemporaryDetach()14390     public void dispatchStartTemporaryDetach() {
14391         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
14392         notifyEnterOrExitForAutoFillIfNeeded(false);
14393         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
14394         onStartTemporaryDetach();
14395     }
14396 
14397     /**
14398      * This is called when a container is going to temporarily detach a child, with
14399      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
14400      * It will either be followed by {@link #onFinishTemporaryDetach()} or
14401      * {@link #onDetachedFromWindow()} when the container is done.
14402      */
onStartTemporaryDetach()14403     public void onStartTemporaryDetach() {
14404         removeUnsetPressCallback();
14405         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
14406     }
14407 
14408     /**
14409      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
14410      * a container View.
14411      */
14412     @CallSuper
dispatchFinishTemporaryDetach()14413     public void dispatchFinishTemporaryDetach() {
14414         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
14415         onFinishTemporaryDetach();
14416         if (hasWindowFocus() && hasFocus()) {
14417             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14418         }
14419         notifyEnterOrExitForAutoFillIfNeeded(true);
14420         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
14421     }
14422 
14423     /**
14424      * Called after {@link #onStartTemporaryDetach} when the container is done
14425      * changing the view.
14426      */
onFinishTemporaryDetach()14427     public void onFinishTemporaryDetach() {
14428     }
14429 
14430     /**
14431      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
14432      * for this view's window.  Returns null if the view is not currently attached
14433      * to the window.  Normally you will not need to use this directly, but
14434      * just use the standard high-level event callbacks like
14435      * {@link #onKeyDown(int, KeyEvent)}.
14436      */
getKeyDispatcherState()14437     public KeyEvent.DispatcherState getKeyDispatcherState() {
14438         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
14439     }
14440 
14441     /**
14442      * Dispatch a key event before it is processed by any input method
14443      * associated with the view hierarchy.  This can be used to intercept
14444      * key events in special situations before the IME consumes them; a
14445      * typical example would be handling the BACK key to update the application's
14446      * UI instead of allowing the IME to see it and close itself.
14447      *
14448      * @param event The key event to be dispatched.
14449      * @return True if the event was handled, false otherwise.
14450      */
dispatchKeyEventPreIme(KeyEvent event)14451     public boolean dispatchKeyEventPreIme(KeyEvent event) {
14452         return onKeyPreIme(event.getKeyCode(), event);
14453     }
14454 
14455     /**
14456      * Dispatch a key event to the next view on the focus path. This path runs
14457      * from the top of the view tree down to the currently focused view. If this
14458      * view has focus, it will dispatch to itself. Otherwise it will dispatch
14459      * the next node down the focus path. This method also fires any key
14460      * listeners.
14461      *
14462      * @param event The key event to be dispatched.
14463      * @return True if the event was handled, false otherwise.
14464      */
dispatchKeyEvent(KeyEvent event)14465     public boolean dispatchKeyEvent(KeyEvent event) {
14466         if (mInputEventConsistencyVerifier != null) {
14467             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
14468         }
14469 
14470         // Give any attached key listener a first crack at the event.
14471         //noinspection SimplifiableIfStatement
14472         ListenerInfo li = mListenerInfo;
14473         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
14474                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
14475             return true;
14476         }
14477 
14478         if (event.dispatch(this, mAttachInfo != null
14479                 ? mAttachInfo.mKeyDispatchState : null, this)) {
14480             return true;
14481         }
14482 
14483         if (mInputEventConsistencyVerifier != null) {
14484             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14485         }
14486         return false;
14487     }
14488 
14489     /**
14490      * Dispatches a key shortcut event.
14491      *
14492      * @param event The key event to be dispatched.
14493      * @return True if the event was handled by the view, false otherwise.
14494      */
dispatchKeyShortcutEvent(KeyEvent event)14495     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
14496         return onKeyShortcut(event.getKeyCode(), event);
14497     }
14498 
14499     /**
14500      * Pass the touch screen motion event down to the target view, or this
14501      * view if it is the target.
14502      *
14503      * @param event The motion event to be dispatched.
14504      * @return True if the event was handled by the view, false otherwise.
14505      */
dispatchTouchEvent(MotionEvent event)14506     public boolean dispatchTouchEvent(MotionEvent event) {
14507         // If the event should be handled by accessibility focus first.
14508         if (event.isTargetAccessibilityFocus()) {
14509             // We don't have focus or no virtual descendant has it, do not handle the event.
14510             if (!isAccessibilityFocusedViewOrHost()) {
14511                 return false;
14512             }
14513             // We have focus and got the event, then use normal event dispatch.
14514             event.setTargetAccessibilityFocus(false);
14515         }
14516         boolean result = false;
14517 
14518         if (mInputEventConsistencyVerifier != null) {
14519             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
14520         }
14521 
14522         final int actionMasked = event.getActionMasked();
14523         if (actionMasked == MotionEvent.ACTION_DOWN) {
14524             // Defensive cleanup for new gesture
14525             stopNestedScroll();
14526         }
14527 
14528         if (onFilterTouchEventForSecurity(event)) {
14529             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
14530                 result = true;
14531             }
14532             //noinspection SimplifiableIfStatement
14533             ListenerInfo li = mListenerInfo;
14534             if (li != null && li.mOnTouchListener != null
14535                     && (mViewFlags & ENABLED_MASK) == ENABLED
14536                     && li.mOnTouchListener.onTouch(this, event)) {
14537                 result = true;
14538             }
14539 
14540             if (!result && onTouchEvent(event)) {
14541                 result = true;
14542             }
14543         }
14544 
14545         if (!result && mInputEventConsistencyVerifier != null) {
14546             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14547         }
14548 
14549         // Clean up after nested scrolls if this is the end of a gesture;
14550         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
14551         // of the gesture.
14552         if (actionMasked == MotionEvent.ACTION_UP ||
14553                 actionMasked == MotionEvent.ACTION_CANCEL ||
14554                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
14555             stopNestedScroll();
14556         }
14557 
14558         return result;
14559     }
14560 
isAccessibilityFocusedViewOrHost()14561     boolean isAccessibilityFocusedViewOrHost() {
14562         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
14563                 .getAccessibilityFocusedHost() == this);
14564     }
14565 
14566     /**
14567      * Returns whether this view can receive pointer events.
14568      *
14569      * @return {@code true} if this view can receive pointer events.
14570      * @hide
14571      */
canReceivePointerEvents()14572     protected boolean canReceivePointerEvents() {
14573         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
14574     }
14575 
14576     /**
14577      * Filter the touch event to apply security policies.
14578      *
14579      * @param event The motion event to be filtered.
14580      * @return True if the event should be dispatched, false if the event should be dropped.
14581      *
14582      * @see #getFilterTouchesWhenObscured
14583      */
onFilterTouchEventForSecurity(MotionEvent event)14584     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
14585         //noinspection RedundantIfStatement
14586         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
14587                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
14588             // Window is obscured, drop this touch.
14589             return false;
14590         }
14591         return true;
14592     }
14593 
14594     /**
14595      * Pass a trackball motion event down to the focused view.
14596      *
14597      * @param event The motion event to be dispatched.
14598      * @return True if the event was handled by the view, false otherwise.
14599      */
dispatchTrackballEvent(MotionEvent event)14600     public boolean dispatchTrackballEvent(MotionEvent event) {
14601         if (mInputEventConsistencyVerifier != null) {
14602             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
14603         }
14604 
14605         return onTrackballEvent(event);
14606     }
14607 
14608     /**
14609      * Pass a captured pointer event down to the focused view.
14610      *
14611      * @param event The motion event to be dispatched.
14612      * @return True if the event was handled by the view, false otherwise.
14613      */
dispatchCapturedPointerEvent(MotionEvent event)14614     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
14615         if (!hasPointerCapture()) {
14616             return false;
14617         }
14618         //noinspection SimplifiableIfStatement
14619         ListenerInfo li = mListenerInfo;
14620         if (li != null && li.mOnCapturedPointerListener != null
14621                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
14622             return true;
14623         }
14624         return onCapturedPointerEvent(event);
14625     }
14626 
14627     /**
14628      * Dispatch a generic motion event.
14629      * <p>
14630      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
14631      * are delivered to the view under the pointer.  All other generic motion events are
14632      * delivered to the focused view.  Hover events are handled specially and are delivered
14633      * to {@link #onHoverEvent(MotionEvent)}.
14634      * </p>
14635      *
14636      * @param event The motion event to be dispatched.
14637      * @return True if the event was handled by the view, false otherwise.
14638      */
dispatchGenericMotionEvent(MotionEvent event)14639     public boolean dispatchGenericMotionEvent(MotionEvent event) {
14640         if (mInputEventConsistencyVerifier != null) {
14641             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
14642         }
14643 
14644         final int source = event.getSource();
14645         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
14646             final int action = event.getAction();
14647             if (action == MotionEvent.ACTION_HOVER_ENTER
14648                     || action == MotionEvent.ACTION_HOVER_MOVE
14649                     || action == MotionEvent.ACTION_HOVER_EXIT) {
14650                 if (dispatchHoverEvent(event)) {
14651                     return true;
14652                 }
14653             } else if (dispatchGenericPointerEvent(event)) {
14654                 return true;
14655             }
14656         } else if (dispatchGenericFocusedEvent(event)) {
14657             return true;
14658         }
14659 
14660         if (dispatchGenericMotionEventInternal(event)) {
14661             return true;
14662         }
14663 
14664         if (mInputEventConsistencyVerifier != null) {
14665             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14666         }
14667         return false;
14668     }
14669 
dispatchGenericMotionEventInternal(MotionEvent event)14670     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
14671         //noinspection SimplifiableIfStatement
14672         ListenerInfo li = mListenerInfo;
14673         if (li != null && li.mOnGenericMotionListener != null
14674                 && (mViewFlags & ENABLED_MASK) == ENABLED
14675                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
14676             return true;
14677         }
14678 
14679         if (onGenericMotionEvent(event)) {
14680             return true;
14681         }
14682 
14683         final int actionButton = event.getActionButton();
14684         switch (event.getActionMasked()) {
14685             case MotionEvent.ACTION_BUTTON_PRESS:
14686                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
14687                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14688                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14689                     if (performContextClick(event.getX(), event.getY())) {
14690                         mInContextButtonPress = true;
14691                         setPressed(true, event.getX(), event.getY());
14692                         removeTapCallback();
14693                         removeLongPressCallback();
14694                         return true;
14695                     }
14696                 }
14697                 break;
14698 
14699             case MotionEvent.ACTION_BUTTON_RELEASE:
14700                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14701                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14702                     mInContextButtonPress = false;
14703                     mIgnoreNextUpEvent = true;
14704                 }
14705                 break;
14706         }
14707 
14708         if (mInputEventConsistencyVerifier != null) {
14709             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14710         }
14711         return false;
14712     }
14713 
14714     /**
14715      * Dispatch a hover event.
14716      * <p>
14717      * Do not call this method directly.
14718      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14719      * </p>
14720      *
14721      * @param event The motion event to be dispatched.
14722      * @return True if the event was handled by the view, false otherwise.
14723      */
dispatchHoverEvent(MotionEvent event)14724     protected boolean dispatchHoverEvent(MotionEvent event) {
14725         ListenerInfo li = mListenerInfo;
14726         //noinspection SimplifiableIfStatement
14727         if (li != null && li.mOnHoverListener != null
14728                 && (mViewFlags & ENABLED_MASK) == ENABLED
14729                 && li.mOnHoverListener.onHover(this, event)) {
14730             return true;
14731         }
14732 
14733         return onHoverEvent(event);
14734     }
14735 
14736     /**
14737      * Returns true if the view has a child to which it has recently sent
14738      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
14739      * it does not have a hovered child, then it must be the innermost hovered view.
14740      * @hide
14741      */
hasHoveredChild()14742     protected boolean hasHoveredChild() {
14743         return false;
14744     }
14745 
14746     /**
14747      * Returns true if the given point, in local coordinates, is inside the hovered child.
14748      *
14749      * @hide
14750      */
pointInHoveredChild(MotionEvent event)14751     protected boolean pointInHoveredChild(MotionEvent event) {
14752         return false;
14753     }
14754 
14755     /**
14756      * Dispatch a generic motion event to the view under the first pointer.
14757      * <p>
14758      * Do not call this method directly.
14759      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14760      * </p>
14761      *
14762      * @param event The motion event to be dispatched.
14763      * @return True if the event was handled by the view, false otherwise.
14764      */
dispatchGenericPointerEvent(MotionEvent event)14765     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
14766         return false;
14767     }
14768 
14769     /**
14770      * Dispatch a generic motion event to the currently focused view.
14771      * <p>
14772      * Do not call this method directly.
14773      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14774      * </p>
14775      *
14776      * @param event The motion event to be dispatched.
14777      * @return True if the event was handled by the view, false otherwise.
14778      */
dispatchGenericFocusedEvent(MotionEvent event)14779     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
14780         return false;
14781     }
14782 
14783     /**
14784      * Dispatch a pointer event.
14785      * <p>
14786      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
14787      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
14788      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
14789      * and should not be expected to handle other pointing device features.
14790      * </p>
14791      *
14792      * @param event The motion event to be dispatched.
14793      * @return True if the event was handled by the view, false otherwise.
14794      * @hide
14795      */
14796     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchPointerEvent(MotionEvent event)14797     public final boolean dispatchPointerEvent(MotionEvent event) {
14798         if (event.isTouchEvent()) {
14799             return dispatchTouchEvent(event);
14800         } else {
14801             return dispatchGenericMotionEvent(event);
14802         }
14803     }
14804 
14805     /**
14806      * Called when the window containing this view gains or loses window focus.
14807      * ViewGroups should override to route to their children.
14808      *
14809      * @param hasFocus True if the window containing this view now has focus,
14810      *        false otherwise.
14811      */
dispatchWindowFocusChanged(boolean hasFocus)14812     public void dispatchWindowFocusChanged(boolean hasFocus) {
14813         onWindowFocusChanged(hasFocus);
14814     }
14815 
14816     /**
14817      * Called when the window containing this view gains or loses focus.  Note
14818      * that this is separate from view focus: to receive key events, both
14819      * your view and its window must have focus.  If a window is displayed
14820      * on top of yours that takes input focus, then your own window will lose
14821      * focus but the view focus will remain unchanged.
14822      *
14823      * @param hasWindowFocus True if the window containing this view now has
14824      *        focus, false otherwise.
14825      */
onWindowFocusChanged(boolean hasWindowFocus)14826     public void onWindowFocusChanged(boolean hasWindowFocus) {
14827         if (!hasWindowFocus) {
14828             if (isPressed()) {
14829                 setPressed(false);
14830             }
14831             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14832             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14833                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
14834             }
14835             removeLongPressCallback();
14836             removeTapCallback();
14837             onFocusLost();
14838         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14839             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14840         }
14841 
14842         refreshDrawableState();
14843     }
14844 
14845     /**
14846      * Returns true if this view is in a window that currently has window focus.
14847      * Note that this is not the same as the view itself having focus.
14848      *
14849      * @return True if this view is in a window that currently has window focus.
14850      */
hasWindowFocus()14851     public boolean hasWindowFocus() {
14852         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
14853     }
14854 
14855     /**
14856      * @return {@code true} if this view is in a window that currently has IME focusable state.
14857      * @hide
14858      */
hasImeFocus()14859     public boolean hasImeFocus() {
14860         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
14861     }
14862 
14863     /**
14864      * Dispatch a view visibility change down the view hierarchy.
14865      * ViewGroups should override to route to their children.
14866      * @param changedView The view whose visibility changed. Could be 'this' or
14867      * an ancestor view.
14868      * @param visibility The new visibility of changedView: {@link #VISIBLE},
14869      * {@link #INVISIBLE} or {@link #GONE}.
14870      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)14871     protected void dispatchVisibilityChanged(@NonNull View changedView,
14872             @Visibility int visibility) {
14873         onVisibilityChanged(changedView, visibility);
14874     }
14875 
14876     /**
14877      * Called when the visibility of the view or an ancestor of the view has
14878      * changed.
14879      *
14880      * @param changedView The view whose visibility changed. May be
14881      *                    {@code this} or an ancestor view.
14882      * @param visibility The new visibility, one of {@link #VISIBLE},
14883      *                   {@link #INVISIBLE} or {@link #GONE}.
14884      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)14885     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
14886     }
14887 
14888     /**
14889      * Dispatch a hint about whether this view is displayed. For instance, when
14890      * a View moves out of the screen, it might receives a display hint indicating
14891      * the view is not displayed. Applications should not <em>rely</em> on this hint
14892      * as there is no guarantee that they will receive one.
14893      *
14894      * @param hint A hint about whether or not this view is displayed:
14895      * {@link #VISIBLE} or {@link #INVISIBLE}.
14896      */
dispatchDisplayHint(@isibility int hint)14897     public void dispatchDisplayHint(@Visibility int hint) {
14898         onDisplayHint(hint);
14899     }
14900 
14901     /**
14902      * Gives this view a hint about whether is displayed or not. For instance, when
14903      * a View moves out of the screen, it might receives a display hint indicating
14904      * the view is not displayed. Applications should not <em>rely</em> on this hint
14905      * as there is no guarantee that they will receive one.
14906      *
14907      * @param hint A hint about whether or not this view is displayed:
14908      * {@link #VISIBLE} or {@link #INVISIBLE}.
14909      */
onDisplayHint(@isibility int hint)14910     protected void onDisplayHint(@Visibility int hint) {
14911     }
14912 
14913     /**
14914      * Dispatch a window visibility change down the view hierarchy.
14915      * ViewGroups should override to route to their children.
14916      *
14917      * @param visibility The new visibility of the window.
14918      *
14919      * @see #onWindowVisibilityChanged(int)
14920      */
dispatchWindowVisibilityChanged(@isibility int visibility)14921     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
14922         onWindowVisibilityChanged(visibility);
14923     }
14924 
14925     /**
14926      * Called when the window containing has change its visibility
14927      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
14928      * that this tells you whether or not your window is being made visible
14929      * to the window manager; this does <em>not</em> tell you whether or not
14930      * your window is obscured by other windows on the screen, even if it
14931      * is itself visible.
14932      *
14933      * @param visibility The new visibility of the window.
14934      */
onWindowVisibilityChanged(@isibility int visibility)14935     protected void onWindowVisibilityChanged(@Visibility int visibility) {
14936         if (visibility == VISIBLE) {
14937             initialAwakenScrollBars();
14938         }
14939     }
14940 
14941     /**
14942      * @return true if this view and all ancestors are visible as of the last
14943      * {@link #onVisibilityAggregated(boolean)} call.
14944      */
isAggregatedVisible()14945     boolean isAggregatedVisible() {
14946         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
14947     }
14948 
14949     /**
14950      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
14951      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
14952      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
14953      *
14954      * @param isVisible true if this view's visibility to the user is uninterrupted by its
14955      *                  ancestors or by window visibility
14956      * @return true if this view is visible to the user, not counting clipping or overlapping
14957      */
dispatchVisibilityAggregated(boolean isVisible)14958     boolean dispatchVisibilityAggregated(boolean isVisible) {
14959         final boolean thisVisible = getVisibility() == VISIBLE;
14960         // If we're not visible but something is telling us we are, ignore it.
14961         if (thisVisible || !isVisible) {
14962             onVisibilityAggregated(isVisible);
14963         }
14964         return thisVisible && isVisible;
14965     }
14966 
14967     /**
14968      * Called when the user-visibility of this View is potentially affected by a change
14969      * to this view itself, an ancestor view or the window this view is attached to.
14970      *
14971      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
14972      *                  and this view's window is also visible
14973      */
14974     @CallSuper
onVisibilityAggregated(boolean isVisible)14975     public void onVisibilityAggregated(boolean isVisible) {
14976         // Update our internal visibility tracking so we can detect changes
14977         boolean oldVisible = isAggregatedVisible();
14978         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
14979                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
14980         if (isVisible && mAttachInfo != null) {
14981             initialAwakenScrollBars();
14982         }
14983 
14984         final Drawable dr = mBackground;
14985         if (dr != null && isVisible != dr.isVisible()) {
14986             dr.setVisible(isVisible, false);
14987         }
14988         final Drawable hl = mDefaultFocusHighlight;
14989         if (hl != null && isVisible != hl.isVisible()) {
14990             hl.setVisible(isVisible, false);
14991         }
14992         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
14993         if (fg != null && isVisible != fg.isVisible()) {
14994             fg.setVisible(isVisible, false);
14995         }
14996 
14997         if (isAutofillable()) {
14998             AutofillManager afm = getAutofillManager();
14999 
15000             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
15001                 if (mVisibilityChangeForAutofillHandler != null) {
15002                     mVisibilityChangeForAutofillHandler.removeMessages(0);
15003                 }
15004 
15005                 // If the view is in the background but still part of the hierarchy this is called
15006                 // with isVisible=false. Hence visibility==false requires further checks
15007                 if (isVisible) {
15008                     afm.notifyViewVisibilityChanged(this, true);
15009                 } else {
15010                     if (mVisibilityChangeForAutofillHandler == null) {
15011                         mVisibilityChangeForAutofillHandler =
15012                                 new VisibilityChangeForAutofillHandler(afm, this);
15013                     }
15014                     // Let current operation (e.g. removal of the view from the hierarchy)
15015                     // finish before checking state
15016                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
15017                 }
15018             }
15019         }
15020 
15021         if (isVisible != oldVisible) {
15022             if (isAccessibilityPane()) {
15023                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
15024                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
15025                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
15026             }
15027 
15028             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
15029 
15030             if (!getSystemGestureExclusionRects().isEmpty()) {
15031                 postUpdateSystemGestureExclusionRects();
15032             }
15033         }
15034     }
15035 
15036     /**
15037      * Returns the current visibility of the window this view is attached to
15038      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
15039      *
15040      * @return Returns the current visibility of the view's window.
15041      */
15042     @Visibility
getWindowVisibility()15043     public int getWindowVisibility() {
15044         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
15045     }
15046 
15047     /**
15048      * Retrieve the overall visible display size in which the window this view is
15049      * attached to has been positioned in.  This takes into account screen
15050      * decorations above the window, for both cases where the window itself
15051      * is being position inside of them or the window is being placed under
15052      * then and covered insets are used for the window to position its content
15053      * inside.  In effect, this tells you the available area where content can
15054      * be placed and remain visible to users.
15055      *
15056      * @param outRect Filled in with the visible display frame.  If the view
15057      * is not attached to a window, this is simply the raw display size.
15058      */
getWindowVisibleDisplayFrame(Rect outRect)15059     public void getWindowVisibleDisplayFrame(Rect outRect) {
15060         if (mAttachInfo != null) {
15061             mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
15062             return;
15063         }
15064         // The view is not attached to a display so we don't have a context.
15065         // Make a best guess about the display size.
15066         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
15067         d.getRectSize(outRect);
15068     }
15069 
15070     /**
15071      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
15072      * is currently in without any insets.
15073      *
15074      * @hide
15075      */
15076     @UnsupportedAppUsage
getWindowDisplayFrame(Rect outRect)15077     public void getWindowDisplayFrame(Rect outRect) {
15078         if (mAttachInfo != null) {
15079             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
15080             return;
15081         }
15082         // The view is not attached to a display so we don't have a context.
15083         // Make a best guess about the display size.
15084         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
15085         d.getRectSize(outRect);
15086     }
15087 
15088     /**
15089      * Dispatch a notification about a resource configuration change down
15090      * the view hierarchy.
15091      * ViewGroups should override to route to their children.
15092      *
15093      * @param newConfig The new resource configuration.
15094      *
15095      * @see #onConfigurationChanged(android.content.res.Configuration)
15096      */
dispatchConfigurationChanged(Configuration newConfig)15097     public void dispatchConfigurationChanged(Configuration newConfig) {
15098         onConfigurationChanged(newConfig);
15099     }
15100 
15101     /**
15102      * Called when the current configuration of the resources being used
15103      * by the application have changed.  You can use this to decide when
15104      * to reload resources that can changed based on orientation and other
15105      * configuration characteristics.  You only need to use this if you are
15106      * not relying on the normal {@link android.app.Activity} mechanism of
15107      * recreating the activity instance upon a configuration change.
15108      *
15109      * @param newConfig The new resource configuration.
15110      */
onConfigurationChanged(Configuration newConfig)15111     protected void onConfigurationChanged(Configuration newConfig) {
15112     }
15113 
15114     /**
15115      * Private function to aggregate all per-view attributes in to the view
15116      * root.
15117      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)15118     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
15119         performCollectViewAttributes(attachInfo, visibility);
15120     }
15121 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)15122     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
15123         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
15124             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
15125                 attachInfo.mKeepScreenOn = true;
15126             }
15127             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
15128             ListenerInfo li = mListenerInfo;
15129             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15130                 attachInfo.mHasSystemUiListeners = true;
15131             }
15132         }
15133     }
15134 
needGlobalAttributesUpdate(boolean force)15135     void needGlobalAttributesUpdate(boolean force) {
15136         final AttachInfo ai = mAttachInfo;
15137         if (ai != null && !ai.mRecomputeGlobalAttributes) {
15138             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
15139                     || ai.mHasSystemUiListeners) {
15140                 ai.mRecomputeGlobalAttributes = true;
15141             }
15142         }
15143     }
15144 
15145     /**
15146      * Returns whether the device is currently in touch mode.  Touch mode is entered
15147      * once the user begins interacting with the device by touch, and affects various
15148      * things like whether focus is always visible to the user.
15149      *
15150      * @return Whether the device is in touch mode.
15151      */
15152     @ViewDebug.ExportedProperty
isInTouchMode()15153     public boolean isInTouchMode() {
15154         if (mAttachInfo != null) {
15155             return mAttachInfo.mInTouchMode;
15156         } else {
15157             return ViewRootImpl.isInTouchMode();
15158         }
15159     }
15160 
15161     /**
15162      * Returns the context the view is running in, through which it can
15163      * access the current theme, resources, etc.
15164      *
15165      * @return The view's Context.
15166      */
15167     @ViewDebug.CapturedViewProperty
15168     @UiContext
getContext()15169     public final Context getContext() {
15170         return mContext;
15171     }
15172 
15173     /**
15174      * Handle a key event before it is processed by any input method
15175      * associated with the view hierarchy.  This can be used to intercept
15176      * key events in special situations before the IME consumes them; a
15177      * typical example would be handling the BACK key to update the application's
15178      * UI instead of allowing the IME to see it and close itself.
15179      *
15180      * @param keyCode The value in event.getKeyCode().
15181      * @param event Description of the key event.
15182      * @return If you handled the event, return true. If you want to allow the
15183      *         event to be handled by the next receiver, return false.
15184      */
onKeyPreIme(int keyCode, KeyEvent event)15185     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
15186         return false;
15187     }
15188 
15189     /**
15190      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
15191      * KeyEvent.Callback.onKeyDown()}: perform press of the view
15192      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
15193      * is released, if the view is enabled and clickable.
15194      * <p>
15195      * Key presses in software keyboards will generally NOT trigger this
15196      * listener, although some may elect to do so in some situations. Do not
15197      * rely on this to catch software key presses.
15198      *
15199      * @param keyCode a key code that represents the button pressed, from
15200      *                {@link android.view.KeyEvent}
15201      * @param event the KeyEvent object that defines the button action
15202      */
onKeyDown(int keyCode, KeyEvent event)15203     public boolean onKeyDown(int keyCode, KeyEvent event) {
15204         if (KeyEvent.isConfirmKey(keyCode)) {
15205             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15206                 return true;
15207             }
15208 
15209             if (event.getRepeatCount() == 0) {
15210                 // Long clickable items don't necessarily have to be clickable.
15211                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
15212                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
15213                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
15214                     // For the purposes of menu anchoring and drawable hotspots,
15215                     // key events are considered to be at the center of the view.
15216                     final float x = getWidth() / 2f;
15217                     final float y = getHeight() / 2f;
15218                     if (clickable) {
15219                         setPressed(true, x, y);
15220                     }
15221                     checkForLongClick(
15222                             ViewConfiguration.getLongPressTimeout(),
15223                             x,
15224                             y,
15225                             // This is not a touch gesture -- do not classify it as one.
15226                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
15227                     return true;
15228                 }
15229             }
15230         }
15231 
15232         return false;
15233     }
15234 
15235     /**
15236      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
15237      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
15238      * the event).
15239      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15240      * although some may elect to do so in some situations. Do not rely on this to
15241      * catch software key presses.
15242      */
onKeyLongPress(int keyCode, KeyEvent event)15243     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
15244         return false;
15245     }
15246 
15247     /**
15248      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
15249      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
15250      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
15251      * or {@link KeyEvent#KEYCODE_SPACE} is released.
15252      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15253      * although some may elect to do so in some situations. Do not rely on this to
15254      * catch software key presses.
15255      *
15256      * @param keyCode A key code that represents the button pressed, from
15257      *                {@link android.view.KeyEvent}.
15258      * @param event   The KeyEvent object that defines the button action.
15259      */
onKeyUp(int keyCode, KeyEvent event)15260     public boolean onKeyUp(int keyCode, KeyEvent event) {
15261         if (KeyEvent.isConfirmKey(keyCode)) {
15262             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15263                 return true;
15264             }
15265             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
15266                 setPressed(false);
15267 
15268                 if (!mHasPerformedLongPress) {
15269                     // This is a tap, so remove the longpress check
15270                     removeLongPressCallback();
15271                     if (!event.isCanceled()) {
15272                         return performClickInternal();
15273                     }
15274                 }
15275             }
15276         }
15277         return false;
15278     }
15279 
15280     /**
15281      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
15282      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
15283      * the event).
15284      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15285      * although some may elect to do so in some situations. Do not rely on this to
15286      * catch software key presses.
15287      *
15288      * @param keyCode     A key code that represents the button pressed, from
15289      *                    {@link android.view.KeyEvent}.
15290      * @param repeatCount The number of times the action was made.
15291      * @param event       The KeyEvent object that defines the button action.
15292      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)15293     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
15294         return false;
15295     }
15296 
15297     /**
15298      * Called on the focused view when a key shortcut event is not handled.
15299      * Override this method to implement local key shortcuts for the View.
15300      * Key shortcuts can also be implemented by setting the
15301      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
15302      *
15303      * @param keyCode The value in event.getKeyCode().
15304      * @param event Description of the key event.
15305      * @return If you handled the event, return true. If you want to allow the
15306      *         event to be handled by the next receiver, return false.
15307      */
onKeyShortcut(int keyCode, KeyEvent event)15308     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
15309         return false;
15310     }
15311 
15312     /**
15313      * Check whether the called view is a text editor, in which case it
15314      * would make sense to automatically display a soft input window for
15315      * it.  Subclasses should override this if they implement
15316      * {@link #onCreateInputConnection(EditorInfo)} to return true if
15317      * a call on that method would return a non-null InputConnection, and
15318      * they are really a first-class editor that the user would normally
15319      * start typing on when the go into a window containing your view.
15320      *
15321      * <p>The default implementation always returns false.  This does
15322      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
15323      * will not be called or the user can not otherwise perform edits on your
15324      * view; it is just a hint to the system that this is not the primary
15325      * purpose of this view.
15326      *
15327      * @return Returns true if this view is a text editor, else false.
15328      */
onCheckIsTextEditor()15329     public boolean onCheckIsTextEditor() {
15330         return false;
15331     }
15332 
15333     /**
15334      * Create a new InputConnection for an InputMethod to interact
15335      * with the view.  The default implementation returns null, since it doesn't
15336      * support input methods.  You can override this to implement such support.
15337      * This is only needed for views that take focus and text input.
15338      *
15339      * <p>When implementing this, you probably also want to implement
15340      * {@link #onCheckIsTextEditor()} to indicate you will return a
15341      * non-null InputConnection.</p>
15342      *
15343      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
15344      * object correctly and in its entirety, so that the connected IME can rely
15345      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
15346      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
15347      * must be filled in with the correct cursor position for IMEs to work correctly
15348      * with your application.</p>
15349      *
15350      * @param outAttrs Fill in with attribute information about the connection.
15351      */
onCreateInputConnection(EditorInfo outAttrs)15352     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
15353         return null;
15354     }
15355 
15356     /**
15357      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
15358      * that the system has successfully initialized an {@link InputConnection} and it is ready for
15359      * use.
15360      *
15361      * <p>The default implementation does nothing, since a view doesn't support input methods by
15362      * default (see {@link #onCreateInputConnection}).
15363      *
15364      * @param inputConnection The {@link InputConnection} from {@link #onCreateInputConnection},
15365      * after it's been fully initialized by the system.
15366      * @param editorInfo The {@link EditorInfo} that was used to create the {@link InputConnection}.
15367      * @param handler The dedicated {@link Handler} on which IPC method calls from input methods
15368      * will be dispatched. This is the handler returned by {@link InputConnection#getHandler()}. If
15369      * that method returns null, this parameter will be null also.
15370      *
15371      * @hide
15372      */
onInputConnectionOpenedInternal(@onNull InputConnection inputConnection, @NonNull EditorInfo editorInfo, @Nullable Handler handler)15373     public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
15374             @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
15375 
15376     /**
15377      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
15378      * that the {@link InputConnection} has been closed.
15379      *
15380      * <p>The default implementation does nothing, since a view doesn't support input methods by
15381      * default (see {@link #onCreateInputConnection}).
15382      *
15383      * <p><strong>Note:</strong> This callback is not invoked if the view is already detached when
15384      * the {@link InputConnection} is closed or the connection is not valid and managed by
15385      * {@link com.android.server.inputmethod.InputMethodManagerService}.
15386      * TODO(b/170645312): Before un-hiding this API, handle the detached view scenario.
15387      *
15388      * @hide
15389      */
onInputConnectionClosedInternal()15390     public void onInputConnectionClosedInternal() {}
15391 
15392     /**
15393      * Called by the {@link android.view.inputmethod.InputMethodManager}
15394      * when a view who is not the current
15395      * input connection target is trying to make a call on the manager.  The
15396      * default implementation returns false; you can override this to return
15397      * true for certain views if you are performing InputConnection proxying
15398      * to them.
15399      * @param view The View that is making the InputMethodManager call.
15400      * @return Return true to allow the call, false to reject.
15401      */
checkInputConnectionProxy(View view)15402     public boolean checkInputConnectionProxy(View view) {
15403         return false;
15404     }
15405 
15406     /**
15407      * Show the context menu for this view. It is not safe to hold on to the
15408      * menu after returning from this method.
15409      *
15410      * You should normally not overload this method. Overload
15411      * {@link #onCreateContextMenu(ContextMenu)} or define an
15412      * {@link OnCreateContextMenuListener} to add items to the context menu.
15413      *
15414      * @param menu The context menu to populate
15415      */
createContextMenu(ContextMenu menu)15416     public void createContextMenu(ContextMenu menu) {
15417         ContextMenuInfo menuInfo = getContextMenuInfo();
15418 
15419         // Sets the current menu info so all items added to menu will have
15420         // my extra info set.
15421         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
15422 
15423         onCreateContextMenu(menu);
15424         ListenerInfo li = mListenerInfo;
15425         if (li != null && li.mOnCreateContextMenuListener != null) {
15426             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
15427         }
15428 
15429         // Clear the extra information so subsequent items that aren't mine don't
15430         // have my extra info.
15431         ((MenuBuilder)menu).setCurrentMenuInfo(null);
15432 
15433         if (mParent != null) {
15434             mParent.createContextMenu(menu);
15435         }
15436     }
15437 
15438     /**
15439      * Views should implement this if they have extra information to associate
15440      * with the context menu. The return result is supplied as a parameter to
15441      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
15442      * callback.
15443      *
15444      * @return Extra information about the item for which the context menu
15445      *         should be shown. This information will vary across different
15446      *         subclasses of View.
15447      */
getContextMenuInfo()15448     protected ContextMenuInfo getContextMenuInfo() {
15449         return null;
15450     }
15451 
15452     /**
15453      * Views should implement this if the view itself is going to add items to
15454      * the context menu.
15455      *
15456      * @param menu the context menu to populate
15457      */
onCreateContextMenu(ContextMenu menu)15458     protected void onCreateContextMenu(ContextMenu menu) {
15459     }
15460 
15461     /**
15462      * Implement this method to handle trackball motion events.  The
15463      * <em>relative</em> movement of the trackball since the last event
15464      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
15465      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
15466      * that a movement of 1 corresponds to the user pressing one DPAD key (so
15467      * they will often be fractional values, representing the more fine-grained
15468      * movement information available from a trackball).
15469      *
15470      * @param event The motion event.
15471      * @return True if the event was handled, false otherwise.
15472      */
onTrackballEvent(MotionEvent event)15473     public boolean onTrackballEvent(MotionEvent event) {
15474         return false;
15475     }
15476 
15477     /**
15478      * Implement this method to handle generic motion events.
15479      * <p>
15480      * Generic motion events describe joystick movements, mouse hovers, track pad
15481      * touches, scroll wheel movements and other input events.  The
15482      * {@link MotionEvent#getSource() source} of the motion event specifies
15483      * the class of input that was received.  Implementations of this method
15484      * must examine the bits in the source before processing the event.
15485      * The following code example shows how this is done.
15486      * </p><p>
15487      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
15488      * are delivered to the view under the pointer.  All other generic motion events are
15489      * delivered to the focused view.
15490      * </p>
15491      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
15492      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
15493      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
15494      *             // process the joystick movement...
15495      *             return true;
15496      *         }
15497      *     }
15498      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
15499      *         switch (event.getAction()) {
15500      *             case MotionEvent.ACTION_HOVER_MOVE:
15501      *                 // process the mouse hover movement...
15502      *                 return true;
15503      *             case MotionEvent.ACTION_SCROLL:
15504      *                 // process the scroll wheel movement...
15505      *                 return true;
15506      *         }
15507      *     }
15508      *     return super.onGenericMotionEvent(event);
15509      * }</pre>
15510      *
15511      * @param event The generic motion event being processed.
15512      * @return True if the event was handled, false otherwise.
15513      */
onGenericMotionEvent(MotionEvent event)15514     public boolean onGenericMotionEvent(MotionEvent event) {
15515         return false;
15516     }
15517 
15518     /**
15519      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
15520      * <p>
15521      * This method is dispatching hover events to the delegate target to support explore by touch.
15522      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
15523      * the delegate target according to the pointer and the touch area of the delegate while touch
15524      * exploration enabled.
15525      * </p>
15526      *
15527      * @param event The motion event dispatch to the delegate target.
15528      * @return True if the event was handled, false otherwise.
15529      *
15530      * @see #onHoverEvent
15531      */
dispatchTouchExplorationHoverEvent(MotionEvent event)15532     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
15533         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
15534         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
15535             return false;
15536         }
15537 
15538         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
15539         final int action = event.getActionMasked();
15540         boolean pointInDelegateRegion = false;
15541         boolean handled = false;
15542 
15543         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
15544         for (int i = 0; i < info.getRegionCount(); i++) {
15545             Region r = info.getRegionAt(i);
15546             if (r.contains((int) event.getX(), (int) event.getY())) {
15547                 pointInDelegateRegion = true;
15548             }
15549         }
15550 
15551         // Explore by touch should dispatch events to children under the pointer first if any
15552         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
15553         // hover events but receive accessibility focus, it should also not delegate to these
15554         // views when hovered.
15555         if (!oldHoveringTouchDelegate) {
15556             if ((action == MotionEvent.ACTION_HOVER_ENTER
15557                     || action == MotionEvent.ACTION_HOVER_MOVE)
15558                     && !pointInHoveredChild(event)
15559                     && pointInDelegateRegion) {
15560                 mHoveringTouchDelegate = true;
15561             }
15562         } else {
15563             if (action == MotionEvent.ACTION_HOVER_EXIT
15564                     || (action == MotionEvent.ACTION_HOVER_MOVE
15565                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
15566                 mHoveringTouchDelegate = false;
15567             }
15568         }
15569         switch (action) {
15570             case MotionEvent.ACTION_HOVER_MOVE:
15571                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15572                     // Inside bounds, dispatch as is.
15573                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
15574                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15575                     // Moving inbound, synthesize hover enter.
15576                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
15577                             ? event : MotionEvent.obtainNoHistory(event);
15578                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
15579                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15580                     eventNoHistory.setAction(action);
15581                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15582                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
15583                     // Moving outbound, synthesize hover exit.
15584                     final boolean hoverExitPending = event.isHoverExitPending();
15585                     event.setHoverExitPending(true);
15586                     mTouchDelegate.onTouchExplorationHoverEvent(event);
15587                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
15588                             ? event : MotionEvent.obtainNoHistory(event);
15589                     eventNoHistory.setHoverExitPending(hoverExitPending);
15590                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
15591                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15592                 }  // else: outside bounds, do nothing.
15593                 break;
15594             case MotionEvent.ACTION_HOVER_ENTER:
15595                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15596                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
15597                 }
15598                 break;
15599             case MotionEvent.ACTION_HOVER_EXIT:
15600                 if (oldHoveringTouchDelegate) {
15601                     mTouchDelegate.onTouchExplorationHoverEvent(event);
15602                 }
15603                 break;
15604         }
15605         return handled;
15606     }
15607 
15608     /**
15609      * Implement this method to handle hover events.
15610      * <p>
15611      * This method is called whenever a pointer is hovering into, over, or out of the
15612      * bounds of a view and the view is not currently being touched.
15613      * Hover events are represented as pointer events with action
15614      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
15615      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
15616      * </p>
15617      * <ul>
15618      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
15619      * when the pointer enters the bounds of the view.</li>
15620      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
15621      * when the pointer has already entered the bounds of the view and has moved.</li>
15622      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
15623      * when the pointer has exited the bounds of the view or when the pointer is
15624      * about to go down due to a button click, tap, or similar user action that
15625      * causes the view to be touched.</li>
15626      * </ul>
15627      * <p>
15628      * The view should implement this method to return true to indicate that it is
15629      * handling the hover event, such as by changing its drawable state.
15630      * </p><p>
15631      * The default implementation calls {@link #setHovered} to update the hovered state
15632      * of the view when a hover enter or hover exit event is received, if the view
15633      * is enabled and is clickable.  The default implementation also sends hover
15634      * accessibility events.
15635      * </p>
15636      *
15637      * @param event The motion event that describes the hover.
15638      * @return True if the view handled the hover event.
15639      *
15640      * @see #isHovered
15641      * @see #setHovered
15642      * @see #onHoverChanged
15643      */
onHoverEvent(MotionEvent event)15644     public boolean onHoverEvent(MotionEvent event) {
15645         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
15646             return true;
15647         }
15648 
15649         // The root view may receive hover (or touch) events that are outside the bounds of
15650         // the window.  This code ensures that we only send accessibility events for
15651         // hovers that are actually within the bounds of the root view.
15652         final int action = event.getActionMasked();
15653         if (!mSendingHoverAccessibilityEvents) {
15654             if ((action == MotionEvent.ACTION_HOVER_ENTER
15655                     || action == MotionEvent.ACTION_HOVER_MOVE)
15656                     && !hasHoveredChild()
15657                     && pointInView(event.getX(), event.getY())) {
15658                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
15659                 mSendingHoverAccessibilityEvents = true;
15660             }
15661         } else {
15662             if (action == MotionEvent.ACTION_HOVER_EXIT
15663                     || (action == MotionEvent.ACTION_HOVER_MOVE
15664                             && !pointInView(event.getX(), event.getY()))) {
15665                 mSendingHoverAccessibilityEvents = false;
15666                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
15667             }
15668         }
15669 
15670         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
15671                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
15672                 && isOnScrollbar(event.getX(), event.getY())) {
15673             awakenScrollBars();
15674         }
15675 
15676         // If we consider ourself hoverable, or if we we're already hovered,
15677         // handle changing state in response to ENTER and EXIT events.
15678         if (isHoverable() || isHovered()) {
15679             switch (action) {
15680                 case MotionEvent.ACTION_HOVER_ENTER:
15681                     setHovered(true);
15682                     break;
15683                 case MotionEvent.ACTION_HOVER_EXIT:
15684                     setHovered(false);
15685                     break;
15686             }
15687 
15688             // Dispatch the event to onGenericMotionEvent before returning true.
15689             // This is to provide compatibility with existing applications that
15690             // handled HOVER_MOVE events in onGenericMotionEvent and that would
15691             // break because of the new default handling for hoverable views
15692             // in onHoverEvent.
15693             // Note that onGenericMotionEvent will be called by default when
15694             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
15695             dispatchGenericMotionEventInternal(event);
15696             // The event was already handled by calling setHovered(), so always
15697             // return true.
15698             return true;
15699         }
15700 
15701         return false;
15702     }
15703 
15704     /**
15705      * Returns true if the view should handle {@link #onHoverEvent}
15706      * by calling {@link #setHovered} to change its hovered state.
15707      *
15708      * @return True if the view is hoverable.
15709      */
isHoverable()15710     private boolean isHoverable() {
15711         final int viewFlags = mViewFlags;
15712         if ((viewFlags & ENABLED_MASK) == DISABLED) {
15713             return false;
15714         }
15715 
15716         return (viewFlags & CLICKABLE) == CLICKABLE
15717                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
15718                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15719     }
15720 
15721     /**
15722      * Returns true if the view is currently hovered.
15723      *
15724      * @return True if the view is currently hovered.
15725      *
15726      * @see #setHovered
15727      * @see #onHoverChanged
15728      */
15729     @ViewDebug.ExportedProperty
isHovered()15730     public boolean isHovered() {
15731         return (mPrivateFlags & PFLAG_HOVERED) != 0;
15732     }
15733 
15734     /**
15735      * Sets whether the view is currently hovered.
15736      * <p>
15737      * Calling this method also changes the drawable state of the view.  This
15738      * enables the view to react to hover by using different drawable resources
15739      * to change its appearance.
15740      * </p><p>
15741      * The {@link #onHoverChanged} method is called when the hovered state changes.
15742      * </p>
15743      *
15744      * @param hovered True if the view is hovered.
15745      *
15746      * @see #isHovered
15747      * @see #onHoverChanged
15748      */
setHovered(boolean hovered)15749     public void setHovered(boolean hovered) {
15750         if (hovered) {
15751             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
15752                 mPrivateFlags |= PFLAG_HOVERED;
15753                 refreshDrawableState();
15754                 onHoverChanged(true);
15755             }
15756         } else {
15757             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
15758                 mPrivateFlags &= ~PFLAG_HOVERED;
15759                 refreshDrawableState();
15760                 onHoverChanged(false);
15761             }
15762         }
15763     }
15764 
15765     /**
15766      * Implement this method to handle hover state changes.
15767      * <p>
15768      * This method is called whenever the hover state changes as a result of a
15769      * call to {@link #setHovered}.
15770      * </p>
15771      *
15772      * @param hovered The current hover state, as returned by {@link #isHovered}.
15773      *
15774      * @see #isHovered
15775      * @see #setHovered
15776      */
onHoverChanged(boolean hovered)15777     public void onHoverChanged(boolean hovered) {
15778     }
15779 
15780     /**
15781      * Handles scroll bar dragging by mouse input.
15782      *
15783      * @hide
15784      * @param event The motion event.
15785      *
15786      * @return true if the event was handled as a scroll bar dragging, false otherwise.
15787      */
handleScrollBarDragging(MotionEvent event)15788     protected boolean handleScrollBarDragging(MotionEvent event) {
15789         if (mScrollCache == null) {
15790             return false;
15791         }
15792         final float x = event.getX();
15793         final float y = event.getY();
15794         final int action = event.getAction();
15795         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
15796                 && action != MotionEvent.ACTION_DOWN)
15797                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
15798                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
15799             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15800             return false;
15801         }
15802 
15803         switch (action) {
15804             case MotionEvent.ACTION_MOVE:
15805                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
15806                     return false;
15807                 }
15808                 if (mScrollCache.mScrollBarDraggingState
15809                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
15810                     final Rect bounds = mScrollCache.mScrollBarBounds;
15811                     getVerticalScrollBarBounds(bounds, null);
15812                     final int range = computeVerticalScrollRange();
15813                     final int offset = computeVerticalScrollOffset();
15814                     final int extent = computeVerticalScrollExtent();
15815 
15816                     final int thumbLength = ScrollBarUtils.getThumbLength(
15817                             bounds.height(), bounds.width(), extent, range);
15818                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15819                             bounds.height(), thumbLength, extent, range, offset);
15820 
15821                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
15822                     final float maxThumbOffset = bounds.height() - thumbLength;
15823                     final float newThumbOffset =
15824                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15825                     final int height = getHeight();
15826                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15827                             && height > 0 && extent > 0) {
15828                         final int newY = Math.round((range - extent)
15829                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
15830                         if (newY != getScrollY()) {
15831                             mScrollCache.mScrollBarDraggingPos = y;
15832                             setScrollY(newY);
15833                         }
15834                     }
15835                     return true;
15836                 }
15837                 if (mScrollCache.mScrollBarDraggingState
15838                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
15839                     final Rect bounds = mScrollCache.mScrollBarBounds;
15840                     getHorizontalScrollBarBounds(bounds, null);
15841                     final int range = computeHorizontalScrollRange();
15842                     final int offset = computeHorizontalScrollOffset();
15843                     final int extent = computeHorizontalScrollExtent();
15844 
15845                     final int thumbLength = ScrollBarUtils.getThumbLength(
15846                             bounds.width(), bounds.height(), extent, range);
15847                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15848                             bounds.width(), thumbLength, extent, range, offset);
15849 
15850                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
15851                     final float maxThumbOffset = bounds.width() - thumbLength;
15852                     final float newThumbOffset =
15853                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15854                     final int width = getWidth();
15855                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15856                             && width > 0 && extent > 0) {
15857                         final int newX = Math.round((range - extent)
15858                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
15859                         if (newX != getScrollX()) {
15860                             mScrollCache.mScrollBarDraggingPos = x;
15861                             setScrollX(newX);
15862                         }
15863                     }
15864                     return true;
15865                 }
15866             case MotionEvent.ACTION_DOWN:
15867                 if (mScrollCache.state == ScrollabilityCache.OFF) {
15868                     return false;
15869                 }
15870                 if (isOnVerticalScrollbarThumb(x, y)) {
15871                     mScrollCache.mScrollBarDraggingState =
15872                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
15873                     mScrollCache.mScrollBarDraggingPos = y;
15874                     return true;
15875                 }
15876                 if (isOnHorizontalScrollbarThumb(x, y)) {
15877                     mScrollCache.mScrollBarDraggingState =
15878                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
15879                     mScrollCache.mScrollBarDraggingPos = x;
15880                     return true;
15881                 }
15882         }
15883         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15884         return false;
15885     }
15886 
15887     /**
15888      * Implement this method to handle touch screen motion events.
15889      * <p>
15890      * If this method is used to detect click actions, it is recommended that
15891      * the actions be performed by implementing and calling
15892      * {@link #performClick()}. This will ensure consistent system behavior,
15893      * including:
15894      * <ul>
15895      * <li>obeying click sound preferences
15896      * <li>dispatching OnClickListener calls
15897      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
15898      * accessibility features are enabled
15899      * </ul>
15900      *
15901      * @param event The motion event.
15902      * @return True if the event was handled, false otherwise.
15903      */
onTouchEvent(MotionEvent event)15904     public boolean onTouchEvent(MotionEvent event) {
15905         final float x = event.getX();
15906         final float y = event.getY();
15907         final int viewFlags = mViewFlags;
15908         final int action = event.getAction();
15909 
15910         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
15911                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
15912                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15913 
15914         if ((viewFlags & ENABLED_MASK) == DISABLED
15915                 && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
15916             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
15917                 setPressed(false);
15918             }
15919             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15920             // A disabled view that is clickable still consumes the touch
15921             // events, it just doesn't respond to them.
15922             return clickable;
15923         }
15924         if (mTouchDelegate != null) {
15925             if (mTouchDelegate.onTouchEvent(event)) {
15926                 return true;
15927             }
15928         }
15929 
15930         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
15931             switch (action) {
15932                 case MotionEvent.ACTION_UP:
15933                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15934                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
15935                         handleTooltipUp();
15936                     }
15937                     if (!clickable) {
15938                         removeTapCallback();
15939                         removeLongPressCallback();
15940                         mInContextButtonPress = false;
15941                         mHasPerformedLongPress = false;
15942                         mIgnoreNextUpEvent = false;
15943                         break;
15944                     }
15945                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
15946                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
15947                         // take focus if we don't have it already and we should in
15948                         // touch mode.
15949                         boolean focusTaken = false;
15950                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
15951                             focusTaken = requestFocus();
15952                         }
15953 
15954                         if (prepressed) {
15955                             // The button is being released before we actually
15956                             // showed it as pressed.  Make it show the pressed
15957                             // state now (before scheduling the click) to ensure
15958                             // the user sees it.
15959                             setPressed(true, x, y);
15960                         }
15961 
15962                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
15963                             // This is a tap, so remove the longpress check
15964                             removeLongPressCallback();
15965 
15966                             // Only perform take click actions if we were in the pressed state
15967                             if (!focusTaken) {
15968                                 // Use a Runnable and post this rather than calling
15969                                 // performClick directly. This lets other visual state
15970                                 // of the view update before click actions start.
15971                                 if (mPerformClick == null) {
15972                                     mPerformClick = new PerformClick();
15973                                 }
15974                                 if (!post(mPerformClick)) {
15975                                     performClickInternal();
15976                                 }
15977                             }
15978                         }
15979 
15980                         if (mUnsetPressedState == null) {
15981                             mUnsetPressedState = new UnsetPressedState();
15982                         }
15983 
15984                         if (prepressed) {
15985                             postDelayed(mUnsetPressedState,
15986                                     ViewConfiguration.getPressedStateDuration());
15987                         } else if (!post(mUnsetPressedState)) {
15988                             // If the post failed, unpress right now
15989                             mUnsetPressedState.run();
15990                         }
15991 
15992                         removeTapCallback();
15993                     }
15994                     mIgnoreNextUpEvent = false;
15995                     break;
15996 
15997                 case MotionEvent.ACTION_DOWN:
15998                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
15999                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
16000                     }
16001                     mHasPerformedLongPress = false;
16002 
16003                     if (!clickable) {
16004                         checkForLongClick(
16005                                 ViewConfiguration.getLongPressTimeout(),
16006                                 x,
16007                                 y,
16008                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16009                         break;
16010                     }
16011 
16012                     if (performButtonActionOnTouchDown(event)) {
16013                         break;
16014                     }
16015 
16016                     // Walk up the hierarchy to determine if we're inside a scrolling container.
16017                     boolean isInScrollingContainer = isInScrollingContainer();
16018 
16019                     // For views inside a scrolling container, delay the pressed feedback for
16020                     // a short period in case this is a scroll.
16021                     if (isInScrollingContainer) {
16022                         mPrivateFlags |= PFLAG_PREPRESSED;
16023                         if (mPendingCheckForTap == null) {
16024                             mPendingCheckForTap = new CheckForTap();
16025                         }
16026                         mPendingCheckForTap.x = event.getX();
16027                         mPendingCheckForTap.y = event.getY();
16028                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
16029                     } else {
16030                         // Not inside a scrolling container, so show the feedback right away
16031                         setPressed(true, x, y);
16032                         checkForLongClick(
16033                                 ViewConfiguration.getLongPressTimeout(),
16034                                 x,
16035                                 y,
16036                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16037                     }
16038                     break;
16039 
16040                 case MotionEvent.ACTION_CANCEL:
16041                     if (clickable) {
16042                         setPressed(false);
16043                     }
16044                     removeTapCallback();
16045                     removeLongPressCallback();
16046                     mInContextButtonPress = false;
16047                     mHasPerformedLongPress = false;
16048                     mIgnoreNextUpEvent = false;
16049                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16050                     break;
16051 
16052                 case MotionEvent.ACTION_MOVE:
16053                     if (clickable) {
16054                         drawableHotspotChanged(x, y);
16055                     }
16056 
16057                     final int motionClassification = event.getClassification();
16058                     final boolean ambiguousGesture =
16059                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
16060                     int touchSlop = mTouchSlop;
16061                     if (ambiguousGesture && hasPendingLongPressCallback()) {
16062                         if (!pointInView(x, y, touchSlop)) {
16063                             // The default action here is to cancel long press. But instead, we
16064                             // just extend the timeout here, in case the classification
16065                             // stays ambiguous.
16066                             removeLongPressCallback();
16067                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
16068                                     * mAmbiguousGestureMultiplier);
16069                             // Subtract the time already spent
16070                             delay -= event.getEventTime() - event.getDownTime();
16071                             checkForLongClick(
16072                                     delay,
16073                                     x,
16074                                     y,
16075                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
16076                         }
16077                         touchSlop *= mAmbiguousGestureMultiplier;
16078                     }
16079 
16080                     // Be lenient about moving outside of buttons
16081                     if (!pointInView(x, y, touchSlop)) {
16082                         // Outside button
16083                         // Remove any future long press/tap checks
16084                         removeTapCallback();
16085                         removeLongPressCallback();
16086                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
16087                             setPressed(false);
16088                         }
16089                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16090                     }
16091 
16092                     final boolean deepPress =
16093                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
16094                     if (deepPress && hasPendingLongPressCallback()) {
16095                         // process the long click action immediately
16096                         removeLongPressCallback();
16097                         checkForLongClick(
16098                                 0 /* send immediately */,
16099                                 x,
16100                                 y,
16101                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
16102                     }
16103 
16104                     break;
16105             }
16106 
16107             return true;
16108         }
16109 
16110         return false;
16111     }
16112 
16113     /**
16114      * @hide
16115      */
16116     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInScrollingContainer()16117     public boolean isInScrollingContainer() {
16118         ViewParent p = getParent();
16119         while (p != null && p instanceof ViewGroup) {
16120             if (((ViewGroup) p).shouldDelayChildPressedState()) {
16121                 return true;
16122             }
16123             p = p.getParent();
16124         }
16125         return false;
16126     }
16127 
16128     /**
16129      * Remove the longpress detection timer.
16130      */
removeLongPressCallback()16131     private void removeLongPressCallback() {
16132         if (mPendingCheckForLongPress != null) {
16133             removeCallbacks(mPendingCheckForLongPress);
16134         }
16135     }
16136 
16137     /**
16138      * Return true if the long press callback is scheduled to run sometime in the future.
16139      * Return false if there is no scheduled long press callback at the moment.
16140      */
hasPendingLongPressCallback()16141     private boolean hasPendingLongPressCallback() {
16142         if (mPendingCheckForLongPress == null) {
16143             return false;
16144         }
16145         final AttachInfo attachInfo = mAttachInfo;
16146         if (attachInfo == null) {
16147             return false;
16148         }
16149         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
16150     }
16151 
16152    /**
16153      * Remove the pending click action
16154      */
16155     @UnsupportedAppUsage
removePerformClickCallback()16156     private void removePerformClickCallback() {
16157         if (mPerformClick != null) {
16158             removeCallbacks(mPerformClick);
16159         }
16160     }
16161 
16162     /**
16163      * Remove the prepress detection timer.
16164      */
removeUnsetPressCallback()16165     private void removeUnsetPressCallback() {
16166         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
16167             setPressed(false);
16168             removeCallbacks(mUnsetPressedState);
16169         }
16170     }
16171 
16172     /**
16173      * Remove the tap detection timer.
16174      */
removeTapCallback()16175     private void removeTapCallback() {
16176         if (mPendingCheckForTap != null) {
16177             mPrivateFlags &= ~PFLAG_PREPRESSED;
16178             removeCallbacks(mPendingCheckForTap);
16179         }
16180     }
16181 
16182     /**
16183      * Cancels a pending long press.  Your subclass can use this if you
16184      * want the context menu to come up if the user presses and holds
16185      * at the same place, but you don't want it to come up if they press
16186      * and then move around enough to cause scrolling.
16187      */
cancelLongPress()16188     public void cancelLongPress() {
16189         removeLongPressCallback();
16190 
16191         /*
16192          * The prepressed state handled by the tap callback is a display
16193          * construct, but the tap callback will post a long press callback
16194          * less its own timeout. Remove it here.
16195          */
16196         removeTapCallback();
16197     }
16198 
16199     /**
16200      * Sets the TouchDelegate for this View.
16201      */
setTouchDelegate(TouchDelegate delegate)16202     public void setTouchDelegate(TouchDelegate delegate) {
16203         mTouchDelegate = delegate;
16204     }
16205 
16206     /**
16207      * Gets the TouchDelegate for this View.
16208      */
getTouchDelegate()16209     public TouchDelegate getTouchDelegate() {
16210         return mTouchDelegate;
16211     }
16212 
16213     /**
16214      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
16215      *
16216      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
16217      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
16218      * available. This method should only be called for touch events.
16219      *
16220      * <p class="note">This API is not intended for most applications. Buffered dispatch
16221      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
16222      * streams will not improve your input latency. Side effects include: increased latency,
16223      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
16224      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
16225      * you.</p>
16226      *
16227      * To receive unbuffered events for arbitrary input device source classes, use
16228      * {@link #requestUnbufferedDispatch(int)},
16229      *
16230      * @see View#requestUnbufferedDispatch(int)
16231      */
requestUnbufferedDispatch(MotionEvent event)16232     public final void requestUnbufferedDispatch(MotionEvent event) {
16233         final int action = event.getAction();
16234         if (mAttachInfo == null
16235                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
16236                 || !event.isTouchEvent()) {
16237             return;
16238         }
16239         mAttachInfo.mUnbufferedDispatchRequested = true;
16240     }
16241 
16242     /**
16243      * Request unbuffered dispatch of the given event source class to this view.
16244      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
16245      * automatically terminate, and allows the specification of arbitrary input source classes.
16246      *
16247      * @param source The combined input source class to request unbuffered dispatch for. All
16248      *               events coming from these source classes will not be buffered. Set to
16249      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
16250      *
16251      * @see View#requestUnbufferedDispatch(MotionEvent)
16252      */
requestUnbufferedDispatch(@nputSourceClass int source)16253     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
16254         if (mUnbufferedInputSource == source) {
16255             return;
16256         }
16257         mUnbufferedInputSource = source;
16258         if (mParent != null) {
16259             mParent.onDescendantUnbufferedRequested();
16260         }
16261     }
16262 
hasSize()16263     private boolean hasSize() {
16264         return (mBottom > mTop) && (mRight > mLeft);
16265     }
16266 
canTakeFocus()16267     private boolean canTakeFocus() {
16268         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
16269                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
16270                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
16271                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
16272     }
16273 
16274     /**
16275      * Set flags controlling behavior of this view.
16276      *
16277      * @param flags Constant indicating the value which should be set
16278      * @param mask Constant indicating the bit range that should be changed
16279      */
16280     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)16281     void setFlags(int flags, int mask) {
16282         final boolean accessibilityEnabled =
16283                 AccessibilityManager.getInstance(mContext).isEnabled();
16284         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
16285 
16286         int old = mViewFlags;
16287         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
16288 
16289         int changed = mViewFlags ^ old;
16290         if (changed == 0) {
16291             return;
16292         }
16293         int privateFlags = mPrivateFlags;
16294         boolean shouldNotifyFocusableAvailable = false;
16295 
16296         // If focusable is auto, update the FOCUSABLE bit.
16297         int focusableChangedByAuto = 0;
16298         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
16299                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
16300             // Heuristic only takes into account whether view is clickable.
16301             final int newFocus;
16302             if ((mViewFlags & CLICKABLE) != 0) {
16303                 newFocus = FOCUSABLE;
16304             } else {
16305                 newFocus = NOT_FOCUSABLE;
16306             }
16307             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
16308             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
16309             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
16310         }
16311 
16312         /* Check if the FOCUSABLE bit has changed */
16313         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
16314             if (((old & FOCUSABLE) == FOCUSABLE)
16315                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
16316                 /* Give up focus if we are no longer focusable */
16317                 clearFocus();
16318                 if (mParent instanceof ViewGroup) {
16319                     ((ViewGroup) mParent).clearFocusedInCluster();
16320                 }
16321             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
16322                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
16323                 /*
16324                  * Tell the view system that we are now available to take focus
16325                  * if no one else already has it.
16326                  */
16327                 if (mParent != null) {
16328                     ViewRootImpl viewRootImpl = getViewRootImpl();
16329                     if (!sAutoFocusableOffUIThreadWontNotifyParents
16330                             || focusableChangedByAuto == 0
16331                             || viewRootImpl == null
16332                             || viewRootImpl.mThread == Thread.currentThread()) {
16333                         shouldNotifyFocusableAvailable = canTakeFocus();
16334                     }
16335                 }
16336             }
16337         }
16338 
16339         final int newVisibility = flags & VISIBILITY_MASK;
16340         if (newVisibility == VISIBLE) {
16341             if ((changed & VISIBILITY_MASK) != 0) {
16342                 /*
16343                  * If this view is becoming visible, invalidate it in case it changed while
16344                  * it was not visible. Marking it drawn ensures that the invalidation will
16345                  * go through.
16346                  */
16347                 mPrivateFlags |= PFLAG_DRAWN;
16348                 invalidate(true);
16349 
16350                 needGlobalAttributesUpdate(true);
16351 
16352                 // a view becoming visible is worth notifying the parent about in case nothing has
16353                 // focus. Even if this specific view isn't focusable, it may contain something that
16354                 // is, so let the root view try to give this focus if nothing else does.
16355                 shouldNotifyFocusableAvailable = hasSize();
16356             }
16357         }
16358 
16359         if ((changed & ENABLED_MASK) != 0) {
16360             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
16361                 // a view becoming enabled should notify the parent as long as the view is also
16362                 // visible and the parent wasn't already notified by becoming visible during this
16363                 // setFlags invocation.
16364                 shouldNotifyFocusableAvailable = canTakeFocus();
16365             } else {
16366                 if (isFocused()) clearFocus();
16367             }
16368         }
16369 
16370         if (shouldNotifyFocusableAvailable && mParent != null) {
16371             mParent.focusableViewAvailable(this);
16372         }
16373 
16374         /* Check if the GONE bit has changed */
16375         if ((changed & GONE) != 0) {
16376             needGlobalAttributesUpdate(false);
16377             requestLayout();
16378 
16379             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
16380                 if (hasFocus()) {
16381                     clearFocus();
16382                     if (mParent instanceof ViewGroup) {
16383                         ((ViewGroup) mParent).clearFocusedInCluster();
16384                     }
16385                 }
16386                 clearAccessibilityFocus();
16387                 destroyDrawingCache();
16388                 if (mParent instanceof View) {
16389                     // GONE views noop invalidation, so invalidate the parent
16390                     ((View) mParent).invalidate(true);
16391                 }
16392                 // Mark the view drawn to ensure that it gets invalidated properly the next
16393                 // time it is visible and gets invalidated
16394                 mPrivateFlags |= PFLAG_DRAWN;
16395             }
16396             if (mAttachInfo != null) {
16397                 mAttachInfo.mViewVisibilityChanged = true;
16398             }
16399         }
16400 
16401         /* Check if the VISIBLE bit has changed */
16402         if ((changed & INVISIBLE) != 0) {
16403             needGlobalAttributesUpdate(false);
16404             /*
16405              * If this view is becoming invisible, set the DRAWN flag so that
16406              * the next invalidate() will not be skipped.
16407              */
16408             mPrivateFlags |= PFLAG_DRAWN;
16409 
16410             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
16411                 // root view becoming invisible shouldn't clear focus and accessibility focus
16412                 if (getRootView() != this) {
16413                     if (hasFocus()) {
16414                         clearFocus();
16415                         if (mParent instanceof ViewGroup) {
16416                             ((ViewGroup) mParent).clearFocusedInCluster();
16417                         }
16418                     }
16419                     clearAccessibilityFocus();
16420                 }
16421             }
16422             if (mAttachInfo != null) {
16423                 mAttachInfo.mViewVisibilityChanged = true;
16424             }
16425         }
16426 
16427         if ((changed & VISIBILITY_MASK) != 0) {
16428             // If the view is invisible, cleanup its display list to free up resources
16429             if (newVisibility != VISIBLE && mAttachInfo != null) {
16430                 cleanupDraw();
16431             }
16432 
16433             if (mParent instanceof ViewGroup) {
16434                 ViewGroup parent = (ViewGroup) mParent;
16435                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
16436                         newVisibility);
16437                 parent.invalidate(true);
16438             } else if (mParent != null) {
16439                 mParent.invalidateChild(this, null);
16440             }
16441 
16442             if (mAttachInfo != null) {
16443                 dispatchVisibilityChanged(this, newVisibility);
16444 
16445                 // Aggregated visibility changes are dispatched to attached views
16446                 // in visible windows where the parent is currently shown/drawn
16447                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
16448                 // discounting clipping or overlapping. This makes it a good place
16449                 // to change animation states.
16450                 if (mParent != null && getWindowVisibility() == VISIBLE &&
16451                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
16452                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
16453                 }
16454                 // If this view is invisible from visible, then sending the A11y event by its
16455                 // parent which is shown and has the accessibility important.
16456                 if ((old & VISIBILITY_MASK) == VISIBLE) {
16457                     notifySubtreeAccessibilityStateChangedByParentIfNeeded();
16458                 } else {
16459                     notifySubtreeAccessibilityStateChangedIfNeeded();
16460                 }
16461             }
16462         }
16463 
16464         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
16465             destroyDrawingCache();
16466         }
16467 
16468         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
16469             destroyDrawingCache();
16470             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16471             invalidateParentCaches();
16472         }
16473 
16474         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
16475             destroyDrawingCache();
16476             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16477         }
16478 
16479         if ((changed & DRAW_MASK) != 0) {
16480             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
16481                 if (mBackground != null
16482                         || mDefaultFocusHighlight != null
16483                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
16484                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16485                 } else {
16486                     mPrivateFlags |= PFLAG_SKIP_DRAW;
16487                 }
16488             } else {
16489                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16490             }
16491             requestLayout();
16492             invalidate(true);
16493         }
16494 
16495         if ((changed & KEEP_SCREEN_ON) != 0) {
16496             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16497                 mParent.recomputeViewAttributes(this);
16498             }
16499         }
16500 
16501         if (accessibilityEnabled) {
16502             // If we're an accessibility pane and the visibility changed, we already have sent
16503             // a state change, so we really don't need to report other changes.
16504             if (isAccessibilityPane()) {
16505                 changed &= ~VISIBILITY_MASK;
16506             }
16507             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
16508                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
16509                     || (changed & CONTEXT_CLICKABLE) != 0) {
16510                 if (oldIncludeForAccessibility != includeForAccessibility()) {
16511                     notifySubtreeAccessibilityStateChangedIfNeeded();
16512                 } else {
16513                     notifyViewAccessibilityStateChangedIfNeeded(
16514                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16515                 }
16516             } else if ((changed & ENABLED_MASK) != 0) {
16517                 notifyViewAccessibilityStateChangedIfNeeded(
16518                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16519             }
16520         }
16521     }
16522 
16523     /**
16524      * Change the view's z order in the tree, so it's on top of other sibling
16525      * views. This ordering change may affect layout, if the parent container
16526      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
16527      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
16528      * method should be followed by calls to {@link #requestLayout()} and
16529      * {@link View#invalidate()} on the view's parent to force the parent to redraw
16530      * with the new child ordering.
16531      *
16532      * @see ViewGroup#bringChildToFront(View)
16533      */
bringToFront()16534     public void bringToFront() {
16535         if (mParent != null) {
16536             mParent.bringChildToFront(this);
16537         }
16538     }
16539 
16540     /**
16541      * This is called in response to an internal scroll in this view (i.e., the
16542      * view scrolled its own contents). This is typically as a result of
16543      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
16544      * called.
16545      *
16546      * @param l Current horizontal scroll origin.
16547      * @param t Current vertical scroll origin.
16548      * @param oldl Previous horizontal scroll origin.
16549      * @param oldt Previous vertical scroll origin.
16550      */
onScrollChanged(int l, int t, int oldl, int oldt)16551     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
16552         notifySubtreeAccessibilityStateChangedIfNeeded();
16553         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
16554 
16555         mBackgroundSizeChanged = true;
16556         mDefaultFocusHighlightSizeChanged = true;
16557         if (mForegroundInfo != null) {
16558             mForegroundInfo.mBoundsChanged = true;
16559         }
16560 
16561         final AttachInfo ai = mAttachInfo;
16562         if (ai != null) {
16563             ai.mViewScrollChanged = true;
16564         }
16565 
16566         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
16567             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
16568         }
16569     }
16570 
16571     /**
16572      * Interface definition for a callback to be invoked when the scroll
16573      * X or Y positions of a view change.
16574      * <p>
16575      * <b>Note:</b> Some views handle scrolling independently from View and may
16576      * have their own separate listeners for scroll-type events. For example,
16577      * {@link android.widget.ListView ListView} allows clients to register an
16578      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
16579      * to listen for changes in list scroll position.
16580      *
16581      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
16582      */
16583     public interface OnScrollChangeListener {
16584         /**
16585          * Called when the scroll position of a view changes.
16586          *
16587          * @param v The view whose scroll position has changed.
16588          * @param scrollX Current horizontal scroll origin.
16589          * @param scrollY Current vertical scroll origin.
16590          * @param oldScrollX Previous horizontal scroll origin.
16591          * @param oldScrollY Previous vertical scroll origin.
16592          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)16593         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
16594     }
16595 
16596     /**
16597      * Interface definition for a callback to be invoked when the layout bounds of a view
16598      * changes due to layout processing.
16599      */
16600     public interface OnLayoutChangeListener {
16601         /**
16602          * Called when the layout bounds of a view changes due to layout processing.
16603          *
16604          * @param v The view whose bounds have changed.
16605          * @param left The new value of the view's left property.
16606          * @param top The new value of the view's top property.
16607          * @param right The new value of the view's right property.
16608          * @param bottom The new value of the view's bottom property.
16609          * @param oldLeft The previous value of the view's left property.
16610          * @param oldTop The previous value of the view's top property.
16611          * @param oldRight The previous value of the view's right property.
16612          * @param oldBottom The previous value of the view's bottom property.
16613          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)16614         void onLayoutChange(View v, int left, int top, int right, int bottom,
16615             int oldLeft, int oldTop, int oldRight, int oldBottom);
16616     }
16617 
16618     /**
16619      * This is called during layout when the size of this view has changed. If
16620      * you were just added to the view hierarchy, you're called with the old
16621      * values of 0.
16622      *
16623      * @param w Current width of this view.
16624      * @param h Current height of this view.
16625      * @param oldw Old width of this view.
16626      * @param oldh Old height of this view.
16627      */
onSizeChanged(int w, int h, int oldw, int oldh)16628     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
16629     }
16630 
16631     /**
16632      * Called by draw to draw the child views. This may be overridden
16633      * by derived classes to gain control just before its children are drawn
16634      * (but after its own view has been drawn).
16635      * @param canvas the canvas on which to draw the view
16636      */
dispatchDraw(Canvas canvas)16637     protected void dispatchDraw(Canvas canvas) {
16638 
16639     }
16640 
16641     /**
16642      * Gets the parent of this view. Note that the parent is a
16643      * ViewParent and not necessarily a View.
16644      *
16645      * @return Parent of this view.
16646      */
getParent()16647     public final ViewParent getParent() {
16648         return mParent;
16649     }
16650 
16651     /**
16652      * Set the horizontal scrolled position of your view. This will cause a call to
16653      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16654      * invalidated.
16655      * @param value the x position to scroll to
16656      */
setScrollX(int value)16657     public void setScrollX(int value) {
16658         scrollTo(value, mScrollY);
16659     }
16660 
16661     /**
16662      * Set the vertical scrolled position of your view. This will cause a call to
16663      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16664      * invalidated.
16665      * @param value the y position to scroll to
16666      */
setScrollY(int value)16667     public void setScrollY(int value) {
16668         scrollTo(mScrollX, value);
16669     }
16670 
16671     /**
16672      * Return the scrolled left position of this view. This is the left edge of
16673      * the displayed part of your view. You do not need to draw any pixels
16674      * farther left, since those are outside of the frame of your view on
16675      * screen.
16676      *
16677      * @return The left edge of the displayed part of your view, in pixels.
16678      */
16679     @InspectableProperty
getScrollX()16680     public final int getScrollX() {
16681         return mScrollX;
16682     }
16683 
16684     /**
16685      * Return the scrolled top position of this view. This is the top edge of
16686      * the displayed part of your view. You do not need to draw any pixels above
16687      * it, since those are outside of the frame of your view on screen.
16688      *
16689      * @return The top edge of the displayed part of your view, in pixels.
16690      */
16691     @InspectableProperty
getScrollY()16692     public final int getScrollY() {
16693         return mScrollY;
16694     }
16695 
16696     /**
16697      * Return the width of your view.
16698      *
16699      * @return The width of your view, in pixels.
16700      */
16701     @ViewDebug.ExportedProperty(category = "layout")
getWidth()16702     public final int getWidth() {
16703         return mRight - mLeft;
16704     }
16705 
16706     /**
16707      * Return the height of your view.
16708      *
16709      * @return The height of your view, in pixels.
16710      */
16711     @ViewDebug.ExportedProperty(category = "layout")
getHeight()16712     public final int getHeight() {
16713         return mBottom - mTop;
16714     }
16715 
16716     /**
16717      * Return the visible drawing bounds of your view. Fills in the output
16718      * rectangle with the values from getScrollX(), getScrollY(),
16719      * getWidth(), and getHeight(). These bounds do not account for any
16720      * transformation properties currently set on the view, such as
16721      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
16722      *
16723      * @param outRect The (scrolled) drawing bounds of the view.
16724      */
getDrawingRect(Rect outRect)16725     public void getDrawingRect(Rect outRect) {
16726         outRect.left = mScrollX;
16727         outRect.top = mScrollY;
16728         outRect.right = mScrollX + (mRight - mLeft);
16729         outRect.bottom = mScrollY + (mBottom - mTop);
16730     }
16731 
16732     /**
16733      * Like {@link #getMeasuredWidthAndState()}, but only returns the
16734      * raw width component (that is the result is masked by
16735      * {@link #MEASURED_SIZE_MASK}).
16736      *
16737      * @return The raw measured width of this view.
16738      */
getMeasuredWidth()16739     public final int getMeasuredWidth() {
16740         return mMeasuredWidth & MEASURED_SIZE_MASK;
16741     }
16742 
16743     /**
16744      * Return the full width measurement information for this view as computed
16745      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16746      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16747      * This should be used during measurement and layout calculations only. Use
16748      * {@link #getWidth()} to see how wide a view is after layout.
16749      *
16750      * @return The measured width of this view as a bit mask.
16751      */
16752     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16753             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16754                     name = "MEASURED_STATE_TOO_SMALL"),
16755     })
getMeasuredWidthAndState()16756     public final int getMeasuredWidthAndState() {
16757         return mMeasuredWidth;
16758     }
16759 
16760     /**
16761      * Like {@link #getMeasuredHeightAndState()}, but only returns the
16762      * raw height component (that is the result is masked by
16763      * {@link #MEASURED_SIZE_MASK}).
16764      *
16765      * @return The raw measured height of this view.
16766      */
getMeasuredHeight()16767     public final int getMeasuredHeight() {
16768         return mMeasuredHeight & MEASURED_SIZE_MASK;
16769     }
16770 
16771     /**
16772      * Return the full height measurement information for this view as computed
16773      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16774      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16775      * This should be used during measurement and layout calculations only. Use
16776      * {@link #getHeight()} to see how high a view is after layout.
16777      *
16778      * @return The measured height of this view as a bit mask.
16779      */
16780     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16781             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16782                     name = "MEASURED_STATE_TOO_SMALL"),
16783     })
getMeasuredHeightAndState()16784     public final int getMeasuredHeightAndState() {
16785         return mMeasuredHeight;
16786     }
16787 
16788     /**
16789      * Return only the state bits of {@link #getMeasuredWidthAndState()}
16790      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
16791      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
16792      * and the height component is at the shifted bits
16793      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
16794      */
getMeasuredState()16795     public final int getMeasuredState() {
16796         return (mMeasuredWidth&MEASURED_STATE_MASK)
16797                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
16798                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
16799     }
16800 
16801     /**
16802      * The transform matrix of this view, which is calculated based on the current
16803      * rotation, scale, and pivot properties.
16804      *
16805      * @see #getRotation()
16806      * @see #getScaleX()
16807      * @see #getScaleY()
16808      * @see #getPivotX()
16809      * @see #getPivotY()
16810      * @return The current transform matrix for the view
16811      */
getMatrix()16812     public Matrix getMatrix() {
16813         ensureTransformationInfo();
16814         final Matrix matrix = mTransformationInfo.mMatrix;
16815         mRenderNode.getMatrix(matrix);
16816         return matrix;
16817     }
16818 
16819     /**
16820      * Returns true if the transform matrix is the identity matrix.
16821      * Recomputes the matrix if necessary.
16822      *
16823      * @return True if the transform matrix is the identity matrix, false otherwise.
16824      * @hide
16825      */
16826     @UnsupportedAppUsage
hasIdentityMatrix()16827     public final boolean hasIdentityMatrix() {
16828         return mRenderNode.hasIdentityMatrix();
16829     }
16830 
16831     @UnsupportedAppUsage
ensureTransformationInfo()16832     void ensureTransformationInfo() {
16833         if (mTransformationInfo == null) {
16834             mTransformationInfo = new TransformationInfo();
16835         }
16836     }
16837 
16838     /**
16839      * Utility method to retrieve the inverse of the current mMatrix property.
16840      * We cache the matrix to avoid recalculating it when transform properties
16841      * have not changed.
16842      *
16843      * @return The inverse of the current matrix of this view.
16844      * @hide
16845      */
16846     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getInverseMatrix()16847     public final Matrix getInverseMatrix() {
16848         ensureTransformationInfo();
16849         if (mTransformationInfo.mInverseMatrix == null) {
16850             mTransformationInfo.mInverseMatrix = new Matrix();
16851         }
16852         final Matrix matrix = mTransformationInfo.mInverseMatrix;
16853         mRenderNode.getInverseMatrix(matrix);
16854         return matrix;
16855     }
16856 
16857     /**
16858      * Gets the distance along the Z axis from the camera to this view.
16859      *
16860      * @see #setCameraDistance(float)
16861      *
16862      * @return The distance along the Z axis.
16863      */
getCameraDistance()16864     public float getCameraDistance() {
16865         final float dpi = mResources.getDisplayMetrics().densityDpi;
16866         return mRenderNode.getCameraDistance() * dpi;
16867     }
16868 
16869     /**
16870      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
16871      * views are drawn) from the camera to this view. The camera's distance
16872      * affects 3D transformations, for instance rotations around the X and Y
16873      * axis. If the rotationX or rotationY properties are changed and this view is
16874      * large (more than half the size of the screen), it is recommended to always
16875      * use a camera distance that's greater than the height (X axis rotation) or
16876      * the width (Y axis rotation) of this view.</p>
16877      *
16878      * <p>The distance of the camera from the view plane can have an affect on the
16879      * perspective distortion of the view when it is rotated around the x or y axis.
16880      * For example, a large distance will result in a large viewing angle, and there
16881      * will not be much perspective distortion of the view as it rotates. A short
16882      * distance may cause much more perspective distortion upon rotation, and can
16883      * also result in some drawing artifacts if the rotated view ends up partially
16884      * behind the camera (which is why the recommendation is to use a distance at
16885      * least as far as the size of the view, if the view is to be rotated.)</p>
16886      *
16887      * <p>The distance is expressed in "depth pixels." The default distance depends
16888      * on the screen density. For instance, on a medium density display, the
16889      * default distance is 1280. On a high density display, the default distance
16890      * is 1920.</p>
16891      *
16892      * <p>If you want to specify a distance that leads to visually consistent
16893      * results across various densities, use the following formula:</p>
16894      * <pre>
16895      * float scale = context.getResources().getDisplayMetrics().density;
16896      * view.setCameraDistance(distance * scale);
16897      * </pre>
16898      *
16899      * <p>The density scale factor of a high density display is 1.5,
16900      * and 1920 = 1280 * 1.5.</p>
16901      *
16902      * @param distance The distance in "depth pixels", if negative the opposite
16903      *        value is used
16904      *
16905      * @see #setRotationX(float)
16906      * @see #setRotationY(float)
16907      */
setCameraDistance(float distance)16908     public void setCameraDistance(float distance) {
16909         final float dpi = mResources.getDisplayMetrics().densityDpi;
16910 
16911         invalidateViewProperty(true, false);
16912         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
16913         invalidateViewProperty(false, false);
16914 
16915         invalidateParentIfNeededAndWasQuickRejected();
16916     }
16917 
16918     /**
16919      * The degrees that the view is rotated around the pivot point.
16920      *
16921      * @see #setRotation(float)
16922      * @see #getPivotX()
16923      * @see #getPivotY()
16924      *
16925      * @return The degrees of rotation.
16926      */
16927     @ViewDebug.ExportedProperty(category = "drawing")
16928     @InspectableProperty
getRotation()16929     public float getRotation() {
16930         return mRenderNode.getRotationZ();
16931     }
16932 
16933     /**
16934      * Sets the degrees that the view is rotated around the pivot point. Increasing values
16935      * result in clockwise rotation.
16936      *
16937      * @param rotation The degrees of rotation.
16938      *
16939      * @see #getRotation()
16940      * @see #getPivotX()
16941      * @see #getPivotY()
16942      * @see #setRotationX(float)
16943      * @see #setRotationY(float)
16944      *
16945      * @attr ref android.R.styleable#View_rotation
16946      */
16947     @RemotableViewMethod
setRotation(float rotation)16948     public void setRotation(float rotation) {
16949         if (rotation != getRotation()) {
16950             // Double-invalidation is necessary to capture view's old and new areas
16951             invalidateViewProperty(true, false);
16952             mRenderNode.setRotationZ(rotation);
16953             invalidateViewProperty(false, true);
16954 
16955             invalidateParentIfNeededAndWasQuickRejected();
16956             notifySubtreeAccessibilityStateChangedIfNeeded();
16957         }
16958     }
16959 
16960     /**
16961      * The degrees that the view is rotated around the vertical axis through the pivot point.
16962      *
16963      * @see #getPivotX()
16964      * @see #getPivotY()
16965      * @see #setRotationY(float)
16966      *
16967      * @return The degrees of Y rotation.
16968      */
16969     @ViewDebug.ExportedProperty(category = "drawing")
16970     @InspectableProperty
getRotationY()16971     public float getRotationY() {
16972         return mRenderNode.getRotationY();
16973     }
16974 
16975     /**
16976      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
16977      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
16978      * down the y axis.
16979      *
16980      * When rotating large views, it is recommended to adjust the camera distance
16981      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
16982      *
16983      * @param rotationY The degrees of Y rotation.
16984      *
16985      * @see #getRotationY()
16986      * @see #getPivotX()
16987      * @see #getPivotY()
16988      * @see #setRotation(float)
16989      * @see #setRotationX(float)
16990      * @see #setCameraDistance(float)
16991      *
16992      * @attr ref android.R.styleable#View_rotationY
16993      */
16994     @RemotableViewMethod
setRotationY(float rotationY)16995     public void setRotationY(float rotationY) {
16996         if (rotationY != getRotationY()) {
16997             invalidateViewProperty(true, false);
16998             mRenderNode.setRotationY(rotationY);
16999             invalidateViewProperty(false, true);
17000 
17001             invalidateParentIfNeededAndWasQuickRejected();
17002             notifySubtreeAccessibilityStateChangedIfNeeded();
17003         }
17004     }
17005 
17006     /**
17007      * The degrees that the view is rotated around the horizontal axis through the pivot point.
17008      *
17009      * @see #getPivotX()
17010      * @see #getPivotY()
17011      * @see #setRotationX(float)
17012      *
17013      * @return The degrees of X rotation.
17014      */
17015     @ViewDebug.ExportedProperty(category = "drawing")
17016     @InspectableProperty
getRotationX()17017     public float getRotationX() {
17018         return mRenderNode.getRotationX();
17019     }
17020 
17021     /**
17022      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
17023      * Increasing values result in clockwise rotation from the viewpoint of looking down the
17024      * x axis.
17025      *
17026      * When rotating large views, it is recommended to adjust the camera distance
17027      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
17028      *
17029      * @param rotationX The degrees of X rotation.
17030      *
17031      * @see #getRotationX()
17032      * @see #getPivotX()
17033      * @see #getPivotY()
17034      * @see #setRotation(float)
17035      * @see #setRotationY(float)
17036      * @see #setCameraDistance(float)
17037      *
17038      * @attr ref android.R.styleable#View_rotationX
17039      */
17040     @RemotableViewMethod
setRotationX(float rotationX)17041     public void setRotationX(float rotationX) {
17042         if (rotationX != getRotationX()) {
17043             invalidateViewProperty(true, false);
17044             mRenderNode.setRotationX(rotationX);
17045             invalidateViewProperty(false, true);
17046 
17047             invalidateParentIfNeededAndWasQuickRejected();
17048             notifySubtreeAccessibilityStateChangedIfNeeded();
17049         }
17050     }
17051 
17052     /**
17053      * The amount that the view is scaled in x around the pivot point, as a proportion of
17054      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
17055      *
17056      * <p>By default, this is 1.0f.
17057      *
17058      * @see #getPivotX()
17059      * @see #getPivotY()
17060      * @return The scaling factor.
17061      */
17062     @ViewDebug.ExportedProperty(category = "drawing")
17063     @InspectableProperty
getScaleX()17064     public float getScaleX() {
17065         return mRenderNode.getScaleX();
17066     }
17067 
17068     /**
17069      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
17070      * the view's unscaled width. A value of 1 means that no scaling is applied.
17071      *
17072      * @param scaleX The scaling factor.
17073      * @see #getPivotX()
17074      * @see #getPivotY()
17075      *
17076      * @attr ref android.R.styleable#View_scaleX
17077      */
17078     @RemotableViewMethod
setScaleX(float scaleX)17079     public void setScaleX(float scaleX) {
17080         if (scaleX != getScaleX()) {
17081             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
17082             invalidateViewProperty(true, false);
17083             mRenderNode.setScaleX(scaleX);
17084             invalidateViewProperty(false, true);
17085 
17086             invalidateParentIfNeededAndWasQuickRejected();
17087             notifySubtreeAccessibilityStateChangedIfNeeded();
17088         }
17089     }
17090 
17091     /**
17092      * The amount that the view is scaled in y around the pivot point, as a proportion of
17093      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
17094      *
17095      * <p>By default, this is 1.0f.
17096      *
17097      * @see #getPivotX()
17098      * @see #getPivotY()
17099      * @return The scaling factor.
17100      */
17101     @ViewDebug.ExportedProperty(category = "drawing")
17102     @InspectableProperty
getScaleY()17103     public float getScaleY() {
17104         return mRenderNode.getScaleY();
17105     }
17106 
17107     /**
17108      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
17109      * the view's unscaled width. A value of 1 means that no scaling is applied.
17110      *
17111      * @param scaleY The scaling factor.
17112      * @see #getPivotX()
17113      * @see #getPivotY()
17114      *
17115      * @attr ref android.R.styleable#View_scaleY
17116      */
17117     @RemotableViewMethod
setScaleY(float scaleY)17118     public void setScaleY(float scaleY) {
17119         if (scaleY != getScaleY()) {
17120             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
17121             invalidateViewProperty(true, false);
17122             mRenderNode.setScaleY(scaleY);
17123             invalidateViewProperty(false, true);
17124 
17125             invalidateParentIfNeededAndWasQuickRejected();
17126             notifySubtreeAccessibilityStateChangedIfNeeded();
17127         }
17128     }
17129 
17130     /**
17131      * The x location of the point around which the view is {@link #setRotation(float) rotated}
17132      * and {@link #setScaleX(float) scaled}.
17133      *
17134      * @see #getRotation()
17135      * @see #getScaleX()
17136      * @see #getScaleY()
17137      * @see #getPivotY()
17138      * @return The x location of the pivot point.
17139      *
17140      * @attr ref android.R.styleable#View_transformPivotX
17141      */
17142     @ViewDebug.ExportedProperty(category = "drawing")
17143     @InspectableProperty(name = "transformPivotX")
getPivotX()17144     public float getPivotX() {
17145         return mRenderNode.getPivotX();
17146     }
17147 
17148     /**
17149      * Sets the x location of the point around which the view is
17150      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
17151      * By default, the pivot point is centered on the object.
17152      * Setting this property disables this behavior and causes the view to use only the
17153      * explicitly set pivotX and pivotY values.
17154      *
17155      * @param pivotX The x location of the pivot point.
17156      * @see #getRotation()
17157      * @see #getScaleX()
17158      * @see #getScaleY()
17159      * @see #getPivotY()
17160      *
17161      * @attr ref android.R.styleable#View_transformPivotX
17162      */
17163     @RemotableViewMethod
setPivotX(float pivotX)17164     public void setPivotX(float pivotX) {
17165         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
17166             invalidateViewProperty(true, false);
17167             mRenderNode.setPivotX(pivotX);
17168             invalidateViewProperty(false, true);
17169 
17170             invalidateParentIfNeededAndWasQuickRejected();
17171         }
17172     }
17173 
17174     /**
17175      * The y location of the point around which the view is {@link #setRotation(float) rotated}
17176      * and {@link #setScaleY(float) scaled}.
17177      *
17178      * @see #getRotation()
17179      * @see #getScaleX()
17180      * @see #getScaleY()
17181      * @see #getPivotY()
17182      * @return The y location of the pivot point.
17183      *
17184      * @attr ref android.R.styleable#View_transformPivotY
17185      */
17186     @ViewDebug.ExportedProperty(category = "drawing")
17187     @InspectableProperty(name = "transformPivotY")
getPivotY()17188     public float getPivotY() {
17189         return mRenderNode.getPivotY();
17190     }
17191 
17192     /**
17193      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
17194      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
17195      * Setting this property disables this behavior and causes the view to use only the
17196      * explicitly set pivotX and pivotY values.
17197      *
17198      * @param pivotY The y location of the pivot point.
17199      * @see #getRotation()
17200      * @see #getScaleX()
17201      * @see #getScaleY()
17202      * @see #getPivotY()
17203      *
17204      * @attr ref android.R.styleable#View_transformPivotY
17205      */
17206     @RemotableViewMethod
setPivotY(float pivotY)17207     public void setPivotY(float pivotY) {
17208         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
17209             invalidateViewProperty(true, false);
17210             mRenderNode.setPivotY(pivotY);
17211             invalidateViewProperty(false, true);
17212 
17213             invalidateParentIfNeededAndWasQuickRejected();
17214         }
17215     }
17216 
17217     /**
17218      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
17219      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
17220      * of the view.
17221      *
17222      * @return True if a pivot has been set, false if the default pivot is being used
17223      */
isPivotSet()17224     public boolean isPivotSet() {
17225         return mRenderNode.isPivotExplicitlySet();
17226     }
17227 
17228     /**
17229      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
17230      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
17231      * and the pivot used for rotation will return to default of being centered on the view.
17232      */
resetPivot()17233     public void resetPivot() {
17234         if (mRenderNode.resetPivot()) {
17235             invalidateViewProperty(false, false);
17236         }
17237     }
17238 
17239     /**
17240      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
17241      * completely transparent and 1 means the view is completely opaque.
17242      *
17243      * <p>By default this is 1.0f.
17244      * @return The opacity of the view.
17245      */
17246     @ViewDebug.ExportedProperty(category = "drawing")
17247     @InspectableProperty
getAlpha()17248     public float getAlpha() {
17249         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
17250     }
17251 
17252     /**
17253      * Sets the behavior for overlapping rendering for this view (see {@link
17254      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
17255      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
17256      * providing the value which is then used internally. That is, when {@link
17257      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
17258      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
17259      * instead.
17260      *
17261      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
17262      * instead of that returned by {@link #hasOverlappingRendering()}.
17263      *
17264      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
17265      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)17266     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
17267         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
17268         if (hasOverlappingRendering) {
17269             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17270         } else {
17271             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17272         }
17273     }
17274 
17275     /**
17276      * Returns the value for overlapping rendering that is used internally. This is either
17277      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
17278      * the return value of {@link #hasOverlappingRendering()}, otherwise.
17279      *
17280      * @return The value for overlapping rendering being used internally.
17281      */
getHasOverlappingRendering()17282     public final boolean getHasOverlappingRendering() {
17283         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
17284                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
17285                 hasOverlappingRendering();
17286     }
17287 
17288     /**
17289      * Returns whether this View has content which overlaps.
17290      *
17291      * <p>This function, intended to be overridden by specific View types, is an optimization when
17292      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
17293      * an offscreen buffer and then composited into place, which can be expensive. If the view has
17294      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
17295      * directly. An example of overlapping rendering is a TextView with a background image, such as
17296      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
17297      * ImageView with only the foreground image. The default implementation returns true; subclasses
17298      * should override if they have cases which can be optimized.</p>
17299      *
17300      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
17301      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
17302      *
17303      * @return true if the content in this view might overlap, false otherwise.
17304      */
17305     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()17306     public boolean hasOverlappingRendering() {
17307         return true;
17308     }
17309 
17310     /**
17311      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
17312      * completely transparent and 1 means the view is completely opaque.
17313      *
17314      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
17315      * can have significant performance implications, especially for large views. It is best to use
17316      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
17317      *
17318      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
17319      * strongly recommended for performance reasons to either override
17320      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
17321      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
17322      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
17323      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
17324      * of rendering cost, even for simple or small views. Starting with
17325      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
17326      * applied to the view at the rendering level.</p>
17327      *
17328      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
17329      * responsible for applying the opacity itself.</p>
17330      *
17331      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
17332      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
17333      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
17334      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
17335      *
17336      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
17337      * value will clip a View to its bounds, unless the View returns <code>false</code> from
17338      * {@link #hasOverlappingRendering}.</p>
17339      *
17340      * @param alpha The opacity of the view.
17341      *
17342      * @see #hasOverlappingRendering()
17343      * @see #setLayerType(int, android.graphics.Paint)
17344      *
17345      * @attr ref android.R.styleable#View_alpha
17346      */
17347     @RemotableViewMethod
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)17348     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
17349         ensureTransformationInfo();
17350         if (mTransformationInfo.mAlpha != alpha) {
17351             setAlphaInternal(alpha);
17352             if (onSetAlpha((int) (alpha * 255))) {
17353                 mPrivateFlags |= PFLAG_ALPHA_SET;
17354                 // subclass is handling alpha - don't optimize rendering cache invalidation
17355                 invalidateParentCaches();
17356                 invalidate(true);
17357             } else {
17358                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17359                 invalidateViewProperty(true, false);
17360                 mRenderNode.setAlpha(getFinalAlpha());
17361             }
17362         }
17363     }
17364 
17365     /**
17366      * Faster version of setAlpha() which performs the same steps except there are
17367      * no calls to invalidate(). The caller of this function should perform proper invalidation
17368      * on the parent and this object. The return value indicates whether the subclass handles
17369      * alpha (the return value for onSetAlpha()).
17370      *
17371      * @param alpha The new value for the alpha property
17372      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
17373      *         the new value for the alpha property is different from the old value
17374      */
17375     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)17376     boolean setAlphaNoInvalidation(float alpha) {
17377         ensureTransformationInfo();
17378         if (mTransformationInfo.mAlpha != alpha) {
17379             setAlphaInternal(alpha);
17380             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
17381             if (subclassHandlesAlpha) {
17382                 mPrivateFlags |= PFLAG_ALPHA_SET;
17383                 return true;
17384             } else {
17385                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17386                 mRenderNode.setAlpha(getFinalAlpha());
17387             }
17388         }
17389         return false;
17390     }
17391 
setAlphaInternal(float alpha)17392     void setAlphaInternal(float alpha) {
17393         float oldAlpha = mTransformationInfo.mAlpha;
17394         mTransformationInfo.mAlpha = alpha;
17395         // Report visibility changes, which can affect children, to accessibility
17396         if ((alpha == 0) ^ (oldAlpha == 0)) {
17397             notifySubtreeAccessibilityStateChangedIfNeeded();
17398         }
17399     }
17400 
17401     /**
17402      * This property is intended only for use by the Fade transition, which animates it
17403      * to produce a visual translucency that does not side-effect (or get affected by)
17404      * the real alpha property. This value is composited with the other alpha value
17405      * (and the AlphaAnimation value, when that is present) to produce a final visual
17406      * translucency result, which is what is passed into the DisplayList.
17407      */
setTransitionAlpha(float alpha)17408     public void setTransitionAlpha(float alpha) {
17409         ensureTransformationInfo();
17410         if (mTransformationInfo.mTransitionAlpha != alpha) {
17411             mTransformationInfo.mTransitionAlpha = alpha;
17412             mPrivateFlags &= ~PFLAG_ALPHA_SET;
17413             invalidateViewProperty(true, false);
17414             mRenderNode.setAlpha(getFinalAlpha());
17415         }
17416     }
17417 
17418     /**
17419      * Calculates the visual alpha of this view, which is a combination of the actual
17420      * alpha value and the transitionAlpha value (if set).
17421      */
getFinalAlpha()17422     private float getFinalAlpha() {
17423         if (mTransformationInfo != null) {
17424             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
17425         }
17426         return 1;
17427     }
17428 
17429     /**
17430      * This property is intended only for use by the Fade transition, which animates
17431      * it to produce a visual translucency that does not side-effect (or get affected
17432      * by) the real alpha property. This value is composited with the other alpha
17433      * value (and the AlphaAnimation value, when that is present) to produce a final
17434      * visual translucency result, which is what is passed into the DisplayList.
17435      */
17436     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()17437     public float getTransitionAlpha() {
17438         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
17439     }
17440 
17441     /**
17442      * Sets whether or not to allow force dark to apply to this view.
17443      *
17444      * Setting this to false will disable the auto-dark feature on everything this view
17445      * draws, including any descendants.
17446      *
17447      * Setting this to true will allow this view to be automatically made dark, however
17448      * a value of 'true' will not override any 'false' value in its parent chain nor will
17449      * it prevent any 'false' in any of its children.
17450      *
17451      * The default behavior of force dark is also influenced by the Theme's
17452      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
17453      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
17454      *
17455      * @param allow Whether or not to allow force dark.
17456      */
setForceDarkAllowed(boolean allow)17457     public void setForceDarkAllowed(boolean allow) {
17458         if (mRenderNode.setForceDarkAllowed(allow)) {
17459             // Currently toggling force-dark requires a new display list push to apply
17460             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
17461             invalidate();
17462         }
17463     }
17464 
17465     /**
17466      * See {@link #setForceDarkAllowed(boolean)}
17467      *
17468      * @return true if force dark is allowed (default), false if it is disabled
17469      */
17470     @ViewDebug.ExportedProperty(category = "drawing")
17471     @InspectableProperty
isForceDarkAllowed()17472     public boolean isForceDarkAllowed() {
17473         return mRenderNode.isForceDarkAllowed();
17474     }
17475 
17476     /**
17477      * Top position of this view relative to its parent.
17478      *
17479      * @return The top of this view, in pixels.
17480      */
17481     @ViewDebug.CapturedViewProperty
getTop()17482     public final int getTop() {
17483         return mTop;
17484     }
17485 
17486     /**
17487      * Sets the top position of this view relative to its parent. This method is meant to be called
17488      * by the layout system and should not generally be called otherwise, because the property
17489      * may be changed at any time by the layout.
17490      *
17491      * @param top The top of this view, in pixels.
17492      */
setTop(int top)17493     public final void setTop(int top) {
17494         if (top != mTop) {
17495             final boolean matrixIsIdentity = hasIdentityMatrix();
17496             if (matrixIsIdentity) {
17497                 if (mAttachInfo != null) {
17498                     int minTop;
17499                     int yLoc;
17500                     if (top < mTop) {
17501                         minTop = top;
17502                         yLoc = top - mTop;
17503                     } else {
17504                         minTop = mTop;
17505                         yLoc = 0;
17506                     }
17507                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
17508                 }
17509             } else {
17510                 // Double-invalidation is necessary to capture view's old and new areas
17511                 invalidate(true);
17512             }
17513 
17514             int width = mRight - mLeft;
17515             int oldHeight = mBottom - mTop;
17516 
17517             mTop = top;
17518             mRenderNode.setTop(mTop);
17519 
17520             sizeChange(width, mBottom - mTop, width, oldHeight);
17521 
17522             if (!matrixIsIdentity) {
17523                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17524                 invalidate(true);
17525             }
17526             mBackgroundSizeChanged = true;
17527             mDefaultFocusHighlightSizeChanged = true;
17528             if (mForegroundInfo != null) {
17529                 mForegroundInfo.mBoundsChanged = true;
17530             }
17531             invalidateParentIfNeeded();
17532         }
17533     }
17534 
17535     /**
17536      * Bottom position of this view relative to its parent.
17537      *
17538      * @return The bottom of this view, in pixels.
17539      */
17540     @ViewDebug.CapturedViewProperty
getBottom()17541     public final int getBottom() {
17542         return mBottom;
17543     }
17544 
17545     /**
17546      * True if this view has changed since the last time being drawn.
17547      *
17548      * @return The dirty state of this view.
17549      */
isDirty()17550     public boolean isDirty() {
17551         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
17552     }
17553 
17554     /**
17555      * Sets the bottom position of this view relative to its parent. This method is meant to be
17556      * called by the layout system and should not generally be called otherwise, because the
17557      * property may be changed at any time by the layout.
17558      *
17559      * @param bottom The bottom of this view, in pixels.
17560      */
setBottom(int bottom)17561     public final void setBottom(int bottom) {
17562         if (bottom != mBottom) {
17563             final boolean matrixIsIdentity = hasIdentityMatrix();
17564             if (matrixIsIdentity) {
17565                 if (mAttachInfo != null) {
17566                     int maxBottom;
17567                     if (bottom < mBottom) {
17568                         maxBottom = mBottom;
17569                     } else {
17570                         maxBottom = bottom;
17571                     }
17572                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
17573                 }
17574             } else {
17575                 // Double-invalidation is necessary to capture view's old and new areas
17576                 invalidate(true);
17577             }
17578 
17579             int width = mRight - mLeft;
17580             int oldHeight = mBottom - mTop;
17581 
17582             mBottom = bottom;
17583             mRenderNode.setBottom(mBottom);
17584 
17585             sizeChange(width, mBottom - mTop, width, oldHeight);
17586 
17587             if (!matrixIsIdentity) {
17588                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17589                 invalidate(true);
17590             }
17591             mBackgroundSizeChanged = true;
17592             mDefaultFocusHighlightSizeChanged = true;
17593             if (mForegroundInfo != null) {
17594                 mForegroundInfo.mBoundsChanged = true;
17595             }
17596             invalidateParentIfNeeded();
17597         }
17598     }
17599 
17600     /**
17601      * Left position of this view relative to its parent.
17602      *
17603      * @return The left edge of this view, in pixels.
17604      */
17605     @ViewDebug.CapturedViewProperty
getLeft()17606     public final int getLeft() {
17607         return mLeft;
17608     }
17609 
17610     /**
17611      * Sets the left position of this view relative to its parent. This method is meant to be called
17612      * by the layout system and should not generally be called otherwise, because the property
17613      * may be changed at any time by the layout.
17614      *
17615      * @param left The left of this view, in pixels.
17616      */
setLeft(int left)17617     public final void setLeft(int left) {
17618         if (left != mLeft) {
17619             final boolean matrixIsIdentity = hasIdentityMatrix();
17620             if (matrixIsIdentity) {
17621                 if (mAttachInfo != null) {
17622                     int minLeft;
17623                     int xLoc;
17624                     if (left < mLeft) {
17625                         minLeft = left;
17626                         xLoc = left - mLeft;
17627                     } else {
17628                         minLeft = mLeft;
17629                         xLoc = 0;
17630                     }
17631                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
17632                 }
17633             } else {
17634                 // Double-invalidation is necessary to capture view's old and new areas
17635                 invalidate(true);
17636             }
17637 
17638             int oldWidth = mRight - mLeft;
17639             int height = mBottom - mTop;
17640 
17641             mLeft = left;
17642             mRenderNode.setLeft(left);
17643 
17644             sizeChange(mRight - mLeft, height, oldWidth, height);
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      * Right position of this view relative to its parent.
17661      *
17662      * @return The right edge of this view, in pixels.
17663      */
17664     @ViewDebug.CapturedViewProperty
getRight()17665     public final int getRight() {
17666         return mRight;
17667     }
17668 
17669     /**
17670      * Sets the right 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 right The right of this view, in pixels.
17675      */
setRight(int right)17676     public final void setRight(int right) {
17677         if (right != mRight) {
17678             final boolean matrixIsIdentity = hasIdentityMatrix();
17679             if (matrixIsIdentity) {
17680                 if (mAttachInfo != null) {
17681                     int maxRight;
17682                     if (right < mRight) {
17683                         maxRight = mRight;
17684                     } else {
17685                         maxRight = right;
17686                     }
17687                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
17688                 }
17689             } else {
17690                 // Double-invalidation is necessary to capture view's old and new areas
17691                 invalidate(true);
17692             }
17693 
17694             int oldWidth = mRight - mLeft;
17695             int height = mBottom - mTop;
17696 
17697             mRight = right;
17698             mRenderNode.setRight(mRight);
17699 
17700             sizeChange(mRight - mLeft, height, oldWidth, height);
17701 
17702             if (!matrixIsIdentity) {
17703                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17704                 invalidate(true);
17705             }
17706             mBackgroundSizeChanged = true;
17707             mDefaultFocusHighlightSizeChanged = true;
17708             if (mForegroundInfo != null) {
17709                 mForegroundInfo.mBoundsChanged = true;
17710             }
17711             invalidateParentIfNeeded();
17712         }
17713     }
17714 
sanitizeFloatPropertyValue(float value, String propertyName)17715     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
17716         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
17717     }
17718 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)17719     private static float sanitizeFloatPropertyValue(float value, String propertyName,
17720             float min, float max) {
17721         // The expected "nothing bad happened" path
17722         if (value >= min && value <= max) return value;
17723 
17724         if (value < min || value == Float.NEGATIVE_INFINITY) {
17725             if (sThrowOnInvalidFloatProperties) {
17726                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17727                         + value + ", the value must be >= " + min);
17728             }
17729             return min;
17730         }
17731 
17732         if (value > max || value == Float.POSITIVE_INFINITY) {
17733             if (sThrowOnInvalidFloatProperties) {
17734                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17735                         + value + ", the value must be <= " + max);
17736             }
17737             return max;
17738         }
17739 
17740         if (Float.isNaN(value)) {
17741             if (sThrowOnInvalidFloatProperties) {
17742                 throw new IllegalArgumentException(
17743                         "Cannot set '" + propertyName + "' to Float.NaN");
17744             }
17745             return 0; // Unclear which direction this NaN went so... 0?
17746         }
17747 
17748         // Shouldn't be possible to reach this.
17749         throw new IllegalStateException("How do you get here?? " + value);
17750     }
17751 
17752     /**
17753      * The visual x position of this view, in pixels. This is equivalent to the
17754      * {@link #setTranslationX(float) translationX} property plus the current
17755      * {@link #getLeft() left} property.
17756      *
17757      * @return The visual x position of this view, in pixels.
17758      */
17759     @ViewDebug.ExportedProperty(category = "drawing")
getX()17760     public float getX() {
17761         return mLeft + getTranslationX();
17762     }
17763 
17764     /**
17765      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
17766      * {@link #setTranslationX(float) translationX} property to be the difference between
17767      * the x value passed in and the current {@link #getLeft() left} property.
17768      *
17769      * @param x The visual x position of this view, in pixels.
17770      */
setX(float x)17771     public void setX(float x) {
17772         setTranslationX(x - mLeft);
17773     }
17774 
17775     /**
17776      * The visual y position of this view, in pixels. This is equivalent to the
17777      * {@link #setTranslationY(float) translationY} property plus the current
17778      * {@link #getTop() top} property.
17779      *
17780      * @return The visual y position of this view, in pixels.
17781      */
17782     @ViewDebug.ExportedProperty(category = "drawing")
getY()17783     public float getY() {
17784         return mTop + getTranslationY();
17785     }
17786 
17787     /**
17788      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
17789      * {@link #setTranslationY(float) translationY} property to be the difference between
17790      * the y value passed in and the current {@link #getTop() top} property.
17791      *
17792      * @param y The visual y position of this view, in pixels.
17793      */
setY(float y)17794     public void setY(float y) {
17795         setTranslationY(y - mTop);
17796     }
17797 
17798     /**
17799      * The visual z position of this view, in pixels. This is equivalent to the
17800      * {@link #setTranslationZ(float) translationZ} property plus the current
17801      * {@link #getElevation() elevation} property.
17802      *
17803      * @return The visual z position of this view, in pixels.
17804      */
17805     @ViewDebug.ExportedProperty(category = "drawing")
getZ()17806     public float getZ() {
17807         return getElevation() + getTranslationZ();
17808     }
17809 
17810     /**
17811      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
17812      * {@link #setTranslationZ(float) translationZ} property to be the difference between
17813      * the z value passed in and the current {@link #getElevation() elevation} property.
17814      *
17815      * @param z The visual z position of this view, in pixels.
17816      */
setZ(float z)17817     public void setZ(float z) {
17818         setTranslationZ(z - getElevation());
17819     }
17820 
17821     /**
17822      * The base elevation of this view relative to its parent, in pixels.
17823      *
17824      * @return The base depth position of the view, in pixels.
17825      */
17826     @ViewDebug.ExportedProperty(category = "drawing")
17827     @InspectableProperty
getElevation()17828     public float getElevation() {
17829         return mRenderNode.getElevation();
17830     }
17831 
17832     /**
17833      * Sets the base elevation of this view, in pixels.
17834      *
17835      * @attr ref android.R.styleable#View_elevation
17836      */
17837     @RemotableViewMethod
setElevation(float elevation)17838     public void setElevation(float elevation) {
17839         if (elevation != getElevation()) {
17840             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
17841             invalidateViewProperty(true, false);
17842             mRenderNode.setElevation(elevation);
17843             invalidateViewProperty(false, true);
17844 
17845             invalidateParentIfNeededAndWasQuickRejected();
17846         }
17847     }
17848 
17849     /**
17850      * The horizontal location of this view relative to its {@link #getLeft() left} position.
17851      * This position is post-layout, in addition to wherever the object's
17852      * layout placed it.
17853      *
17854      * @return The horizontal position of this view relative to its left position, in pixels.
17855      */
17856     @ViewDebug.ExportedProperty(category = "drawing")
17857     @InspectableProperty
getTranslationX()17858     public float getTranslationX() {
17859         return mRenderNode.getTranslationX();
17860     }
17861 
17862     /**
17863      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
17864      * This effectively positions the object post-layout, in addition to wherever the object's
17865      * layout placed it.
17866      *
17867      * @param translationX The horizontal position of this view relative to its left position,
17868      * in pixels.
17869      *
17870      * @attr ref android.R.styleable#View_translationX
17871      */
17872     @RemotableViewMethod
setTranslationX(float translationX)17873     public void setTranslationX(float translationX) {
17874         if (translationX != getTranslationX()) {
17875             invalidateViewProperty(true, false);
17876             mRenderNode.setTranslationX(translationX);
17877             invalidateViewProperty(false, true);
17878 
17879             invalidateParentIfNeededAndWasQuickRejected();
17880             notifySubtreeAccessibilityStateChangedIfNeeded();
17881         }
17882     }
17883 
17884     /**
17885      * The vertical location of this view relative to its {@link #getTop() top} position.
17886      * This position is post-layout, in addition to wherever the object's
17887      * layout placed it.
17888      *
17889      * @return The vertical position of this view relative to its top position,
17890      * in pixels.
17891      */
17892     @ViewDebug.ExportedProperty(category = "drawing")
17893     @InspectableProperty
getTranslationY()17894     public float getTranslationY() {
17895         return mRenderNode.getTranslationY();
17896     }
17897 
17898     /**
17899      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
17900      * This effectively positions the object post-layout, in addition to wherever the object's
17901      * layout placed it.
17902      *
17903      * @param translationY The vertical position of this view relative to its top position,
17904      * in pixels.
17905      *
17906      * @attr ref android.R.styleable#View_translationY
17907      */
17908     @RemotableViewMethod
setTranslationY(float translationY)17909     public void setTranslationY(float translationY) {
17910         if (translationY != getTranslationY()) {
17911             invalidateViewProperty(true, false);
17912             mRenderNode.setTranslationY(translationY);
17913             invalidateViewProperty(false, true);
17914 
17915             invalidateParentIfNeededAndWasQuickRejected();
17916             notifySubtreeAccessibilityStateChangedIfNeeded();
17917         }
17918     }
17919 
17920     /**
17921      * The depth location of this view relative to its {@link #getElevation() elevation}.
17922      *
17923      * @return The depth of this view relative to its elevation.
17924      */
17925     @ViewDebug.ExportedProperty(category = "drawing")
17926     @InspectableProperty
getTranslationZ()17927     public float getTranslationZ() {
17928         return mRenderNode.getTranslationZ();
17929     }
17930 
17931     /**
17932      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
17933      *
17934      * @attr ref android.R.styleable#View_translationZ
17935      */
17936     @RemotableViewMethod
setTranslationZ(float translationZ)17937     public void setTranslationZ(float translationZ) {
17938         if (translationZ != getTranslationZ()) {
17939             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
17940             invalidateViewProperty(true, false);
17941             mRenderNode.setTranslationZ(translationZ);
17942             invalidateViewProperty(false, true);
17943 
17944             invalidateParentIfNeededAndWasQuickRejected();
17945         }
17946     }
17947 
17948     /**
17949      * Changes the transformation matrix on the view. This is used in animation frameworks,
17950      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
17951      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
17952      * Application developers should use transformation methods like {@link #setRotation(float)},
17953      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
17954      * and {@link #setTranslationY(float)} (float)}} instead.
17955      *
17956      * @param matrix The matrix, null indicates that the matrix should be cleared.
17957      * @see #getAnimationMatrix()
17958      */
setAnimationMatrix(@ullable Matrix matrix)17959     public void setAnimationMatrix(@Nullable Matrix matrix) {
17960         invalidateViewProperty(true, false);
17961         mRenderNode.setAnimationMatrix(matrix);
17962         invalidateViewProperty(false, true);
17963 
17964         invalidateParentIfNeededAndWasQuickRejected();
17965     }
17966 
17967     /**
17968      * Return the current transformation matrix of the view. This is used in animation frameworks,
17969      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
17970      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
17971      * Application developers should use transformation methods like {@link #setRotation(float)},
17972      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
17973      * and {@link #setTranslationY(float)} (float)}} instead.
17974      *
17975      * @return the Matrix, null indicates there is no transformation
17976      * @see #setAnimationMatrix(Matrix)
17977      */
17978     @Nullable
getAnimationMatrix()17979     public Matrix getAnimationMatrix() {
17980         return mRenderNode.getAnimationMatrix();
17981     }
17982 
17983     /**
17984      * Returns the current StateListAnimator if exists.
17985      *
17986      * @return StateListAnimator or null if it does not exists
17987      * @see    #setStateListAnimator(android.animation.StateListAnimator)
17988      */
17989     @InspectableProperty
getStateListAnimator()17990     public StateListAnimator getStateListAnimator() {
17991         return mStateListAnimator;
17992     }
17993 
17994     /**
17995      * Attaches the provided StateListAnimator to this View.
17996      * <p>
17997      * Any previously attached StateListAnimator will be detached.
17998      *
17999      * @param stateListAnimator The StateListAnimator to update the view
18000      * @see android.animation.StateListAnimator
18001      */
setStateListAnimator(StateListAnimator stateListAnimator)18002     public void setStateListAnimator(StateListAnimator stateListAnimator) {
18003         if (mStateListAnimator == stateListAnimator) {
18004             return;
18005         }
18006         if (mStateListAnimator != null) {
18007             mStateListAnimator.setTarget(null);
18008         }
18009         mStateListAnimator = stateListAnimator;
18010         if (stateListAnimator != null) {
18011             stateListAnimator.setTarget(this);
18012             if (isAttachedToWindow()) {
18013                 stateListAnimator.setState(getDrawableState());
18014             }
18015         }
18016     }
18017 
18018     /**
18019      * Returns whether the Outline should be used to clip the contents of the View.
18020      * <p>
18021      * Note that this flag will only be respected if the View's Outline returns true from
18022      * {@link Outline#canClip()}.
18023      *
18024      * @see #setOutlineProvider(ViewOutlineProvider)
18025      * @see #setClipToOutline(boolean)
18026      */
getClipToOutline()18027     public final boolean getClipToOutline() {
18028         return mRenderNode.getClipToOutline();
18029     }
18030 
18031     /**
18032      * Sets whether the View's Outline should be used to clip the contents of the View.
18033      * <p>
18034      * Only a single non-rectangular clip can be applied on a View at any time.
18035      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
18036      * circular reveal} animation take priority over Outline clipping, and
18037      * child Outline clipping takes priority over Outline clipping done by a
18038      * parent.
18039      * <p>
18040      * Note that this flag will only be respected if the View's Outline returns true from
18041      * {@link Outline#canClip()}.
18042      *
18043      * @see #setOutlineProvider(ViewOutlineProvider)
18044      * @see #getClipToOutline()
18045      *
18046      * @attr ref android.R.styleable#View_clipToOutline
18047      */
18048     @RemotableViewMethod
setClipToOutline(boolean clipToOutline)18049     public void setClipToOutline(boolean clipToOutline) {
18050         damageInParent();
18051         if (getClipToOutline() != clipToOutline) {
18052             mRenderNode.setClipToOutline(clipToOutline);
18053         }
18054     }
18055 
18056     // correspond to the enum values of View_outlineProvider
18057     private static final int PROVIDER_BACKGROUND = 0;
18058     private static final int PROVIDER_NONE = 1;
18059     private static final int PROVIDER_BOUNDS = 2;
18060     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)18061     private void setOutlineProviderFromAttribute(int providerInt) {
18062         switch (providerInt) {
18063             case PROVIDER_BACKGROUND:
18064                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
18065                 break;
18066             case PROVIDER_NONE:
18067                 setOutlineProvider(null);
18068                 break;
18069             case PROVIDER_BOUNDS:
18070                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
18071                 break;
18072             case PROVIDER_PADDED_BOUNDS:
18073                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
18074                 break;
18075         }
18076     }
18077 
18078     /**
18079      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
18080      * the shape of the shadow it casts, and enables outline clipping.
18081      * <p>
18082      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
18083      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
18084      * outline provider with this method allows this behavior to be overridden.
18085      * <p>
18086      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
18087      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
18088      * <p>
18089      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
18090      *
18091      * @see #setClipToOutline(boolean)
18092      * @see #getClipToOutline()
18093      * @see #getOutlineProvider()
18094      */
setOutlineProvider(ViewOutlineProvider provider)18095     public void setOutlineProvider(ViewOutlineProvider provider) {
18096         mOutlineProvider = provider;
18097         invalidateOutline();
18098     }
18099 
18100     /**
18101      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
18102      * that defines the shape of the shadow it casts, and enables outline clipping.
18103      *
18104      * @see #setOutlineProvider(ViewOutlineProvider)
18105      */
18106     @InspectableProperty
getOutlineProvider()18107     public ViewOutlineProvider getOutlineProvider() {
18108         return mOutlineProvider;
18109     }
18110 
18111     /**
18112      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
18113      *
18114      * @see #setOutlineProvider(ViewOutlineProvider)
18115      */
invalidateOutline()18116     public void invalidateOutline() {
18117         rebuildOutline();
18118 
18119         notifySubtreeAccessibilityStateChangedIfNeeded();
18120         invalidateViewProperty(false, false);
18121     }
18122 
18123     /**
18124      * Internal version of {@link #invalidateOutline()} which invalidates the
18125      * outline without invalidating the view itself. This is intended to be called from
18126      * within methods in the View class itself which are the result of the view being
18127      * invalidated already. For example, when we are drawing the background of a View,
18128      * we invalidate the outline in case it changed in the meantime, but we do not
18129      * need to invalidate the view because we're already drawing the background as part
18130      * of drawing the view in response to an earlier invalidation of the view.
18131      */
rebuildOutline()18132     private void rebuildOutline() {
18133         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
18134         if (mAttachInfo == null) return;
18135 
18136         if (mOutlineProvider == null) {
18137             // no provider, remove outline
18138             mRenderNode.setOutline(null);
18139         } else {
18140             final Outline outline = mAttachInfo.mTmpOutline;
18141             outline.setEmpty();
18142             outline.setAlpha(1.0f);
18143 
18144             mOutlineProvider.getOutline(this, outline);
18145             mRenderNode.setOutline(outline);
18146         }
18147     }
18148 
18149     /**
18150      * HierarchyViewer only
18151      *
18152      * @hide
18153      */
18154     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()18155     public boolean hasShadow() {
18156         return mRenderNode.hasShadow();
18157     }
18158 
18159     /**
18160      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
18161      * elevation value.
18162      * <p>
18163      * By default the shadow color is black. Generally, this color will be opaque so the intensity
18164      * of the shadow is consistent between different views with different colors.
18165      * <p>
18166      * The opacity of the final spot shadow is a function of the shadow caster height, the
18167      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
18168      * {@link android.R.attr#spotShadowAlpha} theme attribute.
18169      *
18170      * @attr ref android.R.styleable#View_outlineSpotShadowColor
18171      * @param color The color this View will cast for its elevation spot shadow.
18172      */
setOutlineSpotShadowColor(@olorInt int color)18173     public void setOutlineSpotShadowColor(@ColorInt int color) {
18174         if (mRenderNode.setSpotShadowColor(color)) {
18175             invalidateViewProperty(true, true);
18176         }
18177     }
18178 
18179     /**
18180      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
18181      * was set
18182      */
18183     @InspectableProperty
getOutlineSpotShadowColor()18184     public @ColorInt int getOutlineSpotShadowColor() {
18185         return mRenderNode.getSpotShadowColor();
18186     }
18187 
18188     /**
18189      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
18190      * elevation value.
18191      * <p>
18192      * By default the shadow color is black. Generally, this color will be opaque so the intensity
18193      * of the shadow is consistent between different views with different colors.
18194      * <p>
18195      * The opacity of the final ambient shadow is a function of the shadow caster height, the
18196      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
18197      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
18198      *
18199      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
18200      * @param color The color this View will cast for its elevation shadow.
18201      */
setOutlineAmbientShadowColor(@olorInt int color)18202     public void setOutlineAmbientShadowColor(@ColorInt int color) {
18203         if (mRenderNode.setAmbientShadowColor(color)) {
18204             invalidateViewProperty(true, true);
18205         }
18206     }
18207 
18208     /**
18209      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
18210      * nothing was set
18211      */
18212     @InspectableProperty
getOutlineAmbientShadowColor()18213     public @ColorInt int getOutlineAmbientShadowColor() {
18214         return mRenderNode.getAmbientShadowColor();
18215     }
18216 
18217 
18218     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)18219     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
18220         mRenderNode.setRevealClip(shouldClip, x, y, radius);
18221         invalidateViewProperty(false, false);
18222     }
18223 
18224     /**
18225      * Hit rectangle in parent's coordinates
18226      *
18227      * @param outRect The hit rectangle of the view.
18228      */
getHitRect(Rect outRect)18229     public void getHitRect(Rect outRect) {
18230         if (hasIdentityMatrix() || mAttachInfo == null) {
18231             outRect.set(mLeft, mTop, mRight, mBottom);
18232         } else {
18233             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
18234             tmpRect.set(0, 0, getWidth(), getHeight());
18235             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
18236             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
18237                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
18238         }
18239     }
18240 
18241     /**
18242      * Determines whether the given point, in local coordinates is inside the view.
18243      */
pointInView(float localX, float localY)18244     /*package*/ final boolean pointInView(float localX, float localY) {
18245         return pointInView(localX, localY, 0);
18246     }
18247 
18248     /**
18249      * Utility method to determine whether the given point, in local coordinates,
18250      * is inside the view, where the area of the view is expanded by the slop factor.
18251      * This method is called while processing touch-move events to determine if the event
18252      * is still within the view.
18253      *
18254      * @hide
18255      */
18256     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)18257     public boolean pointInView(float localX, float localY, float slop) {
18258         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
18259                 localY < ((mBottom - mTop) + slop);
18260     }
18261 
18262     /**
18263      * When a view has focus and the user navigates away from it, the next view is searched for
18264      * starting from the rectangle filled in by this method.
18265      *
18266      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
18267      * of the view.  However, if your view maintains some idea of internal selection,
18268      * such as a cursor, or a selected row or column, you should override this method and
18269      * fill in a more specific rectangle.
18270      *
18271      * @param r The rectangle to fill in, in this view's coordinates.
18272      */
getFocusedRect(Rect r)18273     public void getFocusedRect(Rect r) {
18274         getDrawingRect(r);
18275     }
18276 
18277     /**
18278      * If some part of this view is not clipped by any of its parents, then
18279      * return that area in r in global (root) coordinates. To convert r to local
18280      * coordinates (without taking possible View rotations into account), offset
18281      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
18282      * If the view is completely clipped or translated out, return false.
18283      *
18284      * @param r If true is returned, r holds the global coordinates of the
18285      *        visible portion of this view.
18286      * @param globalOffset If true is returned, globalOffset holds the dx,dy
18287      *        between this view and its root. globalOffet may be null.
18288      * @return true if r is non-empty (i.e. part of the view is visible at the
18289      *         root level.
18290      */
getGlobalVisibleRect(Rect r, Point globalOffset)18291     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
18292         int width = mRight - mLeft;
18293         int height = mBottom - mTop;
18294         if (width > 0 && height > 0) {
18295             r.set(0, 0, width, height);
18296             if (globalOffset != null) {
18297                 globalOffset.set(-mScrollX, -mScrollY);
18298             }
18299             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
18300         }
18301         return false;
18302     }
18303 
getGlobalVisibleRect(Rect r)18304     public final boolean getGlobalVisibleRect(Rect r) {
18305         return getGlobalVisibleRect(r, null);
18306     }
18307 
getLocalVisibleRect(Rect r)18308     public final boolean getLocalVisibleRect(Rect r) {
18309         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
18310         if (getGlobalVisibleRect(r, offset)) {
18311             r.offset(-offset.x, -offset.y); // make r local
18312             return true;
18313         }
18314         return false;
18315     }
18316 
18317     /**
18318      * Offset this view's vertical location by the specified number of pixels.
18319      *
18320      * @param offset the number of pixels to offset the view by
18321      */
offsetTopAndBottom(int offset)18322     public void offsetTopAndBottom(int offset) {
18323         if (offset != 0) {
18324             final boolean matrixIsIdentity = hasIdentityMatrix();
18325             if (matrixIsIdentity) {
18326                 if (isHardwareAccelerated()) {
18327                     invalidateViewProperty(false, false);
18328                 } else {
18329                     final ViewParent p = mParent;
18330                     if (p != null && mAttachInfo != null) {
18331                         final Rect r = mAttachInfo.mTmpInvalRect;
18332                         int minTop;
18333                         int maxBottom;
18334                         int yLoc;
18335                         if (offset < 0) {
18336                             minTop = mTop + offset;
18337                             maxBottom = mBottom;
18338                             yLoc = offset;
18339                         } else {
18340                             minTop = mTop;
18341                             maxBottom = mBottom + offset;
18342                             yLoc = 0;
18343                         }
18344                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
18345                         p.invalidateChild(this, r);
18346                     }
18347                 }
18348             } else {
18349                 invalidateViewProperty(false, false);
18350             }
18351 
18352             mTop += offset;
18353             mBottom += offset;
18354             mRenderNode.offsetTopAndBottom(offset);
18355             if (isHardwareAccelerated()) {
18356                 invalidateViewProperty(false, false);
18357                 invalidateParentIfNeededAndWasQuickRejected();
18358             } else {
18359                 if (!matrixIsIdentity) {
18360                     invalidateViewProperty(false, true);
18361                 }
18362                 invalidateParentIfNeeded();
18363             }
18364             notifySubtreeAccessibilityStateChangedIfNeeded();
18365         }
18366     }
18367 
18368     /**
18369      * Offset this view's horizontal location by the specified amount of pixels.
18370      *
18371      * @param offset the number of pixels to offset the view by
18372      */
offsetLeftAndRight(int offset)18373     public void offsetLeftAndRight(int offset) {
18374         if (offset != 0) {
18375             final boolean matrixIsIdentity = hasIdentityMatrix();
18376             if (matrixIsIdentity) {
18377                 if (isHardwareAccelerated()) {
18378                     invalidateViewProperty(false, false);
18379                 } else {
18380                     final ViewParent p = mParent;
18381                     if (p != null && mAttachInfo != null) {
18382                         final Rect r = mAttachInfo.mTmpInvalRect;
18383                         int minLeft;
18384                         int maxRight;
18385                         if (offset < 0) {
18386                             minLeft = mLeft + offset;
18387                             maxRight = mRight;
18388                         } else {
18389                             minLeft = mLeft;
18390                             maxRight = mRight + offset;
18391                         }
18392                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
18393                         p.invalidateChild(this, r);
18394                     }
18395                 }
18396             } else {
18397                 invalidateViewProperty(false, false);
18398             }
18399 
18400             mLeft += offset;
18401             mRight += offset;
18402             mRenderNode.offsetLeftAndRight(offset);
18403             if (isHardwareAccelerated()) {
18404                 invalidateViewProperty(false, false);
18405                 invalidateParentIfNeededAndWasQuickRejected();
18406             } else {
18407                 if (!matrixIsIdentity) {
18408                     invalidateViewProperty(false, true);
18409                 }
18410                 invalidateParentIfNeeded();
18411             }
18412             notifySubtreeAccessibilityStateChangedIfNeeded();
18413         }
18414     }
18415 
18416     /**
18417      * Get the LayoutParams associated with this view. All views should have
18418      * layout parameters. These supply parameters to the <i>parent</i> of this
18419      * view specifying how it should be arranged. There are many subclasses of
18420      * ViewGroup.LayoutParams, and these correspond to the different subclasses
18421      * of ViewGroup that are responsible for arranging their children.
18422      *
18423      * This method may return null if this View is not attached to a parent
18424      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
18425      * was not invoked successfully. When a View is attached to a parent
18426      * ViewGroup, this method must not return null.
18427      *
18428      * @return The LayoutParams associated with this view, or null if no
18429      *         parameters have been set yet
18430      */
18431     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()18432     public ViewGroup.LayoutParams getLayoutParams() {
18433         return mLayoutParams;
18434     }
18435 
18436     /**
18437      * Set the layout parameters associated with this view. These supply
18438      * parameters to the <i>parent</i> of this view specifying how it should be
18439      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
18440      * correspond to the different subclasses of ViewGroup that are responsible
18441      * for arranging their children.
18442      *
18443      * @param params The layout parameters for this view, cannot be null
18444      */
setLayoutParams(ViewGroup.LayoutParams params)18445     public void setLayoutParams(ViewGroup.LayoutParams params) {
18446         if (params == null) {
18447             throw new NullPointerException("Layout parameters cannot be null");
18448         }
18449         mLayoutParams = params;
18450         resolveLayoutParams();
18451         if (mParent instanceof ViewGroup) {
18452             ((ViewGroup) mParent).onSetLayoutParams(this, params);
18453         }
18454         requestLayout();
18455     }
18456 
18457     /**
18458      * Resolve the layout parameters depending on the resolved layout direction
18459      *
18460      * @hide
18461      */
resolveLayoutParams()18462     public void resolveLayoutParams() {
18463         if (mLayoutParams != null) {
18464             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
18465         }
18466     }
18467 
18468     /**
18469      * Set the scrolled position of your view. This will cause a call to
18470      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18471      * invalidated.
18472      * @param x the x position to scroll to
18473      * @param y the y position to scroll to
18474      */
scrollTo(int x, int y)18475     public void scrollTo(int x, int y) {
18476         if (mScrollX != x || mScrollY != y) {
18477             int oldX = mScrollX;
18478             int oldY = mScrollY;
18479             mScrollX = x;
18480             mScrollY = y;
18481             invalidateParentCaches();
18482             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
18483             if (!awakenScrollBars()) {
18484                 postInvalidateOnAnimation();
18485             }
18486         }
18487     }
18488 
18489     /**
18490      * Move the scrolled position of your view. This will cause a call to
18491      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18492      * invalidated.
18493      * @param x the amount of pixels to scroll by horizontally
18494      * @param y the amount of pixels to scroll by vertically
18495      */
scrollBy(int x, int y)18496     public void scrollBy(int x, int y) {
18497         scrollTo(mScrollX + x, mScrollY + y);
18498     }
18499 
18500     /**
18501      * <p>Trigger the scrollbars to draw. When invoked this method starts an
18502      * animation to fade the scrollbars out after a default delay. If a subclass
18503      * provides animated scrolling, the start delay should equal the duration
18504      * of the scrolling animation.</p>
18505      *
18506      * <p>The animation starts only if at least one of the scrollbars is
18507      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
18508      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18509      * this method returns true, and false otherwise. If the animation is
18510      * started, this method calls {@link #invalidate()}; in that case the
18511      * caller should not call {@link #invalidate()}.</p>
18512      *
18513      * <p>This method should be invoked every time a subclass directly updates
18514      * the scroll parameters.</p>
18515      *
18516      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
18517      * and {@link #scrollTo(int, int)}.</p>
18518      *
18519      * @return true if the animation is played, false otherwise
18520      *
18521      * @see #awakenScrollBars(int)
18522      * @see #scrollBy(int, int)
18523      * @see #scrollTo(int, int)
18524      * @see #isHorizontalScrollBarEnabled()
18525      * @see #isVerticalScrollBarEnabled()
18526      * @see #setHorizontalScrollBarEnabled(boolean)
18527      * @see #setVerticalScrollBarEnabled(boolean)
18528      */
awakenScrollBars()18529     protected boolean awakenScrollBars() {
18530         return mScrollCache != null &&
18531                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
18532     }
18533 
18534     /**
18535      * Trigger the scrollbars to draw.
18536      * This method differs from awakenScrollBars() only in its default duration.
18537      * initialAwakenScrollBars() will show the scroll bars for longer than
18538      * usual to give the user more of a chance to notice them.
18539      *
18540      * @return true if the animation is played, false otherwise.
18541      */
initialAwakenScrollBars()18542     private boolean initialAwakenScrollBars() {
18543         return mScrollCache != null &&
18544                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
18545     }
18546 
18547     /**
18548      * <p>
18549      * Trigger the scrollbars to draw. When invoked this method starts an
18550      * animation to fade the scrollbars out after a fixed delay. If a subclass
18551      * provides animated scrolling, the start delay should equal the duration of
18552      * the scrolling animation.
18553      * </p>
18554      *
18555      * <p>
18556      * The animation starts only if at least one of the scrollbars is enabled,
18557      * as specified by {@link #isHorizontalScrollBarEnabled()} and
18558      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18559      * this method returns true, and false otherwise. If the animation is
18560      * started, this method calls {@link #invalidate()}; in that case the caller
18561      * should not call {@link #invalidate()}.
18562      * </p>
18563      *
18564      * <p>
18565      * This method should be invoked every time a subclass directly updates the
18566      * scroll parameters.
18567      * </p>
18568      *
18569      * @param startDelay the delay, in milliseconds, after which the animation
18570      *        should start; when the delay is 0, the animation starts
18571      *        immediately
18572      * @return true if the animation is played, false otherwise
18573      *
18574      * @see #scrollBy(int, int)
18575      * @see #scrollTo(int, int)
18576      * @see #isHorizontalScrollBarEnabled()
18577      * @see #isVerticalScrollBarEnabled()
18578      * @see #setHorizontalScrollBarEnabled(boolean)
18579      * @see #setVerticalScrollBarEnabled(boolean)
18580      */
awakenScrollBars(int startDelay)18581     protected boolean awakenScrollBars(int startDelay) {
18582         return awakenScrollBars(startDelay, true);
18583     }
18584 
18585     /**
18586      * <p>
18587      * Trigger the scrollbars to draw. When invoked this method starts an
18588      * animation to fade the scrollbars out after a fixed delay. If a subclass
18589      * provides animated scrolling, the start delay should equal the duration of
18590      * the scrolling animation.
18591      * </p>
18592      *
18593      * <p>
18594      * The animation starts only if at least one of the scrollbars is enabled,
18595      * as specified by {@link #isHorizontalScrollBarEnabled()} and
18596      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18597      * this method returns true, and false otherwise. If the animation is
18598      * started, this method calls {@link #invalidate()} if the invalidate parameter
18599      * is set to true; in that case the caller
18600      * should not call {@link #invalidate()}.
18601      * </p>
18602      *
18603      * <p>
18604      * This method should be invoked every time a subclass directly updates the
18605      * scroll parameters.
18606      * </p>
18607      *
18608      * @param startDelay the delay, in milliseconds, after which the animation
18609      *        should start; when the delay is 0, the animation starts
18610      *        immediately
18611      *
18612      * @param invalidate Whether this method should call invalidate
18613      *
18614      * @return true if the animation is played, false otherwise
18615      *
18616      * @see #scrollBy(int, int)
18617      * @see #scrollTo(int, int)
18618      * @see #isHorizontalScrollBarEnabled()
18619      * @see #isVerticalScrollBarEnabled()
18620      * @see #setHorizontalScrollBarEnabled(boolean)
18621      * @see #setVerticalScrollBarEnabled(boolean)
18622      */
awakenScrollBars(int startDelay, boolean invalidate)18623     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
18624         final ScrollabilityCache scrollCache = mScrollCache;
18625 
18626         if (scrollCache == null || !scrollCache.fadeScrollBars) {
18627             return false;
18628         }
18629 
18630         if (scrollCache.scrollBar == null) {
18631             scrollCache.scrollBar = new ScrollBarDrawable();
18632             scrollCache.scrollBar.setState(getDrawableState());
18633             scrollCache.scrollBar.setCallback(this);
18634         }
18635 
18636         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
18637 
18638             if (invalidate) {
18639                 // Invalidate to show the scrollbars
18640                 postInvalidateOnAnimation();
18641             }
18642 
18643             if (scrollCache.state == ScrollabilityCache.OFF) {
18644                 // FIXME: this is copied from WindowManagerService.
18645                 // We should get this value from the system when it
18646                 // is possible to do so.
18647                 final int KEY_REPEAT_FIRST_DELAY = 750;
18648                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
18649             }
18650 
18651             // Tell mScrollCache when we should start fading. This may
18652             // extend the fade start time if one was already scheduled
18653             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
18654             scrollCache.fadeStartTime = fadeStartTime;
18655             scrollCache.state = ScrollabilityCache.ON;
18656 
18657             // Schedule our fader to run, unscheduling any old ones first
18658             if (mAttachInfo != null) {
18659                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
18660                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
18661             }
18662 
18663             return true;
18664         }
18665 
18666         return false;
18667     }
18668 
18669     /**
18670      * Do not invalidate views which are not visible and which are not running an animation. They
18671      * will not get drawn and they should not set dirty flags as if they will be drawn
18672      */
skipInvalidate()18673     private boolean skipInvalidate() {
18674         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
18675                 (!(mParent instanceof ViewGroup) ||
18676                         !((ViewGroup) mParent).isViewTransitioning(this));
18677     }
18678 
18679     /**
18680      * Mark the area defined by dirty as needing to be drawn. If the view is
18681      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18682      * point in the future.
18683      * <p>
18684      * This must be called from a UI thread. To call from a non-UI thread, call
18685      * {@link #postInvalidate()}.
18686      * <p>
18687      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
18688      * {@code dirty}.
18689      *
18690      * @param dirty the rectangle representing the bounds of the dirty region
18691      *
18692      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18693      * the importance of the dirty rectangle. In API 21 the given rectangle is
18694      * ignored entirely in favor of an internally-calculated area instead.
18695      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18696      */
18697     @Deprecated
invalidate(Rect dirty)18698     public void invalidate(Rect dirty) {
18699         final int scrollX = mScrollX;
18700         final int scrollY = mScrollY;
18701         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
18702                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
18703     }
18704 
18705     /**
18706      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
18707      * coordinates of the dirty rect are relative to the view. If the view is
18708      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18709      * point in the future.
18710      * <p>
18711      * This must be called from a UI thread. To call from a non-UI thread, call
18712      * {@link #postInvalidate()}.
18713      *
18714      * @param l the left position of the dirty region
18715      * @param t the top position of the dirty region
18716      * @param r the right position of the dirty region
18717      * @param b the bottom position of the dirty region
18718      *
18719      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18720      * the importance of the dirty rectangle. In API 21 the given rectangle is
18721      * ignored entirely in favor of an internally-calculated area instead.
18722      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18723      */
18724     @Deprecated
invalidate(int l, int t, int r, int b)18725     public void invalidate(int l, int t, int r, int b) {
18726         final int scrollX = mScrollX;
18727         final int scrollY = mScrollY;
18728         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
18729     }
18730 
18731     /**
18732      * Invalidate the whole view. If the view is visible,
18733      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
18734      * the future.
18735      * <p>
18736      * This must be called from a UI thread. To call from a non-UI thread, call
18737      * {@link #postInvalidate()}.
18738      */
invalidate()18739     public void invalidate() {
18740         invalidate(true);
18741     }
18742 
18743     /**
18744      * This is where the invalidate() work actually happens. A full invalidate()
18745      * causes the drawing cache to be invalidated, but this function can be
18746      * called with invalidateCache set to false to skip that invalidation step
18747      * for cases that do not need it (for example, a component that remains at
18748      * the same dimensions with the same content).
18749      *
18750      * @param invalidateCache Whether the drawing cache for this view should be
18751      *            invalidated as well. This is usually true for a full
18752      *            invalidate, but may be set to false if the View's contents or
18753      *            dimensions have not changed.
18754      * @hide
18755      */
18756     @UnsupportedAppUsage
invalidate(boolean invalidateCache)18757     public void invalidate(boolean invalidateCache) {
18758         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
18759     }
18760 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)18761     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
18762             boolean fullInvalidate) {
18763         if (mGhostView != null) {
18764             mGhostView.invalidate(true);
18765             return;
18766         }
18767 
18768         if (skipInvalidate()) {
18769             return;
18770         }
18771 
18772         // Reset content capture caches
18773         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
18774         mContentCaptureSessionCached = false;
18775 
18776         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
18777                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
18778                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
18779                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
18780             if (fullInvalidate) {
18781                 mLastIsOpaque = isOpaque();
18782                 mPrivateFlags &= ~PFLAG_DRAWN;
18783             }
18784 
18785             mPrivateFlags |= PFLAG_DIRTY;
18786 
18787             if (invalidateCache) {
18788                 mPrivateFlags |= PFLAG_INVALIDATED;
18789                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18790             }
18791 
18792             // Propagate the damage rectangle to the parent view.
18793             final AttachInfo ai = mAttachInfo;
18794             final ViewParent p = mParent;
18795             if (p != null && ai != null && l < r && t < b) {
18796                 final Rect damage = ai.mTmpInvalRect;
18797                 damage.set(l, t, r, b);
18798                 p.invalidateChild(this, damage);
18799             }
18800 
18801             // Damage the entire projection receiver, if necessary.
18802             if (mBackground != null && mBackground.isProjected()) {
18803                 final View receiver = getProjectionReceiver();
18804                 if (receiver != null) {
18805                     receiver.damageInParent();
18806                 }
18807             }
18808         }
18809     }
18810 
18811     /**
18812      * @return this view's projection receiver, or {@code null} if none exists
18813      */
getProjectionReceiver()18814     private View getProjectionReceiver() {
18815         ViewParent p = getParent();
18816         while (p != null && p instanceof View) {
18817             final View v = (View) p;
18818             if (v.isProjectionReceiver()) {
18819                 return v;
18820             }
18821             p = p.getParent();
18822         }
18823 
18824         return null;
18825     }
18826 
18827     /**
18828      * @return whether the view is a projection receiver
18829      */
isProjectionReceiver()18830     private boolean isProjectionReceiver() {
18831         return mBackground != null;
18832     }
18833 
18834     /**
18835      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
18836      * set any flags or handle all of the cases handled by the default invalidation methods.
18837      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
18838      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
18839      * walk up the hierarchy, transforming the dirty rect as necessary.
18840      *
18841      * The method also handles normal invalidation logic if display list properties are not
18842      * being used in this view. The invalidateParent and forceRedraw flags are used by that
18843      * backup approach, to handle these cases used in the various property-setting methods.
18844      *
18845      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
18846      * are not being used in this view
18847      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
18848      * list properties are not being used in this view
18849      */
18850     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)18851     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
18852         if (!isHardwareAccelerated()
18853                 || !mRenderNode.hasDisplayList()
18854                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
18855             if (invalidateParent) {
18856                 invalidateParentCaches();
18857             }
18858             if (forceRedraw) {
18859                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18860             }
18861             invalidate(false);
18862         } else {
18863             damageInParent();
18864         }
18865     }
18866 
18867     /**
18868      * Tells the parent view to damage this view's bounds.
18869      *
18870      * @hide
18871      */
damageInParent()18872     protected void damageInParent() {
18873         if (mParent != null && mAttachInfo != null) {
18874             mParent.onDescendantInvalidated(this, this);
18875         }
18876     }
18877 
18878     /**
18879      * Used to indicate that the parent of this view should clear its caches. This functionality
18880      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18881      * which is necessary when various parent-managed properties of the view change, such as
18882      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
18883      * clears the parent caches and does not causes an invalidate event.
18884      *
18885      * @hide
18886      */
18887     @UnsupportedAppUsage
invalidateParentCaches()18888     protected void invalidateParentCaches() {
18889         if (mParent instanceof View) {
18890             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
18891         }
18892     }
18893 
18894     /**
18895      * Used to indicate that the parent of this view should be invalidated. This functionality
18896      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18897      * which is necessary when various parent-managed properties of the view change, such as
18898      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
18899      * an invalidation event to the parent.
18900      *
18901      * @hide
18902      */
18903     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
invalidateParentIfNeeded()18904     protected void invalidateParentIfNeeded() {
18905         if (isHardwareAccelerated() && mParent instanceof View) {
18906             ((View) mParent).invalidate(true);
18907         }
18908     }
18909 
18910     /**
18911      * @hide
18912      */
invalidateParentIfNeededAndWasQuickRejected()18913     protected void invalidateParentIfNeededAndWasQuickRejected() {
18914         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
18915             // View was rejected last time it was drawn by its parent; this may have changed
18916             invalidateParentIfNeeded();
18917         }
18918     }
18919 
18920     /**
18921      * Indicates whether this View is opaque. An opaque View guarantees that it will
18922      * draw all the pixels overlapping its bounds using a fully opaque color.
18923      *
18924      * Subclasses of View should override this method whenever possible to indicate
18925      * whether an instance is opaque. Opaque Views are treated in a special way by
18926      * the View hierarchy, possibly allowing it to perform optimizations during
18927      * invalidate/draw passes.
18928      *
18929      * @return True if this View is guaranteed to be fully opaque, false otherwise.
18930      */
18931     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()18932     public boolean isOpaque() {
18933         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
18934                 getFinalAlpha() >= 1.0f;
18935     }
18936 
18937     /**
18938      * @hide
18939      */
18940     @UnsupportedAppUsage
computeOpaqueFlags()18941     protected void computeOpaqueFlags() {
18942         // Opaque if:
18943         //   - Has a background
18944         //   - Background is opaque
18945         //   - Doesn't have scrollbars or scrollbars overlay
18946 
18947         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
18948             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
18949         } else {
18950             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
18951         }
18952 
18953         final int flags = mViewFlags;
18954         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
18955                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
18956                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
18957             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
18958         } else {
18959             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
18960         }
18961     }
18962 
18963     /**
18964      * @hide
18965      */
hasOpaqueScrollbars()18966     protected boolean hasOpaqueScrollbars() {
18967         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
18968     }
18969 
18970     /**
18971      * @return A handler associated with the thread running the View. This
18972      * handler can be used to pump events in the UI events queue.
18973      */
getHandler()18974     public Handler getHandler() {
18975         final AttachInfo attachInfo = mAttachInfo;
18976         if (attachInfo != null) {
18977             return attachInfo.mHandler;
18978         }
18979         return null;
18980     }
18981 
18982     /**
18983      * Returns the queue of runnable for this view.
18984      *
18985      * @return the queue of runnables for this view
18986      */
getRunQueue()18987     private HandlerActionQueue getRunQueue() {
18988         if (mRunQueue == null) {
18989             mRunQueue = new HandlerActionQueue();
18990         }
18991         return mRunQueue;
18992     }
18993 
18994     /**
18995      * Gets the view root associated with the View.
18996      * @return The view root, or null if none.
18997      * @hide
18998      */
18999     @UnsupportedAppUsage
getViewRootImpl()19000     public ViewRootImpl getViewRootImpl() {
19001         if (mAttachInfo != null) {
19002             return mAttachInfo.mViewRootImpl;
19003         }
19004         return null;
19005     }
19006 
19007     /**
19008      * @hide
19009      */
19010     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getThreadedRenderer()19011     public ThreadedRenderer getThreadedRenderer() {
19012         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
19013     }
19014 
19015     /**
19016      * <p>Causes the Runnable to be added to the message queue.
19017      * The runnable will be run on the user interface thread.</p>
19018      *
19019      * @param action The Runnable that will be executed.
19020      *
19021      * @return Returns true if the Runnable was successfully placed in to the
19022      *         message queue.  Returns false on failure, usually because the
19023      *         looper processing the message queue is exiting.
19024      *
19025      * @see #postDelayed
19026      * @see #removeCallbacks
19027      */
post(Runnable action)19028     public boolean post(Runnable action) {
19029         final AttachInfo attachInfo = mAttachInfo;
19030         if (attachInfo != null) {
19031             return attachInfo.mHandler.post(action);
19032         }
19033 
19034         // Postpone the runnable until we know on which thread it needs to run.
19035         // Assume that the runnable will be successfully placed after attach.
19036         getRunQueue().post(action);
19037         return true;
19038     }
19039 
19040     /**
19041      * <p>Causes the Runnable to be added to the message queue, to be run
19042      * after the specified amount of time elapses.
19043      * The runnable will be run on the user interface thread.</p>
19044      *
19045      * @param action The Runnable that will be executed.
19046      * @param delayMillis The delay (in milliseconds) until the Runnable
19047      *        will be executed.
19048      *
19049      * @return true if the Runnable was successfully placed in to the
19050      *         message queue.  Returns false on failure, usually because the
19051      *         looper processing the message queue is exiting.  Note that a
19052      *         result of true does not mean the Runnable will be processed --
19053      *         if the looper is quit before the delivery time of the message
19054      *         occurs then the message will be dropped.
19055      *
19056      * @see #post
19057      * @see #removeCallbacks
19058      */
postDelayed(Runnable action, long delayMillis)19059     public boolean postDelayed(Runnable action, long delayMillis) {
19060         final AttachInfo attachInfo = mAttachInfo;
19061         if (attachInfo != null) {
19062             return attachInfo.mHandler.postDelayed(action, delayMillis);
19063         }
19064 
19065         // Postpone the runnable until we know on which thread it needs to run.
19066         // Assume that the runnable will be successfully placed after attach.
19067         getRunQueue().postDelayed(action, delayMillis);
19068         return true;
19069     }
19070 
19071     /**
19072      * <p>Causes the Runnable to execute on the next animation time step.
19073      * The runnable will be run on the user interface thread.</p>
19074      *
19075      * @param action The Runnable that will be executed.
19076      *
19077      * @see #postOnAnimationDelayed
19078      * @see #removeCallbacks
19079      */
postOnAnimation(Runnable action)19080     public void postOnAnimation(Runnable action) {
19081         final AttachInfo attachInfo = mAttachInfo;
19082         if (attachInfo != null) {
19083             attachInfo.mViewRootImpl.mChoreographer.postCallback(
19084                     Choreographer.CALLBACK_ANIMATION, action, null);
19085         } else {
19086             // Postpone the runnable until we know
19087             // on which thread it needs to run.
19088             getRunQueue().post(action);
19089         }
19090     }
19091 
19092     /**
19093      * <p>Causes the Runnable to execute on the next animation time step,
19094      * after the specified amount of time elapses.
19095      * The runnable will be run on the user interface thread.</p>
19096      *
19097      * @param action The Runnable that will be executed.
19098      * @param delayMillis The delay (in milliseconds) until the Runnable
19099      *        will be executed.
19100      *
19101      * @see #postOnAnimation
19102      * @see #removeCallbacks
19103      */
postOnAnimationDelayed(Runnable action, long delayMillis)19104     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
19105         final AttachInfo attachInfo = mAttachInfo;
19106         if (attachInfo != null) {
19107             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19108                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
19109         } else {
19110             // Postpone the runnable until we know
19111             // on which thread it needs to run.
19112             getRunQueue().postDelayed(action, delayMillis);
19113         }
19114     }
19115 
19116     /**
19117      * <p>Removes the specified Runnable from the message queue.</p>
19118      *
19119      * @param action The Runnable to remove from the message handling queue
19120      *
19121      * @return true if this view could ask the Handler to remove the Runnable,
19122      *         false otherwise. When the returned value is true, the Runnable
19123      *         may or may not have been actually removed from the message queue
19124      *         (for instance, if the Runnable was not in the queue already.)
19125      *
19126      * @see #post
19127      * @see #postDelayed
19128      * @see #postOnAnimation
19129      * @see #postOnAnimationDelayed
19130      */
removeCallbacks(Runnable action)19131     public boolean removeCallbacks(Runnable action) {
19132         if (action != null) {
19133             final AttachInfo attachInfo = mAttachInfo;
19134             if (attachInfo != null) {
19135                 attachInfo.mHandler.removeCallbacks(action);
19136                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19137                         Choreographer.CALLBACK_ANIMATION, action, null);
19138             }
19139             getRunQueue().removeCallbacks(action);
19140         }
19141         return true;
19142     }
19143 
19144     /**
19145      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
19146      * Use this to invalidate the View from a non-UI thread.</p>
19147      *
19148      * <p>This method can be invoked from outside of the UI thread
19149      * only when this View is attached to a window.</p>
19150      *
19151      * @see #invalidate()
19152      * @see #postInvalidateDelayed(long)
19153      */
postInvalidate()19154     public void postInvalidate() {
19155         postInvalidateDelayed(0);
19156     }
19157 
19158     /**
19159      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
19160      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
19161      *
19162      * <p>This method can be invoked from outside of the UI thread
19163      * only when this View is attached to a window.</p>
19164      *
19165      * @param left The left coordinate of the rectangle to invalidate.
19166      * @param top The top coordinate of the rectangle to invalidate.
19167      * @param right The right coordinate of the rectangle to invalidate.
19168      * @param bottom The bottom coordinate of the rectangle to invalidate.
19169      *
19170      * @see #invalidate(int, int, int, int)
19171      * @see #invalidate(Rect)
19172      * @see #postInvalidateDelayed(long, int, int, int, int)
19173      */
postInvalidate(int left, int top, int right, int bottom)19174     public void postInvalidate(int left, int top, int right, int bottom) {
19175         postInvalidateDelayed(0, left, top, right, bottom);
19176     }
19177 
19178     /**
19179      * <p>Cause an invalidate to happen on a subsequent cycle through the event
19180      * loop. Waits for the specified amount of time.</p>
19181      *
19182      * <p>This method can be invoked from outside of the UI thread
19183      * only when this View is attached to a window.</p>
19184      *
19185      * @param delayMilliseconds the duration in milliseconds to delay the
19186      *         invalidation by
19187      *
19188      * @see #invalidate()
19189      * @see #postInvalidate()
19190      */
postInvalidateDelayed(long delayMilliseconds)19191     public void postInvalidateDelayed(long delayMilliseconds) {
19192         // We try only with the AttachInfo because there's no point in invalidating
19193         // if we are not attached to our window
19194         final AttachInfo attachInfo = mAttachInfo;
19195         if (attachInfo != null) {
19196             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
19197         }
19198     }
19199 
19200     /**
19201      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
19202      * through the event loop. Waits for the specified amount of time.</p>
19203      *
19204      * <p>This method can be invoked from outside of the UI thread
19205      * only when this View is attached to a window.</p>
19206      *
19207      * @param delayMilliseconds the duration in milliseconds to delay the
19208      *         invalidation by
19209      * @param left The left coordinate of the rectangle to invalidate.
19210      * @param top The top coordinate of the rectangle to invalidate.
19211      * @param right The right coordinate of the rectangle to invalidate.
19212      * @param bottom The bottom coordinate of the rectangle to invalidate.
19213      *
19214      * @see #invalidate(int, int, int, int)
19215      * @see #invalidate(Rect)
19216      * @see #postInvalidate(int, int, int, int)
19217      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)19218     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
19219             int right, int bottom) {
19220 
19221         // We try only with the AttachInfo because there's no point in invalidating
19222         // if we are not attached to our window
19223         final AttachInfo attachInfo = mAttachInfo;
19224         if (attachInfo != null) {
19225             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19226             info.target = this;
19227             info.left = left;
19228             info.top = top;
19229             info.right = right;
19230             info.bottom = bottom;
19231 
19232             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
19233         }
19234     }
19235 
19236     /**
19237      * <p>Cause an invalidate to happen on the next animation time step, typically the
19238      * next display frame.</p>
19239      *
19240      * <p>This method can be invoked from outside of the UI thread
19241      * only when this View is attached to a window.</p>
19242      *
19243      * @see #invalidate()
19244      */
postInvalidateOnAnimation()19245     public void postInvalidateOnAnimation() {
19246         // We try only with the AttachInfo because there's no point in invalidating
19247         // if we are not attached to our window
19248         final AttachInfo attachInfo = mAttachInfo;
19249         if (attachInfo != null) {
19250             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
19251         }
19252     }
19253 
19254     /**
19255      * <p>Cause an invalidate of the specified area to happen on the next animation
19256      * time step, typically the next display frame.</p>
19257      *
19258      * <p>This method can be invoked from outside of the UI thread
19259      * only when this View is attached to a window.</p>
19260      *
19261      * @param left The left coordinate of the rectangle to invalidate.
19262      * @param top The top coordinate of the rectangle to invalidate.
19263      * @param right The right coordinate of the rectangle to invalidate.
19264      * @param bottom The bottom coordinate of the rectangle to invalidate.
19265      *
19266      * @see #invalidate(int, int, int, int)
19267      * @see #invalidate(Rect)
19268      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)19269     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
19270         // We try only with the AttachInfo because there's no point in invalidating
19271         // if we are not attached to our window
19272         final AttachInfo attachInfo = mAttachInfo;
19273         if (attachInfo != null) {
19274             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19275             info.target = this;
19276             info.left = left;
19277             info.top = top;
19278             info.right = right;
19279             info.bottom = bottom;
19280 
19281             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
19282         }
19283     }
19284 
19285     /**
19286      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
19287      * This event is sent at most once every
19288      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
19289      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)19290     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
19291         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
19292             AccessibilityEvent event =
19293                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
19294             event.setScrollDeltaX(dx);
19295             event.setScrollDeltaY(dy);
19296             sendAccessibilityEventUnchecked(event);
19297         }
19298     }
19299 
19300     /**
19301      * Called by a parent to request that a child update its values for mScrollX
19302      * and mScrollY if necessary. This will typically be done if the child is
19303      * animating a scroll using a {@link android.widget.Scroller Scroller}
19304      * object.
19305      */
computeScroll()19306     public void computeScroll() {
19307     }
19308 
19309     /**
19310      * <p>Indicate whether the horizontal edges are faded when the view is
19311      * scrolled horizontally.</p>
19312      *
19313      * @return true if the horizontal edges should are faded on scroll, false
19314      *         otherwise
19315      *
19316      * @see #setHorizontalFadingEdgeEnabled(boolean)
19317      *
19318      * @attr ref android.R.styleable#View_requiresFadingEdge
19319      */
isHorizontalFadingEdgeEnabled()19320     public boolean isHorizontalFadingEdgeEnabled() {
19321         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
19322     }
19323 
19324     /**
19325      * <p>Define whether the horizontal edges should be faded when this view
19326      * is scrolled horizontally.</p>
19327      *
19328      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
19329      *                                    be faded when the view is scrolled
19330      *                                    horizontally
19331      *
19332      * @see #isHorizontalFadingEdgeEnabled()
19333      *
19334      * @attr ref android.R.styleable#View_requiresFadingEdge
19335      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)19336     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
19337         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
19338             if (horizontalFadingEdgeEnabled) {
19339                 initScrollCache();
19340             }
19341 
19342             mViewFlags ^= FADING_EDGE_HORIZONTAL;
19343         }
19344     }
19345 
19346     /**
19347      * <p>Indicate whether the vertical edges are faded when the view is
19348      * scrolled horizontally.</p>
19349      *
19350      * @return true if the vertical edges should are faded on scroll, false
19351      *         otherwise
19352      *
19353      * @see #setVerticalFadingEdgeEnabled(boolean)
19354      *
19355      * @attr ref android.R.styleable#View_requiresFadingEdge
19356      */
isVerticalFadingEdgeEnabled()19357     public boolean isVerticalFadingEdgeEnabled() {
19358         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
19359     }
19360 
19361     /**
19362      * <p>Define whether the vertical edges should be faded when this view
19363      * is scrolled vertically.</p>
19364      *
19365      * @param verticalFadingEdgeEnabled true if the vertical edges should
19366      *                                  be faded when the view is scrolled
19367      *                                  vertically
19368      *
19369      * @see #isVerticalFadingEdgeEnabled()
19370      *
19371      * @attr ref android.R.styleable#View_requiresFadingEdge
19372      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)19373     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
19374         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
19375             if (verticalFadingEdgeEnabled) {
19376                 initScrollCache();
19377             }
19378 
19379             mViewFlags ^= FADING_EDGE_VERTICAL;
19380         }
19381     }
19382 
19383     /**
19384      * Get the fading edge flags, used for inspection.
19385      *
19386      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
19387      *         or {@link #FADING_EDGE_HORIZONTAL}
19388      * @hide
19389      */
19390     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
19391             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
19392             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
19393             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
19394     })
getFadingEdge()19395     public int getFadingEdge() {
19396         return mViewFlags & FADING_EDGE_MASK;
19397     }
19398 
19399     /**
19400      * Get the fading edge length, used for inspection
19401      *
19402      * @return The fading edge length or 0
19403      * @hide
19404      */
19405     @InspectableProperty
getFadingEdgeLength()19406     public int getFadingEdgeLength() {
19407         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
19408             return mScrollCache.fadingEdgeLength;
19409         }
19410         return 0;
19411     }
19412 
19413     /**
19414      * Returns the strength, or intensity, of the top faded edge. The strength is
19415      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19416      * returns 0.0 or 1.0 but no value in between.
19417      *
19418      * Subclasses should override this method to provide a smoother fade transition
19419      * when scrolling occurs.
19420      *
19421      * @return the intensity of the top fade as a float between 0.0f and 1.0f
19422      */
getTopFadingEdgeStrength()19423     protected float getTopFadingEdgeStrength() {
19424         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
19425     }
19426 
19427     /**
19428      * Returns the strength, or intensity, of the bottom faded edge. The strength is
19429      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19430      * returns 0.0 or 1.0 but no value in between.
19431      *
19432      * Subclasses should override this method to provide a smoother fade transition
19433      * when scrolling occurs.
19434      *
19435      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
19436      */
getBottomFadingEdgeStrength()19437     protected float getBottomFadingEdgeStrength() {
19438         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
19439                 computeVerticalScrollRange() ? 1.0f : 0.0f;
19440     }
19441 
19442     /**
19443      * Returns the strength, or intensity, of the left faded edge. The strength is
19444      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19445      * returns 0.0 or 1.0 but no value in between.
19446      *
19447      * Subclasses should override this method to provide a smoother fade transition
19448      * when scrolling occurs.
19449      *
19450      * @return the intensity of the left fade as a float between 0.0f and 1.0f
19451      */
getLeftFadingEdgeStrength()19452     protected float getLeftFadingEdgeStrength() {
19453         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
19454     }
19455 
19456     /**
19457      * Returns the strength, or intensity, of the right faded edge. The strength is
19458      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19459      * returns 0.0 or 1.0 but no value in between.
19460      *
19461      * Subclasses should override this method to provide a smoother fade transition
19462      * when scrolling occurs.
19463      *
19464      * @return the intensity of the right fade as a float between 0.0f and 1.0f
19465      */
getRightFadingEdgeStrength()19466     protected float getRightFadingEdgeStrength() {
19467         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
19468                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
19469     }
19470 
19471     /**
19472      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
19473      * scrollbar is not drawn by default.</p>
19474      *
19475      * @return true if the horizontal scrollbar should be painted, false
19476      *         otherwise
19477      *
19478      * @see #setHorizontalScrollBarEnabled(boolean)
19479      */
isHorizontalScrollBarEnabled()19480     public boolean isHorizontalScrollBarEnabled() {
19481         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
19482     }
19483 
19484     /**
19485      * <p>Define whether the horizontal scrollbar should be drawn or not. The
19486      * scrollbar is not drawn by default.</p>
19487      *
19488      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
19489      *                                   be painted
19490      *
19491      * @see #isHorizontalScrollBarEnabled()
19492      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)19493     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
19494         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
19495             mViewFlags ^= SCROLLBARS_HORIZONTAL;
19496             computeOpaqueFlags();
19497             resolvePadding();
19498         }
19499     }
19500 
19501     /**
19502      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
19503      * scrollbar is not drawn by default.</p>
19504      *
19505      * @return true if the vertical scrollbar should be painted, false
19506      *         otherwise
19507      *
19508      * @see #setVerticalScrollBarEnabled(boolean)
19509      */
isVerticalScrollBarEnabled()19510     public boolean isVerticalScrollBarEnabled() {
19511         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
19512     }
19513 
19514     /**
19515      * <p>Define whether the vertical scrollbar should be drawn or not. The
19516      * scrollbar is not drawn by default.</p>
19517      *
19518      * @param verticalScrollBarEnabled true if the vertical scrollbar should
19519      *                                 be painted
19520      *
19521      * @see #isVerticalScrollBarEnabled()
19522      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)19523     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
19524         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
19525             mViewFlags ^= SCROLLBARS_VERTICAL;
19526             computeOpaqueFlags();
19527             resolvePadding();
19528         }
19529     }
19530 
19531     /**
19532      * @hide
19533      */
19534     @UnsupportedAppUsage
recomputePadding()19535     protected void recomputePadding() {
19536         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
19537     }
19538 
19539     /**
19540      * Define whether scrollbars will fade when the view is not scrolling.
19541      *
19542      * @param fadeScrollbars whether to enable fading
19543      *
19544      * @attr ref android.R.styleable#View_fadeScrollbars
19545      */
setScrollbarFadingEnabled(boolean fadeScrollbars)19546     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
19547         initScrollCache();
19548         final ScrollabilityCache scrollabilityCache = mScrollCache;
19549         scrollabilityCache.fadeScrollBars = fadeScrollbars;
19550         if (fadeScrollbars) {
19551             scrollabilityCache.state = ScrollabilityCache.OFF;
19552         } else {
19553             scrollabilityCache.state = ScrollabilityCache.ON;
19554         }
19555     }
19556 
19557     /**
19558      *
19559      * Returns true if scrollbars will fade when this view is not scrolling
19560      *
19561      * @return true if scrollbar fading is enabled
19562      *
19563      * @attr ref android.R.styleable#View_fadeScrollbars
19564      */
isScrollbarFadingEnabled()19565     public boolean isScrollbarFadingEnabled() {
19566         return mScrollCache != null && mScrollCache.fadeScrollBars;
19567     }
19568 
19569     /**
19570      *
19571      * Returns the delay before scrollbars fade.
19572      *
19573      * @return the delay before scrollbars fade
19574      *
19575      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
19576      */
19577     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()19578     public int getScrollBarDefaultDelayBeforeFade() {
19579         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
19580                 mScrollCache.scrollBarDefaultDelayBeforeFade;
19581     }
19582 
19583     /**
19584      * Define the delay before scrollbars fade.
19585      *
19586      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
19587      *
19588      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
19589      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)19590     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
19591         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
19592     }
19593 
19594     /**
19595      *
19596      * Returns the scrollbar fade duration.
19597      *
19598      * @return the scrollbar fade duration, in milliseconds
19599      *
19600      * @attr ref android.R.styleable#View_scrollbarFadeDuration
19601      */
19602     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()19603     public int getScrollBarFadeDuration() {
19604         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
19605                 mScrollCache.scrollBarFadeDuration;
19606     }
19607 
19608     /**
19609      * Define the scrollbar fade duration.
19610      *
19611      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
19612      *
19613      * @attr ref android.R.styleable#View_scrollbarFadeDuration
19614      */
setScrollBarFadeDuration(int scrollBarFadeDuration)19615     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
19616         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
19617     }
19618 
19619     /**
19620      *
19621      * Returns the scrollbar size.
19622      *
19623      * @return the scrollbar size
19624      *
19625      * @attr ref android.R.styleable#View_scrollbarSize
19626      */
19627     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()19628     public int getScrollBarSize() {
19629         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
19630                 mScrollCache.scrollBarSize;
19631     }
19632 
19633     /**
19634      * Define the scrollbar size.
19635      *
19636      * @param scrollBarSize - the scrollbar size
19637      *
19638      * @attr ref android.R.styleable#View_scrollbarSize
19639      */
setScrollBarSize(int scrollBarSize)19640     public void setScrollBarSize(int scrollBarSize) {
19641         getScrollCache().scrollBarSize = scrollBarSize;
19642     }
19643 
19644     /**
19645      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
19646      * inset. When inset, they add to the padding of the view. And the scrollbars
19647      * can be drawn inside the padding area or on the edge of the view. For example,
19648      * if a view has a background drawable and you want to draw the scrollbars
19649      * inside the padding specified by the drawable, you can use
19650      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
19651      * appear at the edge of the view, ignoring the padding, then you can use
19652      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
19653      * @param style the style of the scrollbars. Should be one of
19654      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
19655      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
19656      * @see #SCROLLBARS_INSIDE_OVERLAY
19657      * @see #SCROLLBARS_INSIDE_INSET
19658      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19659      * @see #SCROLLBARS_OUTSIDE_INSET
19660      *
19661      * @attr ref android.R.styleable#View_scrollbarStyle
19662      */
setScrollBarStyle(@crollBarStyle int style)19663     public void setScrollBarStyle(@ScrollBarStyle int style) {
19664         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
19665             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
19666             computeOpaqueFlags();
19667             resolvePadding();
19668         }
19669     }
19670 
19671     /**
19672      * <p>Returns the current scrollbar style.</p>
19673      * @return the current scrollbar style
19674      * @see #SCROLLBARS_INSIDE_OVERLAY
19675      * @see #SCROLLBARS_INSIDE_INSET
19676      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19677      * @see #SCROLLBARS_OUTSIDE_INSET
19678      *
19679      * @attr ref android.R.styleable#View_scrollbarStyle
19680      */
19681     @ViewDebug.ExportedProperty(mapping = {
19682             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
19683             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
19684             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
19685             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
19686     })
19687     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
19688             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
19689             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
19690             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
19691             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
19692     })
19693     @ScrollBarStyle
getScrollBarStyle()19694     public int getScrollBarStyle() {
19695         return mViewFlags & SCROLLBARS_STYLE_MASK;
19696     }
19697 
19698     /**
19699      * <p>Compute the horizontal range that the horizontal scrollbar
19700      * represents.</p>
19701      *
19702      * <p>The range is expressed in arbitrary units that must be the same as the
19703      * units used by {@link #computeHorizontalScrollExtent()} and
19704      * {@link #computeHorizontalScrollOffset()}.</p>
19705      *
19706      * <p>The default range is the drawing width of this view.</p>
19707      *
19708      * @return the total horizontal range represented by the horizontal
19709      *         scrollbar
19710      *
19711      * @see #computeHorizontalScrollExtent()
19712      * @see #computeHorizontalScrollOffset()
19713      */
computeHorizontalScrollRange()19714     protected int computeHorizontalScrollRange() {
19715         return getWidth();
19716     }
19717 
19718     /**
19719      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
19720      * within the horizontal range. This value is used to compute the position
19721      * of the thumb within the scrollbar's track.</p>
19722      *
19723      * <p>The range is expressed in arbitrary units that must be the same as the
19724      * units used by {@link #computeHorizontalScrollRange()} and
19725      * {@link #computeHorizontalScrollExtent()}.</p>
19726      *
19727      * <p>The default offset is the scroll offset of this view.</p>
19728      *
19729      * @return the horizontal offset of the scrollbar's thumb
19730      *
19731      * @see #computeHorizontalScrollRange()
19732      * @see #computeHorizontalScrollExtent()
19733      */
computeHorizontalScrollOffset()19734     protected int computeHorizontalScrollOffset() {
19735         return mScrollX;
19736     }
19737 
19738     /**
19739      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
19740      * within the horizontal range. This value is used to compute the length
19741      * of the thumb within the scrollbar's track.</p>
19742      *
19743      * <p>The range is expressed in arbitrary units that must be the same as the
19744      * units used by {@link #computeHorizontalScrollRange()} and
19745      * {@link #computeHorizontalScrollOffset()}.</p>
19746      *
19747      * <p>The default extent is the drawing width of this view.</p>
19748      *
19749      * @return the horizontal extent of the scrollbar's thumb
19750      *
19751      * @see #computeHorizontalScrollRange()
19752      * @see #computeHorizontalScrollOffset()
19753      */
computeHorizontalScrollExtent()19754     protected int computeHorizontalScrollExtent() {
19755         return getWidth();
19756     }
19757 
19758     /**
19759      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
19760      *
19761      * <p>The range is expressed in arbitrary units that must be the same as the
19762      * units used by {@link #computeVerticalScrollExtent()} and
19763      * {@link #computeVerticalScrollOffset()}.</p>
19764      *
19765      * @return the total vertical range represented by the vertical scrollbar
19766      *
19767      * <p>The default range is the drawing height of this view.</p>
19768      *
19769      * @see #computeVerticalScrollExtent()
19770      * @see #computeVerticalScrollOffset()
19771      */
computeVerticalScrollRange()19772     protected int computeVerticalScrollRange() {
19773         return getHeight();
19774     }
19775 
19776     /**
19777      * <p>Compute the vertical offset of the vertical scrollbar's thumb
19778      * within the horizontal range. This value is used to compute the position
19779      * of the thumb within the scrollbar's track.</p>
19780      *
19781      * <p>The range is expressed in arbitrary units that must be the same as the
19782      * units used by {@link #computeVerticalScrollRange()} and
19783      * {@link #computeVerticalScrollExtent()}.</p>
19784      *
19785      * <p>The default offset is the scroll offset of this view.</p>
19786      *
19787      * @return the vertical offset of the scrollbar's thumb
19788      *
19789      * @see #computeVerticalScrollRange()
19790      * @see #computeVerticalScrollExtent()
19791      */
computeVerticalScrollOffset()19792     protected int computeVerticalScrollOffset() {
19793         return mScrollY;
19794     }
19795 
19796     /**
19797      * <p>Compute the vertical extent of the vertical scrollbar's thumb
19798      * within the vertical range. This value is used to compute the length
19799      * of the thumb within the scrollbar's track.</p>
19800      *
19801      * <p>The range is expressed in arbitrary units that must be the same as the
19802      * units used by {@link #computeVerticalScrollRange()} and
19803      * {@link #computeVerticalScrollOffset()}.</p>
19804      *
19805      * <p>The default extent is the drawing height of this view.</p>
19806      *
19807      * @return the vertical extent of the scrollbar's thumb
19808      *
19809      * @see #computeVerticalScrollRange()
19810      * @see #computeVerticalScrollOffset()
19811      */
computeVerticalScrollExtent()19812     protected int computeVerticalScrollExtent() {
19813         return getHeight();
19814     }
19815 
19816     /**
19817      * Check if this view can be scrolled horizontally in a certain direction.
19818      *
19819      * @param direction Negative to check scrolling left, positive to check scrolling right.
19820      * @return true if this view can be scrolled in the specified direction, false otherwise.
19821      */
canScrollHorizontally(int direction)19822     public boolean canScrollHorizontally(int direction) {
19823         final int offset = computeHorizontalScrollOffset();
19824         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
19825         if (range == 0) return false;
19826         if (direction < 0) {
19827             return offset > 0;
19828         } else {
19829             return offset < range - 1;
19830         }
19831     }
19832 
19833     /**
19834      * Check if this view can be scrolled vertically in a certain direction.
19835      *
19836      * @param direction Negative to check scrolling up, positive to check scrolling down.
19837      * @return true if this view can be scrolled in the specified direction, false otherwise.
19838      */
canScrollVertically(int direction)19839     public boolean canScrollVertically(int direction) {
19840         final int offset = computeVerticalScrollOffset();
19841         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
19842         if (range == 0) return false;
19843         if (direction < 0) {
19844             return offset > 0;
19845         } else {
19846             return offset < range - 1;
19847         }
19848     }
19849 
getScrollIndicatorBounds(@onNull Rect out)19850     void getScrollIndicatorBounds(@NonNull Rect out) {
19851         out.left = mScrollX;
19852         out.right = mScrollX + mRight - mLeft;
19853         out.top = mScrollY;
19854         out.bottom = mScrollY + mBottom - mTop;
19855     }
19856 
onDrawScrollIndicators(Canvas c)19857     private void onDrawScrollIndicators(Canvas c) {
19858         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
19859             // No scroll indicators enabled.
19860             return;
19861         }
19862 
19863         final Drawable dr = mScrollIndicatorDrawable;
19864         if (dr == null) {
19865             // Scroll indicators aren't supported here.
19866             return;
19867         }
19868 
19869         if (mAttachInfo == null) {
19870             // View is not attached.
19871             return;
19872         }
19873 
19874         final int h = dr.getIntrinsicHeight();
19875         final int w = dr.getIntrinsicWidth();
19876         final Rect rect = mAttachInfo.mTmpInvalRect;
19877         getScrollIndicatorBounds(rect);
19878 
19879         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
19880             final boolean canScrollUp = canScrollVertically(-1);
19881             if (canScrollUp) {
19882                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
19883                 dr.draw(c);
19884             }
19885         }
19886 
19887         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
19888             final boolean canScrollDown = canScrollVertically(1);
19889             if (canScrollDown) {
19890                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
19891                 dr.draw(c);
19892             }
19893         }
19894 
19895         final int leftRtl;
19896         final int rightRtl;
19897         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
19898             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
19899             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
19900         } else {
19901             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
19902             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
19903         }
19904 
19905         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
19906         if ((mPrivateFlags3 & leftMask) != 0) {
19907             final boolean canScrollLeft = canScrollHorizontally(-1);
19908             if (canScrollLeft) {
19909                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
19910                 dr.draw(c);
19911             }
19912         }
19913 
19914         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
19915         if ((mPrivateFlags3 & rightMask) != 0) {
19916             final boolean canScrollRight = canScrollHorizontally(1);
19917             if (canScrollRight) {
19918                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
19919                 dr.draw(c);
19920             }
19921         }
19922     }
19923 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19924     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
19925             @Nullable Rect touchBounds) {
19926         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19927         if (bounds == null) {
19928             return;
19929         }
19930         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19931         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
19932                 && !isVerticalScrollBarHidden();
19933         final int size = getHorizontalScrollbarHeight();
19934         final int verticalScrollBarGap = drawVerticalScrollBar ?
19935                 getVerticalScrollbarWidth() : 0;
19936         final int width = mRight - mLeft;
19937         final int height = mBottom - mTop;
19938         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
19939         bounds.left = mScrollX + (mPaddingLeft & inside);
19940         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
19941         bounds.bottom = bounds.top + size;
19942 
19943         if (touchBounds == null) {
19944             return;
19945         }
19946         if (touchBounds != bounds) {
19947             touchBounds.set(bounds);
19948         }
19949         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
19950         if (touchBounds.height() < minTouchTarget) {
19951             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
19952             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
19953             touchBounds.top = touchBounds.bottom - minTouchTarget;
19954         }
19955         if (touchBounds.width() < minTouchTarget) {
19956             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
19957             touchBounds.left -= adjust;
19958             touchBounds.right = touchBounds.left + minTouchTarget;
19959         }
19960     }
19961 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)19962     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
19963         if (mRoundScrollbarRenderer == null) {
19964             getStraightVerticalScrollBarBounds(bounds, touchBounds);
19965         } else {
19966             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
19967         }
19968     }
19969 
getRoundVerticalScrollBarBounds(Rect bounds)19970     private void getRoundVerticalScrollBarBounds(Rect bounds) {
19971         final int width = mRight - mLeft;
19972         final int height = mBottom - mTop;
19973         // Do not take padding into account as we always want the scrollbars
19974         // to hug the screen for round wearable devices.
19975         bounds.left = mScrollX;
19976         bounds.top = mScrollY;
19977         bounds.right = bounds.left + width;
19978         bounds.bottom = mScrollY + height;
19979     }
19980 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19981     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
19982             @Nullable Rect touchBounds) {
19983         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19984         if (bounds == null) {
19985             return;
19986         }
19987         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19988         final int size = getVerticalScrollbarWidth();
19989         int verticalScrollbarPosition = mVerticalScrollbarPosition;
19990         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
19991             verticalScrollbarPosition = isLayoutRtl() ?
19992                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
19993         }
19994         final int width = mRight - mLeft;
19995         final int height = mBottom - mTop;
19996         switch (verticalScrollbarPosition) {
19997             default:
19998             case SCROLLBAR_POSITION_RIGHT:
19999                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
20000                 break;
20001             case SCROLLBAR_POSITION_LEFT:
20002                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
20003                 break;
20004         }
20005         bounds.top = mScrollY + (mPaddingTop & inside);
20006         bounds.right = bounds.left + size;
20007         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
20008 
20009         if (touchBounds == null) {
20010             return;
20011         }
20012         if (touchBounds != bounds) {
20013             touchBounds.set(bounds);
20014         }
20015         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
20016         if (touchBounds.width() < minTouchTarget) {
20017             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
20018             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
20019                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
20020                 touchBounds.left = touchBounds.right - minTouchTarget;
20021             } else {
20022                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
20023                 touchBounds.right = touchBounds.left + minTouchTarget;
20024             }
20025         }
20026         if (touchBounds.height() < minTouchTarget) {
20027             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
20028             touchBounds.top -= adjust;
20029             touchBounds.bottom = touchBounds.top + minTouchTarget;
20030         }
20031     }
20032 
20033     /**
20034      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
20035      * scrollbars are painted only if they have been awakened first.</p>
20036      *
20037      * @param canvas the canvas on which to draw the scrollbars
20038      *
20039      * @see #awakenScrollBars(int)
20040      */
onDrawScrollBars(Canvas canvas)20041     protected final void onDrawScrollBars(Canvas canvas) {
20042         // scrollbars are drawn only when the animation is running
20043         final ScrollabilityCache cache = mScrollCache;
20044 
20045         if (cache != null) {
20046 
20047             int state = cache.state;
20048 
20049             if (state == ScrollabilityCache.OFF) {
20050                 return;
20051             }
20052 
20053             boolean invalidate = false;
20054 
20055             if (state == ScrollabilityCache.FADING) {
20056                 // We're fading -- get our fade interpolation
20057                 if (cache.interpolatorValues == null) {
20058                     cache.interpolatorValues = new float[1];
20059                 }
20060 
20061                 float[] values = cache.interpolatorValues;
20062 
20063                 // Stops the animation if we're done
20064                 if (cache.scrollBarInterpolator.timeToValues(values) ==
20065                         Interpolator.Result.FREEZE_END) {
20066                     cache.state = ScrollabilityCache.OFF;
20067                 } else {
20068                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
20069                 }
20070 
20071                 // This will make the scroll bars inval themselves after
20072                 // drawing. We only want this when we're fading so that
20073                 // we prevent excessive redraws
20074                 invalidate = true;
20075             } else {
20076                 // We're just on -- but we may have been fading before so
20077                 // reset alpha
20078                 cache.scrollBar.mutate().setAlpha(255);
20079             }
20080 
20081             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
20082             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
20083                     && !isVerticalScrollBarHidden();
20084 
20085             // Fork out the scroll bar drawing for round wearable devices.
20086             if (mRoundScrollbarRenderer != null) {
20087                 if (drawVerticalScrollBar) {
20088                     final Rect bounds = cache.mScrollBarBounds;
20089                     getVerticalScrollBarBounds(bounds, null);
20090                     mRoundScrollbarRenderer.drawRoundScrollbars(
20091                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
20092                     if (invalidate) {
20093                         invalidate();
20094                     }
20095                 }
20096                 // Do not draw horizontal scroll bars for round wearable devices.
20097             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
20098                 final ScrollBarDrawable scrollBar = cache.scrollBar;
20099 
20100                 if (drawHorizontalScrollBar) {
20101                     scrollBar.setParameters(computeHorizontalScrollRange(),
20102                             computeHorizontalScrollOffset(),
20103                             computeHorizontalScrollExtent(), false);
20104                     final Rect bounds = cache.mScrollBarBounds;
20105                     getHorizontalScrollBarBounds(bounds, null);
20106                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
20107                             bounds.right, bounds.bottom);
20108                     if (invalidate) {
20109                         invalidate(bounds);
20110                     }
20111                 }
20112 
20113                 if (drawVerticalScrollBar) {
20114                     scrollBar.setParameters(computeVerticalScrollRange(),
20115                             computeVerticalScrollOffset(),
20116                             computeVerticalScrollExtent(), true);
20117                     final Rect bounds = cache.mScrollBarBounds;
20118                     getVerticalScrollBarBounds(bounds, null);
20119                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
20120                             bounds.right, bounds.bottom);
20121                     if (invalidate) {
20122                         invalidate(bounds);
20123                     }
20124                 }
20125             }
20126         }
20127     }
20128 
20129     /**
20130      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
20131      * FastScroller is visible.
20132      * @return whether to temporarily hide the vertical scrollbar
20133      * @hide
20134      */
isVerticalScrollBarHidden()20135     protected boolean isVerticalScrollBarHidden() {
20136         return false;
20137     }
20138 
20139     /**
20140      * <p>Draw the horizontal scrollbar if
20141      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
20142      *
20143      * @param canvas the canvas on which to draw the scrollbar
20144      * @param scrollBar the scrollbar's drawable
20145      *
20146      * @see #isHorizontalScrollBarEnabled()
20147      * @see #computeHorizontalScrollRange()
20148      * @see #computeHorizontalScrollExtent()
20149      * @see #computeHorizontalScrollOffset()
20150      * @hide
20151      */
20152     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)20153     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
20154             int l, int t, int r, int b) {
20155         scrollBar.setBounds(l, t, r, b);
20156         scrollBar.draw(canvas);
20157     }
20158 
20159     /**
20160      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
20161      * returns true.</p>
20162      *
20163      * @param canvas the canvas on which to draw the scrollbar
20164      * @param scrollBar the scrollbar's drawable
20165      *
20166      * @see #isVerticalScrollBarEnabled()
20167      * @see #computeVerticalScrollRange()
20168      * @see #computeVerticalScrollExtent()
20169      * @see #computeVerticalScrollOffset()
20170      * @hide
20171      */
20172     @UnsupportedAppUsage
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)20173     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
20174             int l, int t, int r, int b) {
20175         scrollBar.setBounds(l, t, r, b);
20176         scrollBar.draw(canvas);
20177     }
20178 
20179     /**
20180      * Implement this to do your drawing.
20181      *
20182      * @param canvas the canvas on which the background will be drawn
20183      */
onDraw(Canvas canvas)20184     protected void onDraw(Canvas canvas) {
20185     }
20186 
20187     /*
20188      * Caller is responsible for calling requestLayout if necessary.
20189      * (This allows addViewInLayout to not request a new layout.)
20190      */
20191     @UnsupportedAppUsage
assignParent(ViewParent parent)20192     void assignParent(ViewParent parent) {
20193         if (mParent == null) {
20194             mParent = parent;
20195         } else if (parent == null) {
20196             mParent = null;
20197         } else {
20198             throw new RuntimeException("view " + this + " being added, but"
20199                     + " it already has a parent");
20200         }
20201     }
20202 
20203     /**
20204      * This is called when the view is attached to a window.  At this point it
20205      * has a Surface and will start drawing.  Note that this function is
20206      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
20207      * however it may be called any time before the first onDraw -- including
20208      * before or after {@link #onMeasure(int, int)}.
20209      *
20210      * @see #onDetachedFromWindow()
20211      */
20212     @CallSuper
onAttachedToWindow()20213     protected void onAttachedToWindow() {
20214         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
20215             mParent.requestTransparentRegion(this);
20216         }
20217 
20218         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
20219 
20220         jumpDrawablesToCurrentState();
20221 
20222         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
20223         resetSubtreeAccessibilityStateChanged();
20224 
20225         // rebuild, since Outline not maintained while View is detached
20226         rebuildOutline();
20227 
20228         if (isFocused()) {
20229             notifyFocusChangeToImeFocusController(true /* hasFocus */);
20230         }
20231     }
20232 
20233     /**
20234      * Resolve all RTL related properties.
20235      *
20236      * @return true if resolution of RTL properties has been done
20237      *
20238      * @hide
20239      */
resolveRtlPropertiesIfNeeded()20240     public boolean resolveRtlPropertiesIfNeeded() {
20241         if (!needRtlPropertiesResolution()) return false;
20242 
20243         // Order is important here: LayoutDirection MUST be resolved first
20244         if (!isLayoutDirectionResolved()) {
20245             resolveLayoutDirection();
20246             resolveLayoutParams();
20247         }
20248         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
20249         if (!isTextDirectionResolved()) {
20250             resolveTextDirection();
20251         }
20252         if (!isTextAlignmentResolved()) {
20253             resolveTextAlignment();
20254         }
20255         // Should resolve Drawables before Padding because we need the layout direction of the
20256         // Drawable to correctly resolve Padding.
20257         if (!areDrawablesResolved()) {
20258             resolveDrawables();
20259         }
20260         if (!isPaddingResolved()) {
20261             resolvePadding();
20262         }
20263         onRtlPropertiesChanged(getLayoutDirection());
20264         return true;
20265     }
20266 
20267     /**
20268      * Reset resolution of all RTL related properties.
20269      *
20270      * @hide
20271      */
20272     @TestApi
resetRtlProperties()20273     public void resetRtlProperties() {
20274         resetResolvedLayoutDirection();
20275         resetResolvedTextDirection();
20276         resetResolvedTextAlignment();
20277         resetResolvedPadding();
20278         resetResolvedDrawables();
20279     }
20280 
20281     /**
20282      * @see #onScreenStateChanged(int)
20283      */
dispatchScreenStateChanged(int screenState)20284     void dispatchScreenStateChanged(int screenState) {
20285         onScreenStateChanged(screenState);
20286     }
20287 
20288     /**
20289      * This method is called whenever the state of the screen this view is
20290      * attached to changes. A state change will usually occurs when the screen
20291      * turns on or off (whether it happens automatically or the user does it
20292      * manually.)
20293      *
20294      * @param screenState The new state of the screen. Can be either
20295      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
20296      */
onScreenStateChanged(int screenState)20297     public void onScreenStateChanged(int screenState) {
20298     }
20299 
20300     /**
20301      * @see #onMovedToDisplay(int, Configuration)
20302      */
dispatchMovedToDisplay(Display display, Configuration config)20303     void dispatchMovedToDisplay(Display display, Configuration config) {
20304         mAttachInfo.mDisplay = display;
20305         mAttachInfo.mDisplayState = display.getState();
20306         onMovedToDisplay(display.getDisplayId(), config);
20307     }
20308 
20309     /**
20310      * Called by the system when the hosting activity is moved from one display to another without
20311      * recreation. This means that the activity is declared to handle all changes to configuration
20312      * that happened when it was switched to another display, so it wasn't destroyed and created
20313      * again.
20314      *
20315      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
20316      * applied configuration actually changed. It is up to app developer to choose whether to handle
20317      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
20318      * call.
20319      *
20320      * <p>Use this callback to track changes to the displays if some functionality relies on an
20321      * association with some display properties.
20322      *
20323      * @param displayId The id of the display to which the view was moved.
20324      * @param config Configuration of the resources on new display after move.
20325      *
20326      * @see #onConfigurationChanged(Configuration)
20327      * @hide
20328      */
onMovedToDisplay(int displayId, Configuration config)20329     public void onMovedToDisplay(int displayId, Configuration config) {
20330     }
20331 
20332     /**
20333      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
20334      */
20335     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hasRtlSupport()20336     private boolean hasRtlSupport() {
20337         return mContext.getApplicationInfo().hasRtlSupport();
20338     }
20339 
20340     /**
20341      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
20342      * RTL not supported)
20343      */
isRtlCompatibilityMode()20344     private boolean isRtlCompatibilityMode() {
20345         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
20346         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
20347     }
20348 
20349     /**
20350      * @return true if RTL properties need resolution.
20351      *
20352      */
needRtlPropertiesResolution()20353     private boolean needRtlPropertiesResolution() {
20354         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
20355     }
20356 
20357     /**
20358      * Called when any RTL property (layout direction or text direction or text alignment) has
20359      * been changed.
20360      *
20361      * Subclasses need to override this method to take care of cached information that depends on the
20362      * resolved layout direction, or to inform child views that inherit their layout direction.
20363      *
20364      * The default implementation does nothing.
20365      *
20366      * @param layoutDirection the direction of the layout
20367      *
20368      * @see #LAYOUT_DIRECTION_LTR
20369      * @see #LAYOUT_DIRECTION_RTL
20370      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)20371     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
20372     }
20373 
20374     /**
20375      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
20376      * that the parent directionality can and will be resolved before its children.
20377      *
20378      * @return true if resolution has been done, false otherwise.
20379      *
20380      * @hide
20381      */
resolveLayoutDirection()20382     public boolean resolveLayoutDirection() {
20383         // Clear any previous layout direction resolution
20384         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20385 
20386         if (hasRtlSupport()) {
20387             // Set resolved depending on layout direction
20388             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
20389                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
20390                 case LAYOUT_DIRECTION_INHERIT:
20391                     // We cannot resolve yet. LTR is by default and let the resolution happen again
20392                     // later to get the correct resolved value
20393                     if (!canResolveLayoutDirection()) return false;
20394 
20395                     // Parent has not yet resolved, LTR is still the default
20396                     try {
20397                         if (!mParent.isLayoutDirectionResolved()) return false;
20398 
20399                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
20400                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20401                         }
20402                     } catch (AbstractMethodError e) {
20403                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20404                                 " does not fully implement ViewParent", e);
20405                     }
20406                     break;
20407                 case LAYOUT_DIRECTION_RTL:
20408                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20409                     break;
20410                 case LAYOUT_DIRECTION_LOCALE:
20411                     if((LAYOUT_DIRECTION_RTL ==
20412                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
20413                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20414                     }
20415                     break;
20416                 default:
20417                     // Nothing to do, LTR by default
20418             }
20419         }
20420 
20421         // Set to resolved
20422         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
20423         return true;
20424     }
20425 
20426     /**
20427      * Check if layout direction resolution can be done.
20428      *
20429      * @return true if layout direction resolution can be done otherwise return false.
20430      */
canResolveLayoutDirection()20431     public boolean canResolveLayoutDirection() {
20432         switch (getRawLayoutDirection()) {
20433             case LAYOUT_DIRECTION_INHERIT:
20434                 if (mParent != null) {
20435                     try {
20436                         return mParent.canResolveLayoutDirection();
20437                     } catch (AbstractMethodError e) {
20438                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20439                                 " does not fully implement ViewParent", e);
20440                     }
20441                 }
20442                 return false;
20443 
20444             default:
20445                 return true;
20446         }
20447     }
20448 
20449     /**
20450      * Reset the resolved layout direction. Layout direction will be resolved during a call to
20451      * {@link #onMeasure(int, int)}.
20452      *
20453      * @hide
20454      */
20455     @TestApi
resetResolvedLayoutDirection()20456     public void resetResolvedLayoutDirection() {
20457         // Reset the current resolved bits
20458         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20459     }
20460 
20461     /**
20462      * @return true if the layout direction is inherited.
20463      *
20464      * @hide
20465      */
isLayoutDirectionInherited()20466     public boolean isLayoutDirectionInherited() {
20467         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
20468     }
20469 
20470     /**
20471      * @return true if layout direction has been resolved.
20472      */
isLayoutDirectionResolved()20473     public boolean isLayoutDirectionResolved() {
20474         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
20475     }
20476 
20477     /**
20478      * Return if padding has been resolved
20479      *
20480      * @hide
20481      */
20482     @UnsupportedAppUsage
isPaddingResolved()20483     boolean isPaddingResolved() {
20484         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
20485     }
20486 
20487     /**
20488      * Resolves padding depending on layout direction, if applicable, and
20489      * recomputes internal padding values to adjust for scroll bars.
20490      *
20491      * @hide
20492      */
20493     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resolvePadding()20494     public void resolvePadding() {
20495         final int resolvedLayoutDirection = getLayoutDirection();
20496 
20497         if (!isRtlCompatibilityMode()) {
20498             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
20499             // If start / end padding are defined, they will be resolved (hence overriding) to
20500             // left / right or right / left depending on the resolved layout direction.
20501             // If start / end padding are not defined, use the left / right ones.
20502             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
20503                 Rect padding = sThreadLocal.get();
20504                 if (padding == null) {
20505                     padding = new Rect();
20506                     sThreadLocal.set(padding);
20507                 }
20508                 mBackground.getPadding(padding);
20509                 if (!mLeftPaddingDefined) {
20510                     mUserPaddingLeftInitial = padding.left;
20511                 }
20512                 if (!mRightPaddingDefined) {
20513                     mUserPaddingRightInitial = padding.right;
20514                 }
20515             }
20516             switch (resolvedLayoutDirection) {
20517                 case LAYOUT_DIRECTION_RTL:
20518                     if (mUserPaddingStart != UNDEFINED_PADDING) {
20519                         mUserPaddingRight = mUserPaddingStart;
20520                     } else {
20521                         mUserPaddingRight = mUserPaddingRightInitial;
20522                     }
20523                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
20524                         mUserPaddingLeft = mUserPaddingEnd;
20525                     } else {
20526                         mUserPaddingLeft = mUserPaddingLeftInitial;
20527                     }
20528                     break;
20529                 case LAYOUT_DIRECTION_LTR:
20530                 default:
20531                     if (mUserPaddingStart != UNDEFINED_PADDING) {
20532                         mUserPaddingLeft = mUserPaddingStart;
20533                     } else {
20534                         mUserPaddingLeft = mUserPaddingLeftInitial;
20535                     }
20536                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
20537                         mUserPaddingRight = mUserPaddingEnd;
20538                     } else {
20539                         mUserPaddingRight = mUserPaddingRightInitial;
20540                     }
20541             }
20542 
20543             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
20544         }
20545 
20546         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
20547         onRtlPropertiesChanged(resolvedLayoutDirection);
20548 
20549         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
20550     }
20551 
20552     /**
20553      * Reset the resolved layout direction.
20554      *
20555      * @hide
20556      */
20557     @TestApi
resetResolvedPadding()20558     public void resetResolvedPadding() {
20559         resetResolvedPaddingInternal();
20560     }
20561 
20562     /**
20563      * Used when we only want to reset *this* view's padding and not trigger overrides
20564      * in ViewGroup that reset children too.
20565      */
resetResolvedPaddingInternal()20566     void resetResolvedPaddingInternal() {
20567         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
20568     }
20569 
20570     /**
20571      * This is called when the view is detached from a window.  At this point it
20572      * no longer has a surface for drawing.
20573      *
20574      * @see #onAttachedToWindow()
20575      */
20576     @CallSuper
onDetachedFromWindow()20577     protected void onDetachedFromWindow() {
20578     }
20579 
20580     /**
20581      * This is a framework-internal mirror of onDetachedFromWindow() that's called
20582      * after onDetachedFromWindow().
20583      *
20584      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
20585      * The super method should be called at the end of the overridden method to ensure
20586      * subclasses are destroyed first
20587      *
20588      * @hide
20589      */
20590     @CallSuper
20591     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDetachedFromWindowInternal()20592     protected void onDetachedFromWindowInternal() {
20593         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
20594         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
20595         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
20596 
20597         removeUnsetPressCallback();
20598         removeLongPressCallback();
20599         removePerformClickCallback();
20600         clearAccessibilityThrottles();
20601         stopNestedScroll();
20602 
20603         // Anything that started animating right before detach should already
20604         // be in its final state when re-attached.
20605         jumpDrawablesToCurrentState();
20606 
20607         destroyDrawingCache();
20608 
20609         cleanupDraw();
20610         mCurrentAnimation = null;
20611 
20612         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
20613             hideTooltip();
20614         }
20615 
20616         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
20617     }
20618 
cleanupDraw()20619     private void cleanupDraw() {
20620         resetDisplayList();
20621         if (mAttachInfo != null) {
20622             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
20623         }
20624     }
20625 
invalidateInheritedLayoutMode(int layoutModeOfRoot)20626     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
20627     }
20628 
20629     /**
20630      * @return The number of times this view has been attached to a window
20631      */
getWindowAttachCount()20632     protected int getWindowAttachCount() {
20633         return mWindowAttachCount;
20634     }
20635 
20636     /**
20637      * Retrieve a unique token identifying the window this view is attached to.
20638      * @return Return the window's token for use in
20639      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
20640      */
getWindowToken()20641     public IBinder getWindowToken() {
20642         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
20643     }
20644 
20645     /**
20646      * Retrieve the {@link WindowId} for the window this view is
20647      * currently attached to.
20648      */
getWindowId()20649     public WindowId getWindowId() {
20650         AttachInfo ai = mAttachInfo;
20651         if (ai == null) {
20652             return null;
20653         }
20654         if (ai.mWindowId == null) {
20655             try {
20656                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
20657                 if (ai.mIWindowId != null) {
20658                     ai.mWindowId = new WindowId(ai.mIWindowId);
20659                 }
20660             } catch (RemoteException e) {
20661             }
20662         }
20663         return ai.mWindowId;
20664     }
20665 
20666     /**
20667      * Retrieve a unique token identifying the top-level "real" window of
20668      * the window that this view is attached to.  That is, this is like
20669      * {@link #getWindowToken}, except if the window this view in is a panel
20670      * window (attached to another containing window), then the token of
20671      * the containing window is returned instead.
20672      *
20673      * @return Returns the associated window token, either
20674      * {@link #getWindowToken()} or the containing window's token.
20675      */
getApplicationWindowToken()20676     public IBinder getApplicationWindowToken() {
20677         AttachInfo ai = mAttachInfo;
20678         if (ai != null) {
20679             IBinder appWindowToken = ai.mPanelParentWindowToken;
20680             if (appWindowToken == null) {
20681                 appWindowToken = ai.mWindowToken;
20682             }
20683             return appWindowToken;
20684         }
20685         return null;
20686     }
20687 
20688     /**
20689      * Gets the logical display to which the view's window has been attached.
20690      *
20691      * @return The logical display, or null if the view is not currently attached to a window.
20692      */
getDisplay()20693     public Display getDisplay() {
20694         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
20695     }
20696 
20697     /**
20698      * Retrieve private session object this view hierarchy is using to
20699      * communicate with the window manager.
20700      * @return the session object to communicate with the window manager
20701      */
20702     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()20703     /*package*/ IWindowSession getWindowSession() {
20704         return mAttachInfo != null ? mAttachInfo.mSession : null;
20705     }
20706 
20707     /**
20708      * Return the window this view is currently attached to.
20709      * @hide
20710      */
getWindow()20711     protected IWindow getWindow() {
20712         return mAttachInfo != null ? mAttachInfo.mWindow : null;
20713     }
20714 
20715     /**
20716      * Return the visibility value of the least visible component passed.
20717      */
combineVisibility(int vis1, int vis2)20718     int combineVisibility(int vis1, int vis2) {
20719         // This works because VISIBLE < INVISIBLE < GONE.
20720         return Math.max(vis1, vis2);
20721     }
20722 
20723     /**
20724      * @param info the {@link android.view.View.AttachInfo} to associated with
20725      *        this view
20726      */
20727     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)20728     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
20729         mAttachInfo = info;
20730         if (mOverlay != null) {
20731             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
20732         }
20733         mWindowAttachCount++;
20734         // We will need to evaluate the drawable state at least once.
20735         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20736         if (mFloatingTreeObserver != null) {
20737             info.mTreeObserver.merge(mFloatingTreeObserver);
20738             mFloatingTreeObserver = null;
20739         }
20740 
20741         registerPendingFrameMetricsObservers();
20742 
20743         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
20744             mAttachInfo.mScrollContainers.add(this);
20745             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
20746         }
20747         // Transfer all pending runnables.
20748         if (mRunQueue != null) {
20749             mRunQueue.executeActions(info.mHandler);
20750             mRunQueue = null;
20751         }
20752         performCollectViewAttributes(mAttachInfo, visibility);
20753         onAttachedToWindow();
20754 
20755         ListenerInfo li = mListenerInfo;
20756         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20757                 li != null ? li.mOnAttachStateChangeListeners : null;
20758         if (listeners != null && listeners.size() > 0) {
20759             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20760             // perform the dispatching. The iterator is a safe guard against listeners that
20761             // could mutate the list by calling the various add/remove methods. This prevents
20762             // the array from being modified while we iterate it.
20763             for (OnAttachStateChangeListener listener : listeners) {
20764                 listener.onViewAttachedToWindow(this);
20765             }
20766         }
20767 
20768         int vis = info.mWindowVisibility;
20769         if (vis != GONE) {
20770             onWindowVisibilityChanged(vis);
20771             if (isShown()) {
20772                 // Calling onVisibilityAggregated directly here since the subtree will also
20773                 // receive dispatchAttachedToWindow and this same call
20774                 onVisibilityAggregated(vis == VISIBLE);
20775             }
20776         }
20777 
20778         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
20779         // As all views in the subtree will already receive dispatchAttachedToWindow
20780         // traversing the subtree again here is not desired.
20781         onVisibilityChanged(this, visibility);
20782 
20783         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
20784             // If nobody has evaluated the drawable state yet, then do it now.
20785             refreshDrawableState();
20786         }
20787         needGlobalAttributesUpdate(false);
20788 
20789         notifyEnterOrExitForAutoFillIfNeeded(true);
20790         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
20791     }
20792 
20793     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()20794     void dispatchDetachedFromWindow() {
20795         AttachInfo info = mAttachInfo;
20796         if (info != null) {
20797             int vis = info.mWindowVisibility;
20798             if (vis != GONE) {
20799                 onWindowVisibilityChanged(GONE);
20800                 if (isShown()) {
20801                     // Invoking onVisibilityAggregated directly here since the subtree
20802                     // will also receive detached from window
20803                     onVisibilityAggregated(false);
20804                 }
20805             }
20806         }
20807 
20808         onDetachedFromWindow();
20809         onDetachedFromWindowInternal();
20810 
20811         if (info != null) {
20812             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
20813         }
20814 
20815         ListenerInfo li = mListenerInfo;
20816         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20817                 li != null ? li.mOnAttachStateChangeListeners : null;
20818         if (listeners != null && listeners.size() > 0) {
20819             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20820             // perform the dispatching. The iterator is a safe guard against listeners that
20821             // could mutate the list by calling the various add/remove methods. This prevents
20822             // the array from being modified while we iterate it.
20823             for (OnAttachStateChangeListener listener : listeners) {
20824                 listener.onViewDetachedFromWindow(this);
20825             }
20826         }
20827 
20828         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
20829             mAttachInfo.mScrollContainers.remove(this);
20830             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
20831         }
20832 
20833         mAttachInfo = null;
20834         if (mOverlay != null) {
20835             mOverlay.getOverlayView().dispatchDetachedFromWindow();
20836         }
20837 
20838         notifyEnterOrExitForAutoFillIfNeeded(false);
20839         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
20840     }
20841 
20842     /**
20843      * Cancel any deferred high-level input events that were previously posted to the event queue.
20844      *
20845      * <p>Many views post high-level events such as click handlers to the event queue
20846      * to run deferred in order to preserve a desired user experience - clearing visible
20847      * pressed states before executing, etc. This method will abort any events of this nature
20848      * that are currently in flight.</p>
20849      *
20850      * <p>Custom views that generate their own high-level deferred input events should override
20851      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
20852      *
20853      * <p>This will also cancel pending input events for any child views.</p>
20854      *
20855      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
20856      * This will not impact newer events posted after this call that may occur as a result of
20857      * lower-level input events still waiting in the queue. If you are trying to prevent
20858      * double-submitted  events for the duration of some sort of asynchronous transaction
20859      * you should also take other steps to protect against unexpected double inputs e.g. calling
20860      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
20861      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
20862      */
cancelPendingInputEvents()20863     public final void cancelPendingInputEvents() {
20864         dispatchCancelPendingInputEvents();
20865     }
20866 
20867     /**
20868      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
20869      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
20870      */
dispatchCancelPendingInputEvents()20871     void dispatchCancelPendingInputEvents() {
20872         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
20873         onCancelPendingInputEvents();
20874         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
20875             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
20876                     " did not call through to super.onCancelPendingInputEvents()");
20877         }
20878     }
20879 
20880     /**
20881      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
20882      * a parent view.
20883      *
20884      * <p>This method is responsible for removing any pending high-level input events that were
20885      * posted to the event queue to run later. Custom view classes that post their own deferred
20886      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
20887      * {@link android.os.Handler} should override this method, call
20888      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
20889      * </p>
20890      */
onCancelPendingInputEvents()20891     public void onCancelPendingInputEvents() {
20892         removePerformClickCallback();
20893         cancelLongPress();
20894         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
20895     }
20896 
20897     /**
20898      * Store this view hierarchy's frozen state into the given container.
20899      *
20900      * @param container The SparseArray in which to save the view's state.
20901      *
20902      * @see #restoreHierarchyState(android.util.SparseArray)
20903      * @see #dispatchSaveInstanceState(android.util.SparseArray)
20904      * @see #onSaveInstanceState()
20905      */
saveHierarchyState(SparseArray<Parcelable> container)20906     public void saveHierarchyState(SparseArray<Parcelable> container) {
20907         dispatchSaveInstanceState(container);
20908     }
20909 
20910     /**
20911      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
20912      * this view and its children. May be overridden to modify how freezing happens to a
20913      * view's children; for example, some views may want to not store state for their children.
20914      *
20915      * @param container The SparseArray in which to save the view's state.
20916      *
20917      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20918      * @see #saveHierarchyState(android.util.SparseArray)
20919      * @see #onSaveInstanceState()
20920      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)20921     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
20922         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
20923             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
20924             Parcelable state = onSaveInstanceState();
20925             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
20926                 throw new IllegalStateException(
20927                         "Derived class did not call super.onSaveInstanceState()");
20928             }
20929             if (state != null) {
20930                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
20931                 // + ": " + state);
20932                 container.put(mID, state);
20933             }
20934         }
20935     }
20936 
20937     /**
20938      * Hook allowing a view to generate a representation of its internal state
20939      * that can later be used to create a new instance with that same state.
20940      * This state should only contain information that is not persistent or can
20941      * not be reconstructed later. For example, you will never store your
20942      * current position on screen because that will be computed again when a
20943      * new instance of the view is placed in its view hierarchy.
20944      * <p>
20945      * Some examples of things you may store here: the current cursor position
20946      * in a text view (but usually not the text itself since that is stored in a
20947      * content provider or other persistent storage), the currently selected
20948      * item in a list view.
20949      *
20950      * @return Returns a Parcelable object containing the view's current dynamic
20951      *         state, or null if there is nothing interesting to save.
20952      * @see #onRestoreInstanceState(Parcelable)
20953      * @see #saveHierarchyState(SparseArray)
20954      * @see #dispatchSaveInstanceState(SparseArray)
20955      * @see #setSaveEnabled(boolean)
20956      */
20957     @CallSuper
onSaveInstanceState()20958     @Nullable protected Parcelable onSaveInstanceState() {
20959         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
20960         if (mStartActivityRequestWho != null || isAutofilled()
20961                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
20962             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
20963 
20964             if (mStartActivityRequestWho != null) {
20965                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
20966             }
20967 
20968             if (isAutofilled()) {
20969                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
20970             }
20971 
20972             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
20973                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
20974             }
20975 
20976             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
20977             state.mIsAutofilled = isAutofilled();
20978             state.mHideHighlight = hideAutofillHighlight();
20979             state.mAutofillViewId = mAutofillViewId;
20980             return state;
20981         }
20982         return BaseSavedState.EMPTY_STATE;
20983     }
20984 
20985     /**
20986      * Restore this view hierarchy's frozen state from the given container.
20987      *
20988      * @param container The SparseArray which holds previously frozen states.
20989      *
20990      * @see #saveHierarchyState(android.util.SparseArray)
20991      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20992      * @see #onRestoreInstanceState(android.os.Parcelable)
20993      */
restoreHierarchyState(SparseArray<Parcelable> container)20994     public void restoreHierarchyState(SparseArray<Parcelable> container) {
20995         dispatchRestoreInstanceState(container);
20996     }
20997 
20998     /**
20999      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
21000      * state for this view and its children. May be overridden to modify how restoring
21001      * happens to a view's children; for example, some views may want to not store state
21002      * for their children.
21003      *
21004      * @param container The SparseArray which holds previously saved state.
21005      *
21006      * @see #dispatchSaveInstanceState(android.util.SparseArray)
21007      * @see #restoreHierarchyState(android.util.SparseArray)
21008      * @see #onRestoreInstanceState(android.os.Parcelable)
21009      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)21010     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
21011         if (mID != NO_ID) {
21012             Parcelable state = container.get(mID);
21013             if (state != null) {
21014                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
21015                 // + ": " + state);
21016                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
21017                 onRestoreInstanceState(state);
21018                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
21019                     throw new IllegalStateException(
21020                             "Derived class did not call super.onRestoreInstanceState()");
21021                 }
21022             }
21023         }
21024     }
21025 
21026     /**
21027      * Hook allowing a view to re-apply a representation of its internal state that had previously
21028      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
21029      * null state.
21030      *
21031      * @param state The frozen state that had previously been returned by
21032      *        {@link #onSaveInstanceState}.
21033      *
21034      * @see #onSaveInstanceState()
21035      * @see #restoreHierarchyState(android.util.SparseArray)
21036      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
21037      */
21038     @CallSuper
onRestoreInstanceState(Parcelable state)21039     protected void onRestoreInstanceState(Parcelable state) {
21040         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
21041         if (state != null && !(state instanceof AbsSavedState)) {
21042             throw new IllegalArgumentException("Wrong state class, expecting View State but "
21043                     + "received " + state.getClass().toString() + " instead. This usually happens "
21044                     + "when two views of different type have the same id in the same hierarchy. "
21045                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
21046                     + "other views do not use the same id.");
21047         }
21048         if (state != null && state instanceof BaseSavedState) {
21049             BaseSavedState baseState = (BaseSavedState) state;
21050 
21051             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
21052                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
21053             }
21054             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
21055                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
21056             }
21057             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
21058                 // It can happen that views have the same view id and the restoration path will not
21059                 // be able to distinguish between them. The autofill id needs to be unique though.
21060                 // Hence prevent the same autofill view id from being restored multiple times.
21061                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
21062 
21063                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
21064                     // Ignore when view already set it through setAutofillId();
21065                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
21066                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
21067                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
21068                                 + " it to " + mAutofillId);
21069                     }
21070                 } else {
21071                     mAutofillViewId = baseState.mAutofillViewId;
21072                     mAutofillId = null; // will be set on demand by getAutofillId()
21073                 }
21074             }
21075         }
21076     }
21077 
21078     /**
21079      * <p>Return the time at which the drawing of the view hierarchy started.</p>
21080      *
21081      * @return the drawing start time in milliseconds
21082      */
getDrawingTime()21083     public long getDrawingTime() {
21084         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
21085     }
21086 
21087     /**
21088      * <p>Enables or disables the duplication of the parent's state into this view. When
21089      * duplication is enabled, this view gets its drawable state from its parent rather
21090      * than from its own internal properties.</p>
21091      *
21092      * <p>Note: in the current implementation, setting this property to true after the
21093      * view was added to a ViewGroup might have no effect at all. This property should
21094      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
21095      *
21096      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
21097      * property is enabled, an exception will be thrown.</p>
21098      *
21099      * <p>Note: if the child view uses and updates additional states which are unknown to the
21100      * parent, these states should not be affected by this method.</p>
21101      *
21102      * @param enabled True to enable duplication of the parent's drawable state, false
21103      *                to disable it.
21104      *
21105      * @see #getDrawableState()
21106      * @see #isDuplicateParentStateEnabled()
21107      */
setDuplicateParentStateEnabled(boolean enabled)21108     public void setDuplicateParentStateEnabled(boolean enabled) {
21109         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
21110     }
21111 
21112     /**
21113      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
21114      *
21115      * @return True if this view's drawable state is duplicated from the parent,
21116      *         false otherwise
21117      *
21118      * @see #getDrawableState()
21119      * @see #setDuplicateParentStateEnabled(boolean)
21120      */
21121     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()21122     public boolean isDuplicateParentStateEnabled() {
21123         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
21124     }
21125 
21126     /**
21127      * <p>Specifies the type of layer backing this view. The layer can be
21128      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21129      * {@link #LAYER_TYPE_HARDWARE}.</p>
21130      *
21131      * <p>A layer is associated with an optional {@link android.graphics.Paint}
21132      * instance that controls how the layer is composed on screen. The following
21133      * properties of the paint are taken into account when composing the layer:</p>
21134      * <ul>
21135      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
21136      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
21137      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
21138      * </ul>
21139      *
21140      * <p>If this view has an alpha value set to < 1.0 by calling
21141      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
21142      * by this view's alpha value.</p>
21143      *
21144      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
21145      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
21146      * for more information on when and how to use layers.</p>
21147      *
21148      * @param layerType The type of layer to use with this view, must be one of
21149      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21150      *        {@link #LAYER_TYPE_HARDWARE}
21151      * @param paint The paint used to compose the layer. This argument is optional
21152      *        and can be null. It is ignored when the layer type is
21153      *        {@link #LAYER_TYPE_NONE}
21154      *
21155      * @see #getLayerType()
21156      * @see #LAYER_TYPE_NONE
21157      * @see #LAYER_TYPE_SOFTWARE
21158      * @see #LAYER_TYPE_HARDWARE
21159      * @see #setAlpha(float)
21160      *
21161      * @attr ref android.R.styleable#View_layerType
21162      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)21163     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
21164         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
21165             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
21166                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
21167         }
21168 
21169         boolean typeChanged = mRenderNode.setLayerType(layerType);
21170 
21171         if (!typeChanged) {
21172             setLayerPaint(paint);
21173             return;
21174         }
21175 
21176         if (layerType != LAYER_TYPE_SOFTWARE) {
21177             // Destroy any previous software drawing cache if present
21178             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
21179             // drawing cache created in View#draw when drawing to a SW canvas.
21180             destroyDrawingCache();
21181         }
21182 
21183         mLayerType = layerType;
21184         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
21185         mRenderNode.setLayerPaint(mLayerPaint);
21186 
21187         // draw() behaves differently if we are on a layer, so we need to
21188         // invalidate() here
21189         invalidateParentCaches();
21190         invalidate(true);
21191     }
21192 
21193     /**
21194      * Configure the {@link android.graphics.RenderEffect} to apply to this View.
21195      * This will apply a visual effect to the results of the View before it is drawn. For example if
21196      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
21197      * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
21198      * when this View is drawn.
21199      * @param renderEffect to be applied to the View. Passing null clears the previously configured
21200      *                     {@link RenderEffect}
21201      */
setRenderEffect(@ullable RenderEffect renderEffect)21202     public void setRenderEffect(@Nullable RenderEffect renderEffect) {
21203         if (mRenderNode.setRenderEffect(renderEffect)) {
21204             invalidateViewProperty(true, true);
21205         }
21206     }
21207 
21208     /**
21209      * Updates the {@link Paint} object used with the current layer (used only if the current
21210      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
21211      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
21212      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
21213      * ensure that the view gets redrawn immediately.
21214      *
21215      * <p>A layer is associated with an optional {@link android.graphics.Paint}
21216      * instance that controls how the layer is composed on screen. The following
21217      * properties of the paint are taken into account when composing the layer:</p>
21218      * <ul>
21219      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
21220      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
21221      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
21222      * </ul>
21223      *
21224      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
21225      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
21226      *
21227      * @param paint The paint used to compose the layer. This argument is optional
21228      *        and can be null. It is ignored when the layer type is
21229      *        {@link #LAYER_TYPE_NONE}
21230      *
21231      * @see #setLayerType(int, android.graphics.Paint)
21232      */
setLayerPaint(@ullable Paint paint)21233     public void setLayerPaint(@Nullable Paint paint) {
21234         int layerType = getLayerType();
21235         if (layerType != LAYER_TYPE_NONE) {
21236             mLayerPaint = paint;
21237             if (layerType == LAYER_TYPE_HARDWARE) {
21238                 if (mRenderNode.setLayerPaint(paint)) {
21239                     invalidateViewProperty(false, false);
21240                 }
21241             } else {
21242                 invalidate();
21243             }
21244         }
21245     }
21246 
21247     /**
21248      * Indicates what type of layer is currently associated with this view. By default
21249      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
21250      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
21251      * for more information on the different types of layers.
21252      *
21253      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
21254      *         {@link #LAYER_TYPE_HARDWARE}
21255      *
21256      * @see #setLayerType(int, android.graphics.Paint)
21257      * @see #buildLayer()
21258      * @see #LAYER_TYPE_NONE
21259      * @see #LAYER_TYPE_SOFTWARE
21260      * @see #LAYER_TYPE_HARDWARE
21261      */
21262     @InspectableProperty(enumMapping = {
21263             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
21264             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
21265             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
21266     })
21267     @LayerType
getLayerType()21268     public int getLayerType() {
21269         return mLayerType;
21270     }
21271 
21272     /**
21273      * Forces this view's layer to be created and this view to be rendered
21274      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
21275      * invoking this method will have no effect.
21276      *
21277      * This method can for instance be used to render a view into its layer before
21278      * starting an animation. If this view is complex, rendering into the layer
21279      * before starting the animation will avoid skipping frames.
21280      *
21281      * @throws IllegalStateException If this view is not attached to a window
21282      *
21283      * @see #setLayerType(int, android.graphics.Paint)
21284      */
buildLayer()21285     public void buildLayer() {
21286         if (mLayerType == LAYER_TYPE_NONE) return;
21287 
21288         final AttachInfo attachInfo = mAttachInfo;
21289         if (attachInfo == null) {
21290             throw new IllegalStateException("This view must be attached to a window first");
21291         }
21292 
21293         if (getWidth() == 0 || getHeight() == 0) {
21294             return;
21295         }
21296 
21297         switch (mLayerType) {
21298             case LAYER_TYPE_HARDWARE:
21299                 updateDisplayListIfDirty();
21300                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
21301                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
21302                 }
21303                 break;
21304             case LAYER_TYPE_SOFTWARE:
21305                 buildDrawingCache(true);
21306                 break;
21307         }
21308     }
21309 
21310     /**
21311      * Destroys all hardware rendering resources. This method is invoked
21312      * when the system needs to reclaim resources. Upon execution of this
21313      * method, you should free any OpenGL resources created by the view.
21314      *
21315      * Note: you <strong>must</strong> call
21316      * <code>super.destroyHardwareResources()</code> when overriding
21317      * this method.
21318      *
21319      * @hide
21320      */
21321     @CallSuper
21322     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
destroyHardwareResources()21323     protected void destroyHardwareResources() {
21324         if (mOverlay != null) {
21325             mOverlay.getOverlayView().destroyHardwareResources();
21326         }
21327         if (mGhostView != null) {
21328             mGhostView.destroyHardwareResources();
21329         }
21330     }
21331 
21332     /**
21333      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
21334      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
21335      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
21336      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
21337      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
21338      * null.</p>
21339      *
21340      * <p>Enabling the drawing cache is similar to
21341      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
21342      * acceleration is turned off. When hardware acceleration is turned on, enabling the
21343      * drawing cache has no effect on rendering because the system uses a different mechanism
21344      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
21345      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
21346      * for information on how to enable software and hardware layers.</p>
21347      *
21348      * <p>This API can be used to manually generate
21349      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
21350      * {@link #getDrawingCache()}.</p>
21351      *
21352      * @param enabled true to enable the drawing cache, false otherwise
21353      *
21354      * @see #isDrawingCacheEnabled()
21355      * @see #getDrawingCache()
21356      * @see #buildDrawingCache()
21357      * @see #setLayerType(int, android.graphics.Paint)
21358      *
21359      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21360      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21361      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21362      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21363      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21364      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21365      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21366      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21367      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21368      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21369      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21370      * reports or unit testing the {@link PixelCopy} API is recommended.
21371      */
21372     @Deprecated
setDrawingCacheEnabled(boolean enabled)21373     public void setDrawingCacheEnabled(boolean enabled) {
21374         mCachingFailed = false;
21375         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
21376     }
21377 
21378     /**
21379      * <p>Indicates whether the drawing cache is enabled for this view.</p>
21380      *
21381      * @return true if the drawing cache is enabled
21382      *
21383      * @see #setDrawingCacheEnabled(boolean)
21384      * @see #getDrawingCache()
21385      *
21386      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21387      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21388      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21389      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21390      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21391      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21392      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21393      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21394      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21395      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21396      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21397      * reports or unit testing the {@link PixelCopy} API is recommended.
21398      */
21399     @Deprecated
21400     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()21401     public boolean isDrawingCacheEnabled() {
21402         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
21403     }
21404 
21405     /**
21406      * Debugging utility which recursively outputs the dirty state of a view and its
21407      * descendants.
21408      *
21409      * @hide
21410      */
21411     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)21412     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
21413         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
21414                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
21415                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
21416                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
21417                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
21418         if (clear) {
21419             mPrivateFlags &= clearMask;
21420         }
21421         if (this instanceof ViewGroup) {
21422             ViewGroup parent = (ViewGroup) this;
21423             final int count = parent.getChildCount();
21424             for (int i = 0; i < count; i++) {
21425                 final View child = parent.getChildAt(i);
21426                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
21427             }
21428         }
21429     }
21430 
21431     /**
21432      * This method is used by ViewGroup to cause its children to restore or recreate their
21433      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
21434      * to recreate its own display list, which would happen if it went through the normal
21435      * draw/dispatchDraw mechanisms.
21436      *
21437      * @hide
21438      */
dispatchGetDisplayList()21439     protected void dispatchGetDisplayList() {}
21440 
21441     /**
21442      * A view that is not attached or hardware accelerated cannot create a display list.
21443      * This method checks these conditions and returns the appropriate result.
21444      *
21445      * @return true if view has the ability to create a display list, false otherwise.
21446      *
21447      * @hide
21448      */
canHaveDisplayList()21449     public boolean canHaveDisplayList() {
21450         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
21451     }
21452 
21453     /**
21454      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
21455      * @hide
21456      */
21457     @NonNull
21458     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateDisplayListIfDirty()21459     public RenderNode updateDisplayListIfDirty() {
21460         final RenderNode renderNode = mRenderNode;
21461         if (!canHaveDisplayList()) {
21462             // can't populate RenderNode, don't try
21463             return renderNode;
21464         }
21465 
21466         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
21467                 || !renderNode.hasDisplayList()
21468                 || (mRecreateDisplayList)) {
21469             // Don't need to recreate the display list, just need to tell our
21470             // children to restore/recreate theirs
21471             if (renderNode.hasDisplayList()
21472                     && !mRecreateDisplayList) {
21473                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21474                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21475                 dispatchGetDisplayList();
21476 
21477                 return renderNode; // no work needed
21478             }
21479 
21480             // If we got here, we're recreating it. Mark it as such to ensure that
21481             // we copy in child display lists into ours in drawChild()
21482             mRecreateDisplayList = true;
21483 
21484             int width = mRight - mLeft;
21485             int height = mBottom - mTop;
21486             int layerType = getLayerType();
21487 
21488             // Hacky hack: Reset any stretch effects as those are applied during the draw pass
21489             // instead of being "stateful" like other RenderNode properties
21490             renderNode.clearStretch();
21491 
21492             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
21493 
21494             try {
21495                 if (layerType == LAYER_TYPE_SOFTWARE) {
21496                     buildDrawingCache(true);
21497                     Bitmap cache = getDrawingCache(true);
21498                     if (cache != null) {
21499                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
21500                     }
21501                 } else {
21502                     computeScroll();
21503 
21504                     canvas.translate(-mScrollX, -mScrollY);
21505                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21506                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21507 
21508                     // Fast path for layouts with no backgrounds
21509                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21510                         dispatchDraw(canvas);
21511                         drawAutofilledHighlight(canvas);
21512                         if (mOverlay != null && !mOverlay.isEmpty()) {
21513                             mOverlay.getOverlayView().draw(canvas);
21514                         }
21515                         if (isShowingLayoutBounds()) {
21516                             debugDrawFocus(canvas);
21517                         }
21518                     } else {
21519                         draw(canvas);
21520                     }
21521                 }
21522             } finally {
21523                 renderNode.endRecording();
21524                 setDisplayListProperties(renderNode);
21525             }
21526         } else {
21527             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21528             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21529         }
21530         return renderNode;
21531     }
21532 
21533     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resetDisplayList()21534     private void resetDisplayList() {
21535         mRenderNode.discardDisplayList();
21536         if (mBackgroundRenderNode != null) {
21537             mBackgroundRenderNode.discardDisplayList();
21538         }
21539     }
21540 
21541     /**
21542      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
21543      *
21544      * @return A non-scaled bitmap representing this view or null if cache is disabled.
21545      *
21546      * @see #getDrawingCache(boolean)
21547      *
21548      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21549      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21550      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21551      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21552      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21553      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21554      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21555      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21556      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21557      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21558      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21559      * reports or unit testing the {@link PixelCopy} API is recommended.
21560      */
21561     @Deprecated
getDrawingCache()21562     public Bitmap getDrawingCache() {
21563         return getDrawingCache(false);
21564     }
21565 
21566     /**
21567      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
21568      * is null when caching is disabled. If caching is enabled and the cache is not ready,
21569      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
21570      * draw from the cache when the cache is enabled. To benefit from the cache, you must
21571      * request the drawing cache by calling this method and draw it on screen if the
21572      * returned bitmap is not null.</p>
21573      *
21574      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21575      * this method will create a bitmap of the same size as this view. Because this bitmap
21576      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21577      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21578      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21579      * size than the view. This implies that your application must be able to handle this
21580      * size.</p>
21581      *
21582      * @param autoScale Indicates whether the generated bitmap should be scaled based on
21583      *        the current density of the screen when the application is in compatibility
21584      *        mode.
21585      *
21586      * @return A bitmap representing this view or null if cache is disabled.
21587      *
21588      * @see #setDrawingCacheEnabled(boolean)
21589      * @see #isDrawingCacheEnabled()
21590      * @see #buildDrawingCache(boolean)
21591      * @see #destroyDrawingCache()
21592      *
21593      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21594      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21595      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21596      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21597      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21598      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21599      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21600      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21601      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21602      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21603      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21604      * reports or unit testing the {@link PixelCopy} API is recommended.
21605      */
21606     @Deprecated
getDrawingCache(boolean autoScale)21607     public Bitmap getDrawingCache(boolean autoScale) {
21608         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
21609             return null;
21610         }
21611         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
21612             buildDrawingCache(autoScale);
21613         }
21614         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
21615     }
21616 
21617     /**
21618      * <p>Frees the resources used by the drawing cache. If you call
21619      * {@link #buildDrawingCache()} manually without calling
21620      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21621      * should cleanup the cache with this method afterwards.</p>
21622      *
21623      * @see #setDrawingCacheEnabled(boolean)
21624      * @see #buildDrawingCache()
21625      * @see #getDrawingCache()
21626      *
21627      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21628      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21629      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21630      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21631      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21632      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21633      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21634      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21635      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21636      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21637      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21638      * reports or unit testing the {@link PixelCopy} API is recommended.
21639      */
21640     @Deprecated
destroyDrawingCache()21641     public void destroyDrawingCache() {
21642         if (mDrawingCache != null) {
21643             mDrawingCache.recycle();
21644             mDrawingCache = null;
21645         }
21646         if (mUnscaledDrawingCache != null) {
21647             mUnscaledDrawingCache.recycle();
21648             mUnscaledDrawingCache = null;
21649         }
21650     }
21651 
21652     /**
21653      * Setting a solid background color for the drawing cache's bitmaps will improve
21654      * performance and memory usage. Note, though that this should only be used if this
21655      * view will always be drawn on top of a solid color.
21656      *
21657      * @param color The background color to use for the drawing cache's bitmap
21658      *
21659      * @see #setDrawingCacheEnabled(boolean)
21660      * @see #buildDrawingCache()
21661      * @see #getDrawingCache()
21662      *
21663      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21664      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21665      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21666      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21667      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21668      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21669      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21670      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21671      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21672      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21673      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21674      * reports or unit testing the {@link PixelCopy} API is recommended.
21675      */
21676     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)21677     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
21678         if (color != mDrawingCacheBackgroundColor) {
21679             mDrawingCacheBackgroundColor = color;
21680             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
21681         }
21682     }
21683 
21684     /**
21685      * @see #setDrawingCacheBackgroundColor(int)
21686      *
21687      * @return The background color to used for the drawing cache's bitmap
21688      *
21689      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21690      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21691      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21692      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21693      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21694      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21695      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21696      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21697      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21698      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21699      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21700      * reports or unit testing the {@link PixelCopy} API is recommended.
21701      */
21702     @Deprecated
21703     @ColorInt
getDrawingCacheBackgroundColor()21704     public int getDrawingCacheBackgroundColor() {
21705         return mDrawingCacheBackgroundColor;
21706     }
21707 
21708     /**
21709      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
21710      *
21711      * @see #buildDrawingCache(boolean)
21712      *
21713      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21714      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21715      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21716      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21717      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21718      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21719      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21720      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21721      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21722      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21723      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21724      * reports or unit testing the {@link PixelCopy} API is recommended.
21725      */
21726     @Deprecated
buildDrawingCache()21727     public void buildDrawingCache() {
21728         buildDrawingCache(false);
21729     }
21730 
21731     /**
21732      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
21733      *
21734      * <p>If you call {@link #buildDrawingCache()} manually without calling
21735      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21736      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
21737      *
21738      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21739      * this method will create a bitmap of the same size as this view. Because this bitmap
21740      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21741      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21742      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21743      * size than the view. This implies that your application must be able to handle this
21744      * size.</p>
21745      *
21746      * <p>You should avoid calling this method when hardware acceleration is enabled. If
21747      * you do not need the drawing cache bitmap, calling this method will increase memory
21748      * usage and cause the view to be rendered in software once, thus negatively impacting
21749      * performance.</p>
21750      *
21751      * @see #getDrawingCache()
21752      * @see #destroyDrawingCache()
21753      *
21754      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21755      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21756      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21757      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21758      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21759      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21760      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21761      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21762      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21763      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21764      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21765      * reports or unit testing the {@link PixelCopy} API is recommended.
21766      */
21767     @Deprecated
buildDrawingCache(boolean autoScale)21768     public void buildDrawingCache(boolean autoScale) {
21769         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
21770                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
21771             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
21772                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
21773                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
21774             }
21775             try {
21776                 buildDrawingCacheImpl(autoScale);
21777             } finally {
21778                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
21779             }
21780         }
21781     }
21782 
21783     /**
21784      * private, internal implementation of buildDrawingCache, used to enable tracing
21785      */
buildDrawingCacheImpl(boolean autoScale)21786     private void buildDrawingCacheImpl(boolean autoScale) {
21787         mCachingFailed = false;
21788 
21789         int width = mRight - mLeft;
21790         int height = mBottom - mTop;
21791 
21792         final AttachInfo attachInfo = mAttachInfo;
21793         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
21794 
21795         if (autoScale && scalingRequired) {
21796             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
21797             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
21798         }
21799 
21800         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
21801         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
21802         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
21803 
21804         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
21805         final long drawingCacheSize =
21806                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
21807         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
21808             if (width > 0 && height > 0) {
21809                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
21810                         + " too large to fit into a software layer (or drawing cache), needs "
21811                         + projectedBitmapSize + " bytes, only "
21812                         + drawingCacheSize + " available");
21813             }
21814             destroyDrawingCache();
21815             mCachingFailed = true;
21816             return;
21817         }
21818 
21819         boolean clear = true;
21820         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
21821 
21822         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
21823             Bitmap.Config quality;
21824             if (!opaque) {
21825                 // Never pick ARGB_4444 because it looks awful
21826                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
21827                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
21828                     case DRAWING_CACHE_QUALITY_AUTO:
21829                     case DRAWING_CACHE_QUALITY_LOW:
21830                     case DRAWING_CACHE_QUALITY_HIGH:
21831                     default:
21832                         quality = Bitmap.Config.ARGB_8888;
21833                         break;
21834                 }
21835             } else {
21836                 // Optimization for translucent windows
21837                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
21838                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
21839             }
21840 
21841             // Try to cleanup memory
21842             if (bitmap != null) bitmap.recycle();
21843 
21844             try {
21845                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
21846                         width, height, quality);
21847                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
21848                 if (autoScale) {
21849                     mDrawingCache = bitmap;
21850                 } else {
21851                     mUnscaledDrawingCache = bitmap;
21852                 }
21853                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
21854             } catch (OutOfMemoryError e) {
21855                 // If there is not enough memory to create the bitmap cache, just
21856                 // ignore the issue as bitmap caches are not required to draw the
21857                 // view hierarchy
21858                 if (autoScale) {
21859                     mDrawingCache = null;
21860                 } else {
21861                     mUnscaledDrawingCache = null;
21862                 }
21863                 mCachingFailed = true;
21864                 return;
21865             }
21866 
21867             clear = drawingCacheBackgroundColor != 0;
21868         }
21869 
21870         Canvas canvas;
21871         if (attachInfo != null) {
21872             canvas = attachInfo.mCanvas;
21873             if (canvas == null) {
21874                 canvas = new Canvas();
21875             }
21876             canvas.setBitmap(bitmap);
21877             // Temporarily clobber the cached Canvas in case one of our children
21878             // is also using a drawing cache. Without this, the children would
21879             // steal the canvas by attaching their own bitmap to it and bad, bad
21880             // thing would happen (invisible views, corrupted drawings, etc.)
21881             attachInfo.mCanvas = null;
21882         } else {
21883             // This case should hopefully never or seldom happen
21884             canvas = new Canvas(bitmap);
21885         }
21886 
21887         if (clear) {
21888             bitmap.eraseColor(drawingCacheBackgroundColor);
21889         }
21890 
21891         computeScroll();
21892         final int restoreCount = canvas.save();
21893 
21894         if (autoScale && scalingRequired) {
21895             final float scale = attachInfo.mApplicationScale;
21896             canvas.scale(scale, scale);
21897         }
21898 
21899         canvas.translate(-mScrollX, -mScrollY);
21900 
21901         mPrivateFlags |= PFLAG_DRAWN;
21902         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
21903                 mLayerType != LAYER_TYPE_NONE) {
21904             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
21905         }
21906 
21907         // Fast path for layouts with no backgrounds
21908         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21909             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21910             dispatchDraw(canvas);
21911             drawAutofilledHighlight(canvas);
21912             if (mOverlay != null && !mOverlay.isEmpty()) {
21913                 mOverlay.getOverlayView().draw(canvas);
21914             }
21915         } else {
21916             draw(canvas);
21917         }
21918 
21919         canvas.restoreToCount(restoreCount);
21920         canvas.setBitmap(null);
21921 
21922         if (attachInfo != null) {
21923             // Restore the cached Canvas for our siblings
21924             attachInfo.mCanvas = canvas;
21925         }
21926     }
21927 
21928     /**
21929      * Create a snapshot of the view into a bitmap.  We should probably make
21930      * some form of this public, but should think about the API.
21931      *
21932      * @hide
21933      */
21934     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)21935     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
21936         int width = mRight - mLeft;
21937         int height = mBottom - mTop;
21938 
21939         final AttachInfo attachInfo = mAttachInfo;
21940         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
21941         width = (int) ((width * scale) + 0.5f);
21942         height = (int) ((height * scale) + 0.5f);
21943 
21944         Canvas oldCanvas = null;
21945         try {
21946             Canvas canvas = canvasProvider.getCanvas(this,
21947                     width > 0 ? width : 1, height > 0 ? height : 1);
21948 
21949             if (attachInfo != null) {
21950                 oldCanvas = attachInfo.mCanvas;
21951                 // Temporarily clobber the cached Canvas in case one of our children
21952                 // is also using a drawing cache. Without this, the children would
21953                 // steal the canvas by attaching their own bitmap to it and bad, bad
21954                 // things would happen (invisible views, corrupted drawings, etc.)
21955                 attachInfo.mCanvas = null;
21956             }
21957 
21958             computeScroll();
21959             final int restoreCount = canvas.save();
21960             canvas.scale(scale, scale);
21961             canvas.translate(-mScrollX, -mScrollY);
21962 
21963             // Temporarily remove the dirty mask
21964             int flags = mPrivateFlags;
21965             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21966 
21967             // Fast path for layouts with no backgrounds
21968             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21969                 dispatchDraw(canvas);
21970                 drawAutofilledHighlight(canvas);
21971                 if (mOverlay != null && !mOverlay.isEmpty()) {
21972                     mOverlay.getOverlayView().draw(canvas);
21973                 }
21974             } else {
21975                 draw(canvas);
21976             }
21977 
21978             mPrivateFlags = flags;
21979             canvas.restoreToCount(restoreCount);
21980             return canvasProvider.createBitmap();
21981         } finally {
21982             if (oldCanvas != null) {
21983                 attachInfo.mCanvas = oldCanvas;
21984             }
21985         }
21986     }
21987 
21988     /**
21989      * Indicates whether this View is currently in edit mode. A View is usually
21990      * in edit mode when displayed within a developer tool. For instance, if
21991      * this View is being drawn by a visual user interface builder, this method
21992      * should return true.
21993      *
21994      * Subclasses should check the return value of this method to provide
21995      * different behaviors if their normal behavior might interfere with the
21996      * host environment. For instance: the class spawns a thread in its
21997      * constructor, the drawing code relies on device-specific features, etc.
21998      *
21999      * This method is usually checked in the drawing code of custom widgets.
22000      *
22001      * @return True if this View is in edit mode, false otherwise.
22002      */
isInEditMode()22003     public boolean isInEditMode() {
22004         return false;
22005     }
22006 
22007     /**
22008      * If the View draws content inside its padding and enables fading edges,
22009      * it needs to support padding offsets. Padding offsets are added to the
22010      * fading edges to extend the length of the fade so that it covers pixels
22011      * drawn inside the padding.
22012      *
22013      * Subclasses of this class should override this method if they need
22014      * to draw content inside the padding.
22015      *
22016      * @return True if padding offset must be applied, false otherwise.
22017      *
22018      * @see #getLeftPaddingOffset()
22019      * @see #getRightPaddingOffset()
22020      * @see #getTopPaddingOffset()
22021      * @see #getBottomPaddingOffset()
22022      *
22023      * @since CURRENT
22024      */
isPaddingOffsetRequired()22025     protected boolean isPaddingOffsetRequired() {
22026         return false;
22027     }
22028 
22029     /**
22030      * Amount by which to extend the left fading region. Called only when
22031      * {@link #isPaddingOffsetRequired()} returns true.
22032      *
22033      * @return The left padding offset in pixels.
22034      *
22035      * @see #isPaddingOffsetRequired()
22036      *
22037      * @since CURRENT
22038      */
getLeftPaddingOffset()22039     protected int getLeftPaddingOffset() {
22040         return 0;
22041     }
22042 
22043     /**
22044      * Amount by which to extend the right fading region. Called only when
22045      * {@link #isPaddingOffsetRequired()} returns true.
22046      *
22047      * @return The right padding offset in pixels.
22048      *
22049      * @see #isPaddingOffsetRequired()
22050      *
22051      * @since CURRENT
22052      */
getRightPaddingOffset()22053     protected int getRightPaddingOffset() {
22054         return 0;
22055     }
22056 
22057     /**
22058      * Amount by which to extend the top fading region. Called only when
22059      * {@link #isPaddingOffsetRequired()} returns true.
22060      *
22061      * @return The top padding offset in pixels.
22062      *
22063      * @see #isPaddingOffsetRequired()
22064      *
22065      * @since CURRENT
22066      */
getTopPaddingOffset()22067     protected int getTopPaddingOffset() {
22068         return 0;
22069     }
22070 
22071     /**
22072      * Amount by which to extend the bottom fading region. Called only when
22073      * {@link #isPaddingOffsetRequired()} returns true.
22074      *
22075      * @return The bottom padding offset in pixels.
22076      *
22077      * @see #isPaddingOffsetRequired()
22078      *
22079      * @since CURRENT
22080      */
getBottomPaddingOffset()22081     protected int getBottomPaddingOffset() {
22082         return 0;
22083     }
22084 
22085     /**
22086      * @hide
22087      * @param offsetRequired
22088      */
getFadeTop(boolean offsetRequired)22089     protected int getFadeTop(boolean offsetRequired) {
22090         int top = mPaddingTop;
22091         if (offsetRequired) top += getTopPaddingOffset();
22092         return top;
22093     }
22094 
22095     /**
22096      * @hide
22097      * @param offsetRequired
22098      */
getFadeHeight(boolean offsetRequired)22099     protected int getFadeHeight(boolean offsetRequired) {
22100         int padding = mPaddingTop;
22101         if (offsetRequired) padding += getTopPaddingOffset();
22102         return mBottom - mTop - mPaddingBottom - padding;
22103     }
22104 
22105     /**
22106      * <p>Indicates whether this view is attached to a hardware accelerated
22107      * window or not.</p>
22108      *
22109      * <p>Even if this method returns true, it does not mean that every call
22110      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
22111      * accelerated {@link android.graphics.Canvas}. For instance, if this view
22112      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
22113      * window is hardware accelerated,
22114      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
22115      * return false, and this method will return true.</p>
22116      *
22117      * @return True if the view is attached to a window and the window is
22118      *         hardware accelerated; false in any other case.
22119      */
22120     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()22121     public boolean isHardwareAccelerated() {
22122         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
22123     }
22124 
22125     /**
22126      * Sets a rectangular area on this view to which the view will be clipped
22127      * when it is drawn. Setting the value to null will remove the clip bounds
22128      * and the view will draw normally, using its full bounds.
22129      *
22130      * @param clipBounds The rectangular area, in the local coordinates of
22131      * this view, to which future drawing operations will be clipped.
22132      */
setClipBounds(Rect clipBounds)22133     public void setClipBounds(Rect clipBounds) {
22134         if (clipBounds == mClipBounds
22135                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
22136             return;
22137         }
22138         if (clipBounds != null) {
22139             if (mClipBounds == null) {
22140                 mClipBounds = new Rect(clipBounds);
22141             } else {
22142                 mClipBounds.set(clipBounds);
22143             }
22144         } else {
22145             mClipBounds = null;
22146         }
22147         mRenderNode.setClipRect(mClipBounds);
22148         invalidateViewProperty(false, false);
22149     }
22150 
22151     /**
22152      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
22153      *
22154      * @return A copy of the current clip bounds if clip bounds are set,
22155      * otherwise null.
22156      */
getClipBounds()22157     public Rect getClipBounds() {
22158         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
22159     }
22160 
22161 
22162     /**
22163      * Populates an output rectangle with the clip bounds of the view,
22164      * returning {@code true} if successful or {@code false} if the view's
22165      * clip bounds are {@code null}.
22166      *
22167      * @param outRect rectangle in which to place the clip bounds of the view
22168      * @return {@code true} if successful or {@code false} if the view's
22169      *         clip bounds are {@code null}
22170      */
getClipBounds(Rect outRect)22171     public boolean getClipBounds(Rect outRect) {
22172         if (mClipBounds != null) {
22173             outRect.set(mClipBounds);
22174             return true;
22175         }
22176         return false;
22177     }
22178 
22179     /**
22180      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
22181      * case of an active Animation being run on the view.
22182      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)22183     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
22184             Animation a, boolean scalingRequired) {
22185         Transformation invalidationTransform;
22186         final int flags = parent.mGroupFlags;
22187         final boolean initialized = a.isInitialized();
22188         if (!initialized) {
22189             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
22190             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
22191             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
22192             onAnimationStart();
22193         }
22194 
22195         final Transformation t = parent.getChildTransformation();
22196         boolean more = a.getTransformation(drawingTime, t, 1f);
22197         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
22198             if (parent.mInvalidationTransformation == null) {
22199                 parent.mInvalidationTransformation = new Transformation();
22200             }
22201             invalidationTransform = parent.mInvalidationTransformation;
22202             a.getTransformation(drawingTime, invalidationTransform, 1f);
22203         } else {
22204             invalidationTransform = t;
22205         }
22206 
22207         if (more) {
22208             if (!a.willChangeBounds()) {
22209                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
22210                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
22211                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
22212                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
22213                     // The child need to draw an animation, potentially offscreen, so
22214                     // make sure we do not cancel invalidate requests
22215                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
22216                     parent.invalidate(mLeft, mTop, mRight, mBottom);
22217                 }
22218             } else {
22219                 if (parent.mInvalidateRegion == null) {
22220                     parent.mInvalidateRegion = new RectF();
22221                 }
22222                 final RectF region = parent.mInvalidateRegion;
22223                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
22224                         invalidationTransform);
22225 
22226                 // The child need to draw an animation, potentially offscreen, so
22227                 // make sure we do not cancel invalidate requests
22228                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
22229 
22230                 final int left = mLeft + (int) region.left;
22231                 final int top = mTop + (int) region.top;
22232                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
22233                         top + (int) (region.height() + .5f));
22234             }
22235         }
22236         return more;
22237     }
22238 
22239     /**
22240      * This method is called by getDisplayList() when a display list is recorded for a View.
22241      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
22242      */
setDisplayListProperties(RenderNode renderNode)22243     void setDisplayListProperties(RenderNode renderNode) {
22244         if (renderNode != null) {
22245             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
22246             renderNode.setClipToBounds(mParent instanceof ViewGroup
22247                     && ((ViewGroup) mParent).getClipChildren());
22248 
22249             float alpha = 1;
22250             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
22251                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22252                 ViewGroup parentVG = (ViewGroup) mParent;
22253                 final Transformation t = parentVG.getChildTransformation();
22254                 if (parentVG.getChildStaticTransformation(this, t)) {
22255                     final int transformType = t.getTransformationType();
22256                     if (transformType != Transformation.TYPE_IDENTITY) {
22257                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
22258                             alpha = t.getAlpha();
22259                         }
22260                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
22261                             renderNode.setStaticMatrix(t.getMatrix());
22262                         }
22263                     }
22264                 }
22265             }
22266             if (mTransformationInfo != null) {
22267                 alpha *= getFinalAlpha();
22268                 if (alpha < 1) {
22269                     final int multipliedAlpha = (int) (255 * alpha);
22270                     if (onSetAlpha(multipliedAlpha)) {
22271                         alpha = 1;
22272                     }
22273                 }
22274                 renderNode.setAlpha(alpha);
22275             } else if (alpha < 1) {
22276                 renderNode.setAlpha(alpha);
22277             }
22278         }
22279     }
22280 
22281     /**
22282      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
22283      *
22284      * This is where the View specializes rendering behavior based on layer type,
22285      * and hardware acceleration.
22286      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)22287     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
22288 
22289         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
22290         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
22291          *
22292          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
22293          * HW accelerated, it can't handle drawing RenderNodes.
22294          */
22295         boolean drawingWithRenderNode = mAttachInfo != null
22296                 && mAttachInfo.mHardwareAccelerated
22297                 && hardwareAcceleratedCanvas;
22298 
22299         boolean more = false;
22300         final boolean childHasIdentityMatrix = hasIdentityMatrix();
22301         final int parentFlags = parent.mGroupFlags;
22302 
22303         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
22304             parent.getChildTransformation().clear();
22305             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22306         }
22307 
22308         Transformation transformToApply = null;
22309         boolean concatMatrix = false;
22310         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
22311         final Animation a = getAnimation();
22312         if (a != null) {
22313             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
22314             concatMatrix = a.willChangeTransformationMatrix();
22315             if (concatMatrix) {
22316                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22317             }
22318             transformToApply = parent.getChildTransformation();
22319         } else {
22320             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
22321                 // No longer animating: clear out old animation matrix
22322                 mRenderNode.setAnimationMatrix(null);
22323                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22324             }
22325             if (!drawingWithRenderNode
22326                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22327                 final Transformation t = parent.getChildTransformation();
22328                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
22329                 if (hasTransform) {
22330                     final int transformType = t.getTransformationType();
22331                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
22332                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
22333                 }
22334             }
22335         }
22336 
22337         concatMatrix |= !childHasIdentityMatrix;
22338 
22339         // Sets the flag as early as possible to allow draw() implementations
22340         // to call invalidate() successfully when doing animations
22341         mPrivateFlags |= PFLAG_DRAWN;
22342 
22343         if (!concatMatrix &&
22344                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
22345                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
22346                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
22347                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
22348             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
22349             return more;
22350         }
22351         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
22352 
22353         if (hardwareAcceleratedCanvas) {
22354             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
22355             // retain the flag's value temporarily in the mRecreateDisplayList flag
22356             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
22357             mPrivateFlags &= ~PFLAG_INVALIDATED;
22358         }
22359 
22360         RenderNode renderNode = null;
22361         Bitmap cache = null;
22362         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
22363         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
22364              if (layerType != LAYER_TYPE_NONE) {
22365                  // If not drawing with RenderNode, treat HW layers as SW
22366                  layerType = LAYER_TYPE_SOFTWARE;
22367                  buildDrawingCache(true);
22368             }
22369             cache = getDrawingCache(true);
22370         }
22371 
22372         if (drawingWithRenderNode) {
22373             // Delay getting the display list until animation-driven alpha values are
22374             // set up and possibly passed on to the view
22375             renderNode = updateDisplayListIfDirty();
22376             if (!renderNode.hasDisplayList()) {
22377                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
22378                 // to getDisplayList(), the display list will be marked invalid and we should not
22379                 // try to use it again.
22380                 renderNode = null;
22381                 drawingWithRenderNode = false;
22382             }
22383         }
22384 
22385         int sx = 0;
22386         int sy = 0;
22387         if (!drawingWithRenderNode) {
22388             computeScroll();
22389             sx = mScrollX;
22390             sy = mScrollY;
22391         }
22392 
22393         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
22394         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
22395 
22396         int restoreTo = -1;
22397         if (!drawingWithRenderNode || transformToApply != null) {
22398             restoreTo = canvas.save();
22399         }
22400         if (offsetForScroll) {
22401             canvas.translate(mLeft - sx, mTop - sy);
22402         } else {
22403             if (!drawingWithRenderNode) {
22404                 canvas.translate(mLeft, mTop);
22405             }
22406             if (scalingRequired) {
22407                 if (drawingWithRenderNode) {
22408                     // TODO: Might not need this if we put everything inside the DL
22409                     restoreTo = canvas.save();
22410                 }
22411                 // mAttachInfo cannot be null, otherwise scalingRequired == false
22412                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
22413                 canvas.scale(scale, scale);
22414             }
22415         }
22416 
22417         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
22418         if (transformToApply != null
22419                 || alpha < 1
22420                 || !hasIdentityMatrix()
22421                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
22422             if (transformToApply != null || !childHasIdentityMatrix) {
22423                 int transX = 0;
22424                 int transY = 0;
22425 
22426                 if (offsetForScroll) {
22427                     transX = -sx;
22428                     transY = -sy;
22429                 }
22430 
22431                 if (transformToApply != null) {
22432                     if (concatMatrix) {
22433                         if (drawingWithRenderNode) {
22434                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
22435                         } else {
22436                             // Undo the scroll translation, apply the transformation matrix,
22437                             // then redo the scroll translate to get the correct result.
22438                             canvas.translate(-transX, -transY);
22439                             canvas.concat(transformToApply.getMatrix());
22440                             canvas.translate(transX, transY);
22441                         }
22442                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22443                     }
22444 
22445                     float transformAlpha = transformToApply.getAlpha();
22446                     if (transformAlpha < 1) {
22447                         alpha *= transformAlpha;
22448                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22449                     }
22450                 }
22451 
22452                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
22453                     canvas.translate(-transX, -transY);
22454                     canvas.concat(getMatrix());
22455                     canvas.translate(transX, transY);
22456                 }
22457             }
22458 
22459             // Deal with alpha if it is or used to be <1
22460             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
22461                 if (alpha < 1) {
22462                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
22463                 } else {
22464                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
22465                 }
22466                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22467                 if (!drawingWithDrawingCache) {
22468                     final int multipliedAlpha = (int) (255 * alpha);
22469                     if (!onSetAlpha(multipliedAlpha)) {
22470                         if (drawingWithRenderNode) {
22471                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
22472                         } else if (layerType == LAYER_TYPE_NONE) {
22473                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
22474                                     multipliedAlpha);
22475                         }
22476                     } else {
22477                         // Alpha is handled by the child directly, clobber the layer's alpha
22478                         mPrivateFlags |= PFLAG_ALPHA_SET;
22479                     }
22480                 }
22481             }
22482         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
22483             onSetAlpha(255);
22484             mPrivateFlags &= ~PFLAG_ALPHA_SET;
22485         }
22486 
22487         if (!drawingWithRenderNode) {
22488             // apply clips directly, since RenderNode won't do it for this draw
22489             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
22490                 if (offsetForScroll) {
22491                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
22492                 } else {
22493                     if (!scalingRequired || cache == null) {
22494                         canvas.clipRect(0, 0, getWidth(), getHeight());
22495                     } else {
22496                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
22497                     }
22498                 }
22499             }
22500 
22501             if (mClipBounds != null) {
22502                 // clip bounds ignore scroll
22503                 canvas.clipRect(mClipBounds);
22504             }
22505         }
22506 
22507         if (!drawingWithDrawingCache) {
22508             if (drawingWithRenderNode) {
22509                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22510                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22511             } else {
22512                 // Fast path for layouts with no backgrounds
22513                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22514                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22515                     dispatchDraw(canvas);
22516                 } else {
22517                     draw(canvas);
22518                 }
22519             }
22520         } else if (cache != null) {
22521             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22522             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
22523                 // no layer paint, use temporary paint to draw bitmap
22524                 Paint cachePaint = parent.mCachePaint;
22525                 if (cachePaint == null) {
22526                     cachePaint = new Paint();
22527                     cachePaint.setDither(false);
22528                     parent.mCachePaint = cachePaint;
22529                 }
22530                 cachePaint.setAlpha((int) (alpha * 255));
22531                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
22532             } else {
22533                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
22534                 int layerPaintAlpha = mLayerPaint.getAlpha();
22535                 if (alpha < 1) {
22536                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
22537                 }
22538                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
22539                 if (alpha < 1) {
22540                     mLayerPaint.setAlpha(layerPaintAlpha);
22541                 }
22542             }
22543         }
22544 
22545         if (restoreTo >= 0) {
22546             canvas.restoreToCount(restoreTo);
22547         }
22548 
22549         if (a != null && !more) {
22550             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
22551                 onSetAlpha(255);
22552             }
22553             parent.finishAnimatingView(this, a);
22554         }
22555 
22556         if (more && hardwareAcceleratedCanvas) {
22557             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
22558                 // alpha animations should cause the child to recreate its display list
22559                 invalidate(true);
22560             }
22561         }
22562 
22563         mRecreateDisplayList = false;
22564 
22565         return more;
22566     }
22567 
getDebugPaint()22568     static Paint getDebugPaint() {
22569         if (sDebugPaint == null) {
22570             sDebugPaint = new Paint();
22571             sDebugPaint.setAntiAlias(false);
22572         }
22573         return sDebugPaint;
22574     }
22575 
dipsToPixels(int dips)22576     final int dipsToPixels(int dips) {
22577         float scale = getContext().getResources().getDisplayMetrics().density;
22578         return (int) (dips * scale + 0.5f);
22579     }
22580 
debugDrawFocus(Canvas canvas)22581     final private void debugDrawFocus(Canvas canvas) {
22582         if (isFocused()) {
22583             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
22584             final int l = mScrollX;
22585             final int r = l + mRight - mLeft;
22586             final int t = mScrollY;
22587             final int b = t + mBottom - mTop;
22588 
22589             final Paint paint = getDebugPaint();
22590             paint.setColor(DEBUG_CORNERS_COLOR);
22591 
22592             // Draw squares in corners.
22593             paint.setStyle(Paint.Style.FILL);
22594             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
22595             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
22596             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
22597             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
22598 
22599             // Draw big X across the view.
22600             paint.setStyle(Paint.Style.STROKE);
22601             canvas.drawLine(l, t, r, b, paint);
22602             canvas.drawLine(l, b, r, t, paint);
22603         }
22604     }
22605 
22606     /**
22607      * Manually render this view (and all of its children) to the given Canvas.
22608      * The view must have already done a full layout before this function is
22609      * called.  When implementing a view, implement
22610      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
22611      * If you do need to override this method, call the superclass version.
22612      *
22613      * @param canvas The Canvas to which the View is rendered.
22614      */
22615     @CallSuper
draw(Canvas canvas)22616     public void draw(Canvas canvas) {
22617         final int privateFlags = mPrivateFlags;
22618         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
22619 
22620         /*
22621          * Draw traversal performs several drawing steps which must be executed
22622          * in the appropriate order:
22623          *
22624          *      1. Draw the background
22625          *      2. If necessary, save the canvas' layers to prepare for fading
22626          *      3. Draw view's content
22627          *      4. Draw children
22628          *      5. If necessary, draw the fading edges and restore layers
22629          *      6. Draw decorations (scrollbars for instance)
22630          *      7. If necessary, draw the default focus highlight
22631          */
22632 
22633         // Step 1, draw the background, if needed
22634         int saveCount;
22635 
22636         drawBackground(canvas);
22637 
22638         // skip step 2 & 5 if possible (common case)
22639         final int viewFlags = mViewFlags;
22640         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
22641         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
22642         if (!verticalEdges && !horizontalEdges) {
22643             // Step 3, draw the content
22644             onDraw(canvas);
22645 
22646             // Step 4, draw the children
22647             dispatchDraw(canvas);
22648 
22649             drawAutofilledHighlight(canvas);
22650 
22651             // Overlay is part of the content and draws beneath Foreground
22652             if (mOverlay != null && !mOverlay.isEmpty()) {
22653                 mOverlay.getOverlayView().dispatchDraw(canvas);
22654             }
22655 
22656             // Step 6, draw decorations (foreground, scrollbars)
22657             onDrawForeground(canvas);
22658 
22659             // Step 7, draw the default focus highlight
22660             drawDefaultFocusHighlight(canvas);
22661 
22662             if (isShowingLayoutBounds()) {
22663                 debugDrawFocus(canvas);
22664             }
22665 
22666             // we're done...
22667             return;
22668         }
22669 
22670         /*
22671          * Here we do the full fledged routine...
22672          * (this is an uncommon case where speed matters less,
22673          * this is why we repeat some of the tests that have been
22674          * done above)
22675          */
22676 
22677         boolean drawTop = false;
22678         boolean drawBottom = false;
22679         boolean drawLeft = false;
22680         boolean drawRight = false;
22681 
22682         float topFadeStrength = 0.0f;
22683         float bottomFadeStrength = 0.0f;
22684         float leftFadeStrength = 0.0f;
22685         float rightFadeStrength = 0.0f;
22686 
22687         // Step 2, save the canvas' layers
22688         int paddingLeft = mPaddingLeft;
22689 
22690         final boolean offsetRequired = isPaddingOffsetRequired();
22691         if (offsetRequired) {
22692             paddingLeft += getLeftPaddingOffset();
22693         }
22694 
22695         int left = mScrollX + paddingLeft;
22696         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
22697         int top = mScrollY + getFadeTop(offsetRequired);
22698         int bottom = top + getFadeHeight(offsetRequired);
22699 
22700         if (offsetRequired) {
22701             right += getRightPaddingOffset();
22702             bottom += getBottomPaddingOffset();
22703         }
22704 
22705         final ScrollabilityCache scrollabilityCache = mScrollCache;
22706         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
22707         int length = (int) fadeHeight;
22708 
22709         // clip the fade length if top and bottom fades overlap
22710         // overlapping fades produce odd-looking artifacts
22711         if (verticalEdges && (top + length > bottom - length)) {
22712             length = (bottom - top) / 2;
22713         }
22714 
22715         // also clip horizontal fades if necessary
22716         if (horizontalEdges && (left + length > right - length)) {
22717             length = (right - left) / 2;
22718         }
22719 
22720         if (verticalEdges) {
22721             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
22722             drawTop = topFadeStrength * fadeHeight > 1.0f;
22723             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
22724             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
22725         }
22726 
22727         if (horizontalEdges) {
22728             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
22729             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
22730             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
22731             drawRight = rightFadeStrength * fadeHeight > 1.0f;
22732         }
22733 
22734         saveCount = canvas.getSaveCount();
22735         int topSaveCount = -1;
22736         int bottomSaveCount = -1;
22737         int leftSaveCount = -1;
22738         int rightSaveCount = -1;
22739 
22740         int solidColor = getSolidColor();
22741         if (solidColor == 0) {
22742             if (drawTop) {
22743                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
22744             }
22745 
22746             if (drawBottom) {
22747                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
22748             }
22749 
22750             if (drawLeft) {
22751                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
22752             }
22753 
22754             if (drawRight) {
22755                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
22756             }
22757         } else {
22758             scrollabilityCache.setFadeColor(solidColor);
22759         }
22760 
22761         // Step 3, draw the content
22762         onDraw(canvas);
22763 
22764         // Step 4, draw the children
22765         dispatchDraw(canvas);
22766 
22767         // Step 5, draw the fade effect and restore layers
22768         final Paint p = scrollabilityCache.paint;
22769         final Matrix matrix = scrollabilityCache.matrix;
22770         final Shader fade = scrollabilityCache.shader;
22771 
22772         // must be restored in the reverse order that they were saved
22773         if (drawRight) {
22774             matrix.setScale(1, fadeHeight * rightFadeStrength);
22775             matrix.postRotate(90);
22776             matrix.postTranslate(right, top);
22777             fade.setLocalMatrix(matrix);
22778             p.setShader(fade);
22779             if (solidColor == 0) {
22780                 canvas.restoreUnclippedLayer(rightSaveCount, p);
22781 
22782             } else {
22783                 canvas.drawRect(right - length, top, right, bottom, p);
22784             }
22785         }
22786 
22787         if (drawLeft) {
22788             matrix.setScale(1, fadeHeight * leftFadeStrength);
22789             matrix.postRotate(-90);
22790             matrix.postTranslate(left, top);
22791             fade.setLocalMatrix(matrix);
22792             p.setShader(fade);
22793             if (solidColor == 0) {
22794                 canvas.restoreUnclippedLayer(leftSaveCount, p);
22795             } else {
22796                 canvas.drawRect(left, top, left + length, bottom, p);
22797             }
22798         }
22799 
22800         if (drawBottom) {
22801             matrix.setScale(1, fadeHeight * bottomFadeStrength);
22802             matrix.postRotate(180);
22803             matrix.postTranslate(left, bottom);
22804             fade.setLocalMatrix(matrix);
22805             p.setShader(fade);
22806             if (solidColor == 0) {
22807                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
22808             } else {
22809                 canvas.drawRect(left, bottom - length, right, bottom, p);
22810             }
22811         }
22812 
22813         if (drawTop) {
22814             matrix.setScale(1, fadeHeight * topFadeStrength);
22815             matrix.postTranslate(left, top);
22816             fade.setLocalMatrix(matrix);
22817             p.setShader(fade);
22818             if (solidColor == 0) {
22819                 canvas.restoreUnclippedLayer(topSaveCount, p);
22820             } else {
22821                 canvas.drawRect(left, top, right, top + length, p);
22822             }
22823         }
22824 
22825         canvas.restoreToCount(saveCount);
22826 
22827         drawAutofilledHighlight(canvas);
22828 
22829         // Overlay is part of the content and draws beneath Foreground
22830         if (mOverlay != null && !mOverlay.isEmpty()) {
22831             mOverlay.getOverlayView().dispatchDraw(canvas);
22832         }
22833 
22834         // Step 6, draw decorations (foreground, scrollbars)
22835         onDrawForeground(canvas);
22836 
22837         // Step 7, draw the default focus highlight
22838         drawDefaultFocusHighlight(canvas);
22839 
22840         if (isShowingLayoutBounds()) {
22841             debugDrawFocus(canvas);
22842         }
22843     }
22844 
22845     /**
22846      * Draws the background onto the specified canvas.
22847      *
22848      * @param canvas Canvas on which to draw the background
22849      */
22850     @UnsupportedAppUsage
drawBackground(Canvas canvas)22851     private void drawBackground(Canvas canvas) {
22852         final Drawable background = mBackground;
22853         if (background == null) {
22854             return;
22855         }
22856 
22857         setBackgroundBounds();
22858 
22859         // Attempt to use a display list if requested.
22860         if (canvas.isHardwareAccelerated() && mAttachInfo != null
22861                 && mAttachInfo.mThreadedRenderer != null) {
22862             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
22863 
22864             final RenderNode renderNode = mBackgroundRenderNode;
22865             if (renderNode != null && renderNode.hasDisplayList()) {
22866                 setBackgroundRenderNodeProperties(renderNode);
22867                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22868                 return;
22869             }
22870         }
22871 
22872         final int scrollX = mScrollX;
22873         final int scrollY = mScrollY;
22874         if ((scrollX | scrollY) == 0) {
22875             background.draw(canvas);
22876         } else {
22877             canvas.translate(scrollX, scrollY);
22878             background.draw(canvas);
22879             canvas.translate(-scrollX, -scrollY);
22880         }
22881     }
22882 
22883     /**
22884      * Sets the correct background bounds and rebuilds the outline, if needed.
22885      * <p/>
22886      * This is called by LayoutLib.
22887      */
setBackgroundBounds()22888     void setBackgroundBounds() {
22889         if (mBackgroundSizeChanged && mBackground != null) {
22890             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
22891             mBackgroundSizeChanged = false;
22892             rebuildOutline();
22893         }
22894     }
22895 
setBackgroundRenderNodeProperties(RenderNode renderNode)22896     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
22897         renderNode.setTranslationX(mScrollX);
22898         renderNode.setTranslationY(mScrollY);
22899     }
22900 
22901     /**
22902      * Creates a new display list or updates the existing display list for the
22903      * specified Drawable.
22904      *
22905      * @param drawable Drawable for which to create a display list
22906      * @param renderNode Existing RenderNode, or {@code null}
22907      * @return A valid display list for the specified drawable
22908      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)22909     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
22910         if (renderNode == null) {
22911             renderNode = RenderNode.create(drawable.getClass().getName(),
22912                     new ViewAnimationHostBridge(this));
22913             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
22914         }
22915 
22916         final Rect bounds = drawable.getBounds();
22917         final int width = bounds.width();
22918         final int height = bounds.height();
22919 
22920         // Hacky hack: Reset any stretch effects as those are applied during the draw pass
22921         // instead of being "stateful" like other RenderNode properties
22922         renderNode.clearStretch();
22923 
22924         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
22925 
22926         // Reverse left/top translation done by drawable canvas, which will
22927         // instead be applied by rendernode's LTRB bounds below. This way, the
22928         // drawable's bounds match with its rendernode bounds and its content
22929         // will lie within those bounds in the rendernode tree.
22930         canvas.translate(-bounds.left, -bounds.top);
22931 
22932         try {
22933             drawable.draw(canvas);
22934         } finally {
22935             renderNode.endRecording();
22936         }
22937 
22938         // Set up drawable properties that are view-independent.
22939         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
22940         renderNode.setProjectBackwards(drawable.isProjected());
22941         renderNode.setProjectionReceiver(true);
22942         renderNode.setClipToBounds(false);
22943         return renderNode;
22944     }
22945 
22946     /**
22947      * Returns the overlay for this view, creating it if it does not yet exist.
22948      * Adding drawables to the overlay will cause them to be displayed whenever
22949      * the view itself is redrawn. Objects in the overlay should be actively
22950      * managed: remove them when they should not be displayed anymore. The
22951      * overlay will always have the same size as its host view.
22952      *
22953      * <p>Note: Overlays do not currently work correctly with {@link
22954      * SurfaceView} or {@link TextureView}; contents in overlays for these
22955      * types of views may not display correctly.</p>
22956      *
22957      * @return The ViewOverlay object for this view.
22958      * @see ViewOverlay
22959      */
getOverlay()22960     public ViewOverlay getOverlay() {
22961         if (mOverlay == null) {
22962             mOverlay = new ViewOverlay(mContext, this);
22963         }
22964         return mOverlay;
22965     }
22966 
22967     /**
22968      * Override this if your view is known to always be drawn on top of a solid color background,
22969      * and needs to draw fading edges. Returning a non-zero color enables the view system to
22970      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
22971      * should be set to 0xFF.
22972      *
22973      * @see #setVerticalFadingEdgeEnabled(boolean)
22974      * @see #setHorizontalFadingEdgeEnabled(boolean)
22975      *
22976      * @return The known solid color background for this view, or 0 if the color may vary
22977      */
22978     @ViewDebug.ExportedProperty(category = "drawing")
22979     @InspectableProperty
22980     @ColorInt
getSolidColor()22981     public int getSolidColor() {
22982         return 0;
22983     }
22984 
22985     /**
22986      * Build a human readable string representation of the specified view flags.
22987      *
22988      * @param flags the view flags to convert to a string
22989      * @return a String representing the supplied flags
22990      */
printFlags(int flags)22991     private static String printFlags(int flags) {
22992         String output = "";
22993         int numFlags = 0;
22994         if ((flags & FOCUSABLE) == FOCUSABLE) {
22995             output += "TAKES_FOCUS";
22996             numFlags++;
22997         }
22998 
22999         switch (flags & VISIBILITY_MASK) {
23000         case INVISIBLE:
23001             if (numFlags > 0) {
23002                 output += " ";
23003             }
23004             output += "INVISIBLE";
23005             // USELESS HERE numFlags++;
23006             break;
23007         case GONE:
23008             if (numFlags > 0) {
23009                 output += " ";
23010             }
23011             output += "GONE";
23012             // USELESS HERE numFlags++;
23013             break;
23014         default:
23015             break;
23016         }
23017         return output;
23018     }
23019 
23020     /**
23021      * Build a human readable string representation of the specified private
23022      * view flags.
23023      *
23024      * @param privateFlags the private view flags to convert to a string
23025      * @return a String representing the supplied flags
23026      */
printPrivateFlags(int privateFlags)23027     private static String printPrivateFlags(int privateFlags) {
23028         String output = "";
23029         int numFlags = 0;
23030 
23031         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
23032             output += "WANTS_FOCUS";
23033             numFlags++;
23034         }
23035 
23036         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
23037             if (numFlags > 0) {
23038                 output += " ";
23039             }
23040             output += "FOCUSED";
23041             numFlags++;
23042         }
23043 
23044         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
23045             if (numFlags > 0) {
23046                 output += " ";
23047             }
23048             output += "SELECTED";
23049             numFlags++;
23050         }
23051 
23052         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
23053             if (numFlags > 0) {
23054                 output += " ";
23055             }
23056             output += "IS_ROOT_NAMESPACE";
23057             numFlags++;
23058         }
23059 
23060         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
23061             if (numFlags > 0) {
23062                 output += " ";
23063             }
23064             output += "HAS_BOUNDS";
23065             numFlags++;
23066         }
23067 
23068         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
23069             if (numFlags > 0) {
23070                 output += " ";
23071             }
23072             output += "DRAWN";
23073             // USELESS HERE numFlags++;
23074         }
23075         return output;
23076     }
23077 
23078     /**
23079      * <p>Indicates whether or not this view's layout will be requested during
23080      * the next hierarchy layout pass.</p>
23081      *
23082      * @return true if the layout will be forced during next layout pass
23083      */
isLayoutRequested()23084     public boolean isLayoutRequested() {
23085         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
23086     }
23087 
23088     /**
23089      * Return true if o is a ViewGroup that is laying out using optical bounds.
23090      * @hide
23091      */
isLayoutModeOptical(Object o)23092     public static boolean isLayoutModeOptical(Object o) {
23093         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
23094     }
23095 
setOpticalFrame(int left, int top, int right, int bottom)23096     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
23097         Insets parentInsets = mParent instanceof View ?
23098                 ((View) mParent).getOpticalInsets() : Insets.NONE;
23099         Insets childInsets = getOpticalInsets();
23100         return setFrame(
23101                 left   + parentInsets.left - childInsets.left,
23102                 top    + parentInsets.top  - childInsets.top,
23103                 right  + parentInsets.left + childInsets.right,
23104                 bottom + parentInsets.top  + childInsets.bottom);
23105     }
23106 
23107     /**
23108      * Assign a size and position to a view and all of its
23109      * descendants
23110      *
23111      * <p>This is the second phase of the layout mechanism.
23112      * (The first is measuring). In this phase, each parent calls
23113      * layout on all of its children to position them.
23114      * This is typically done using the child measurements
23115      * that were stored in the measure pass().</p>
23116      *
23117      * <p>Derived classes should not override this method.
23118      * Derived classes with children should override
23119      * onLayout. In that method, they should
23120      * call layout on each of their children.</p>
23121      *
23122      * @param l Left position, relative to parent
23123      * @param t Top position, relative to parent
23124      * @param r Right position, relative to parent
23125      * @param b Bottom position, relative to parent
23126      */
23127     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)23128     public void layout(int l, int t, int r, int b) {
23129         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
23130             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
23131             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
23132         }
23133 
23134         int oldL = mLeft;
23135         int oldT = mTop;
23136         int oldB = mBottom;
23137         int oldR = mRight;
23138 
23139         boolean changed = isLayoutModeOptical(mParent) ?
23140                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
23141 
23142         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
23143             onLayout(changed, l, t, r, b);
23144 
23145             if (shouldDrawRoundScrollbar()) {
23146                 if(mRoundScrollbarRenderer == null) {
23147                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
23148                 }
23149             } else {
23150                 mRoundScrollbarRenderer = null;
23151             }
23152 
23153             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
23154 
23155             ListenerInfo li = mListenerInfo;
23156             if (li != null && li.mOnLayoutChangeListeners != null) {
23157                 ArrayList<OnLayoutChangeListener> listenersCopy =
23158                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
23159                 int numListeners = listenersCopy.size();
23160                 for (int i = 0; i < numListeners; ++i) {
23161                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
23162                 }
23163             }
23164         }
23165 
23166         final boolean wasLayoutValid = isLayoutValid();
23167 
23168         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
23169         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
23170 
23171         if (!wasLayoutValid && isFocused()) {
23172             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
23173             if (canTakeFocus()) {
23174                 // We have a robust focus, so parents should no longer be wanting focus.
23175                 clearParentsWantFocus();
23176             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
23177                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
23178                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
23179                 // and thus the safest action is to clear focus here.
23180                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23181                 clearParentsWantFocus();
23182             } else if (!hasParentWantsFocus()) {
23183                 // original requestFocus was likely on this view directly, so just clear focus
23184                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23185             }
23186             // otherwise, we let parents handle re-assigning focus during their layout passes.
23187         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
23188             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
23189             View focused = findFocus();
23190             if (focused != null) {
23191                 // Try to restore focus as close as possible to our starting focus.
23192                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
23193                     // Give up and clear focus once we've reached the top-most parent which wants
23194                     // focus.
23195                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
23196                 }
23197             }
23198         }
23199 
23200         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
23201             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
23202             notifyEnterOrExitForAutoFillIfNeeded(true);
23203         }
23204 
23205         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
23206     }
23207 
hasParentWantsFocus()23208     private boolean hasParentWantsFocus() {
23209         ViewParent parent = mParent;
23210         while (parent instanceof ViewGroup) {
23211             ViewGroup pv = (ViewGroup) parent;
23212             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
23213                 return true;
23214             }
23215             parent = pv.mParent;
23216         }
23217         return false;
23218     }
23219 
23220     /**
23221      * Called from layout when this view should
23222      * assign a size and position to each of its children.
23223      *
23224      * Derived classes with children should override
23225      * this method and call layout on each of
23226      * their children.
23227      * @param changed This is a new size or position for this view
23228      * @param left Left position, relative to parent
23229      * @param top Top position, relative to parent
23230      * @param right Right position, relative to parent
23231      * @param bottom Bottom position, relative to parent
23232      */
onLayout(boolean changed, int left, int top, int right, int bottom)23233     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
23234     }
23235 
23236     /**
23237      * Assign a size and position to this view.
23238      *
23239      * This is called from layout.
23240      *
23241      * @param left Left position, relative to parent
23242      * @param top Top position, relative to parent
23243      * @param right Right position, relative to parent
23244      * @param bottom Bottom position, relative to parent
23245      * @return true if the new size and position are different than the
23246      *         previous ones
23247      * {@hide}
23248      */
23249     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)23250     protected boolean setFrame(int left, int top, int right, int bottom) {
23251         boolean changed = false;
23252 
23253         if (DBG) {
23254             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
23255                     + right + "," + bottom + ")");
23256         }
23257 
23258         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
23259             changed = true;
23260 
23261             // Remember our drawn bit
23262             int drawn = mPrivateFlags & PFLAG_DRAWN;
23263 
23264             int oldWidth = mRight - mLeft;
23265             int oldHeight = mBottom - mTop;
23266             int newWidth = right - left;
23267             int newHeight = bottom - top;
23268             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
23269 
23270             // Invalidate our old position
23271             invalidate(sizeChanged);
23272 
23273             mLeft = left;
23274             mTop = top;
23275             mRight = right;
23276             mBottom = bottom;
23277             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
23278 
23279             mPrivateFlags |= PFLAG_HAS_BOUNDS;
23280 
23281 
23282             if (sizeChanged) {
23283                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
23284             }
23285 
23286             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
23287                 // If we are visible, force the DRAWN bit to on so that
23288                 // this invalidate will go through (at least to our parent).
23289                 // This is because someone may have invalidated this view
23290                 // before this call to setFrame came in, thereby clearing
23291                 // the DRAWN bit.
23292                 mPrivateFlags |= PFLAG_DRAWN;
23293                 invalidate(sizeChanged);
23294                 // parent display list may need to be recreated based on a change in the bounds
23295                 // of any child
23296                 invalidateParentCaches();
23297             }
23298 
23299             // Reset drawn bit to original value (invalidate turns it off)
23300             mPrivateFlags |= drawn;
23301 
23302             mBackgroundSizeChanged = true;
23303             mDefaultFocusHighlightSizeChanged = true;
23304             if (mForegroundInfo != null) {
23305                 mForegroundInfo.mBoundsChanged = true;
23306             }
23307 
23308             notifySubtreeAccessibilityStateChangedIfNeeded();
23309         }
23310         return changed;
23311     }
23312 
23313     /**
23314      * Assign a size and position to this view.
23315      *
23316      * This method is meant to be used in animations only as it applies this position and size
23317      * for the view only temporary and it can be changed back at any time by the layout.
23318      *
23319      * @param left Left position, relative to parent
23320      * @param top Top position, relative to parent
23321      * @param right Right position, relative to parent
23322      * @param bottom Bottom position, relative to parent
23323      *
23324      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
23325      */
setLeftTopRightBottom(int left, int top, int right, int bottom)23326     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
23327         setFrame(left, top, right, bottom);
23328     }
23329 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)23330     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
23331         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
23332         if (mOverlay != null) {
23333             mOverlay.getOverlayView().setRight(newWidth);
23334             mOverlay.getOverlayView().setBottom(newHeight);
23335         }
23336         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
23337         // backtracking" of requestFocus during layout, so don't touch focus here.
23338         if (!sCanFocusZeroSized && isLayoutValid()
23339                 // Don't touch focus if animating
23340                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
23341             if (newWidth <= 0 || newHeight <= 0) {
23342                 if (hasFocus()) {
23343                     clearFocus();
23344                     if (mParent instanceof ViewGroup) {
23345                         ((ViewGroup) mParent).clearFocusedInCluster();
23346                     }
23347                 }
23348                 clearAccessibilityFocus();
23349             } else if (oldWidth <= 0 || oldHeight <= 0) {
23350                 if (mParent != null && canTakeFocus()) {
23351                     mParent.focusableViewAvailable(this);
23352                 }
23353             }
23354         }
23355         rebuildOutline();
23356     }
23357 
23358     /**
23359      * Finalize inflating a view from XML.  This is called as the last phase
23360      * of inflation, after all child views have been added.
23361      *
23362      * <p>Even if the subclass overrides onFinishInflate, they should always be
23363      * sure to call the super method, so that we get called.
23364      */
23365     @CallSuper
onFinishInflate()23366     protected void onFinishInflate() {
23367     }
23368 
23369     /**
23370      * Returns the resources associated with this view.
23371      *
23372      * @return Resources object.
23373      */
getResources()23374     public Resources getResources() {
23375         return mResources;
23376     }
23377 
23378     /**
23379      * Invalidates the specified Drawable.
23380      *
23381      * @param drawable the drawable to invalidate
23382      */
23383     @Override
invalidateDrawable(@onNull Drawable drawable)23384     public void invalidateDrawable(@NonNull Drawable drawable) {
23385         if (verifyDrawable(drawable)) {
23386             final Rect dirty = drawable.getDirtyBounds();
23387             final int scrollX = mScrollX;
23388             final int scrollY = mScrollY;
23389 
23390             invalidate(dirty.left + scrollX, dirty.top + scrollY,
23391                     dirty.right + scrollX, dirty.bottom + scrollY);
23392             rebuildOutline();
23393         }
23394     }
23395 
23396     /**
23397      * Schedules an action on a drawable to occur at a specified time.
23398      *
23399      * @param who the recipient of the action
23400      * @param what the action to run on the drawable
23401      * @param when the time at which the action must occur. Uses the
23402      *        {@link SystemClock#uptimeMillis} timebase.
23403      */
23404     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)23405     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
23406         if (verifyDrawable(who) && what != null) {
23407             final long delay = when - SystemClock.uptimeMillis();
23408             if (mAttachInfo != null) {
23409                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
23410                         Choreographer.CALLBACK_ANIMATION, what, who,
23411                         Choreographer.subtractFrameDelay(delay));
23412             } else {
23413                 // Postpone the runnable until we know
23414                 // on which thread it needs to run.
23415                 getRunQueue().postDelayed(what, delay);
23416             }
23417         }
23418     }
23419 
23420     /**
23421      * Cancels a scheduled action on a drawable.
23422      *
23423      * @param who the recipient of the action
23424      * @param what the action to cancel
23425      */
23426     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)23427     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
23428         if (verifyDrawable(who) && what != null) {
23429             if (mAttachInfo != null) {
23430                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
23431                         Choreographer.CALLBACK_ANIMATION, what, who);
23432             }
23433             getRunQueue().removeCallbacks(what);
23434         }
23435     }
23436 
23437     /**
23438      * Unschedule any events associated with the given Drawable.  This can be
23439      * used when selecting a new Drawable into a view, so that the previous
23440      * one is completely unscheduled.
23441      *
23442      * @param who The Drawable to unschedule.
23443      *
23444      * @see #drawableStateChanged
23445      */
unscheduleDrawable(Drawable who)23446     public void unscheduleDrawable(Drawable who) {
23447         if (mAttachInfo != null && who != null) {
23448             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
23449                     Choreographer.CALLBACK_ANIMATION, null, who);
23450         }
23451     }
23452 
23453     /**
23454      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
23455      * that the View directionality can and will be resolved before its Drawables.
23456      *
23457      * Will call {@link View#onResolveDrawables} when resolution is done.
23458      *
23459      * @hide
23460      */
resolveDrawables()23461     protected void resolveDrawables() {
23462         // Drawables resolution may need to happen before resolving the layout direction (which is
23463         // done only during the measure() call).
23464         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
23465         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
23466         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
23467         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
23468         // direction to be resolved as its resolved value will be the same as its raw value.
23469         if (!isLayoutDirectionResolved() &&
23470                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
23471             return;
23472         }
23473 
23474         final int layoutDirection = isLayoutDirectionResolved() ?
23475                 getLayoutDirection() : getRawLayoutDirection();
23476 
23477         if (mBackground != null) {
23478             mBackground.setLayoutDirection(layoutDirection);
23479         }
23480         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23481             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
23482         }
23483         if (mDefaultFocusHighlight != null) {
23484             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
23485         }
23486         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
23487         onResolveDrawables(layoutDirection);
23488     }
23489 
areDrawablesResolved()23490     boolean areDrawablesResolved() {
23491         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
23492     }
23493 
23494     /**
23495      * Called when layout direction has been resolved.
23496      *
23497      * The default implementation does nothing.
23498      *
23499      * @param layoutDirection The resolved layout direction.
23500      *
23501      * @see #LAYOUT_DIRECTION_LTR
23502      * @see #LAYOUT_DIRECTION_RTL
23503      *
23504      * @hide
23505      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)23506     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
23507     }
23508 
23509     /**
23510      * @hide
23511      */
23512     @TestApi
resetResolvedDrawables()23513     protected void resetResolvedDrawables() {
23514         resetResolvedDrawablesInternal();
23515     }
23516 
resetResolvedDrawablesInternal()23517     void resetResolvedDrawablesInternal() {
23518         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
23519     }
23520 
23521     /**
23522      * If your view subclass is displaying its own Drawable objects, it should
23523      * override this function and return true for any Drawable it is
23524      * displaying.  This allows animations for those drawables to be
23525      * scheduled.
23526      *
23527      * <p>Be sure to call through to the super class when overriding this
23528      * function.
23529      *
23530      * @param who The Drawable to verify.  Return true if it is one you are
23531      *            displaying, else return the result of calling through to the
23532      *            super class.
23533      *
23534      * @return boolean If true then the Drawable is being displayed in the
23535      *         view; else false and it is not allowed to animate.
23536      *
23537      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
23538      * @see #drawableStateChanged()
23539      */
23540     @CallSuper
verifyDrawable(@onNull Drawable who)23541     protected boolean verifyDrawable(@NonNull Drawable who) {
23542         // Avoid verifying the scroll bar drawable so that we don't end up in
23543         // an invalidation loop. This effectively prevents the scroll bar
23544         // drawable from triggering invalidations and scheduling runnables.
23545         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
23546                 || (mDefaultFocusHighlight == who);
23547     }
23548 
23549     /**
23550      * This function is called whenever the state of the view changes in such
23551      * a way that it impacts the state of drawables being shown.
23552      * <p>
23553      * If the View has a StateListAnimator, it will also be called to run necessary state
23554      * change animations.
23555      * <p>
23556      * Be sure to call through to the superclass when overriding this function.
23557      *
23558      * @see Drawable#setState(int[])
23559      */
23560     @CallSuper
drawableStateChanged()23561     protected void drawableStateChanged() {
23562         final int[] state = getDrawableState();
23563         boolean changed = false;
23564 
23565         final Drawable bg = mBackground;
23566         if (bg != null && bg.isStateful()) {
23567             changed |= bg.setState(state);
23568         }
23569 
23570         final Drawable hl = mDefaultFocusHighlight;
23571         if (hl != null && hl.isStateful()) {
23572             changed |= hl.setState(state);
23573         }
23574 
23575         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23576         if (fg != null && fg.isStateful()) {
23577             changed |= fg.setState(state);
23578         }
23579 
23580         if (mScrollCache != null) {
23581             final Drawable scrollBar = mScrollCache.scrollBar;
23582             if (scrollBar != null && scrollBar.isStateful()) {
23583                 changed |= scrollBar.setState(state)
23584                         && mScrollCache.state != ScrollabilityCache.OFF;
23585             }
23586         }
23587 
23588         if (mStateListAnimator != null) {
23589             mStateListAnimator.setState(state);
23590         }
23591 
23592         if (!isAggregatedVisible()) {
23593             // If we're not visible, skip any animated changes
23594             jumpDrawablesToCurrentState();
23595         }
23596 
23597         if (changed) {
23598             invalidate();
23599         }
23600     }
23601 
23602     /**
23603      * This function is called whenever the view hotspot changes and needs to
23604      * be propagated to drawables or child views managed by the view.
23605      * <p>
23606      * Dispatching to child views is handled by
23607      * {@link #dispatchDrawableHotspotChanged(float, float)}.
23608      * <p>
23609      * Be sure to call through to the superclass when overriding this function.
23610      *
23611      * @param x hotspot x coordinate
23612      * @param y hotspot y coordinate
23613      */
23614     @CallSuper
drawableHotspotChanged(float x, float y)23615     public void drawableHotspotChanged(float x, float y) {
23616         if (mBackground != null) {
23617             mBackground.setHotspot(x, y);
23618         }
23619         if (mDefaultFocusHighlight != null) {
23620             mDefaultFocusHighlight.setHotspot(x, y);
23621         }
23622         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23623             mForegroundInfo.mDrawable.setHotspot(x, y);
23624         }
23625 
23626         dispatchDrawableHotspotChanged(x, y);
23627     }
23628 
23629     /**
23630      * Dispatches drawableHotspotChanged to all of this View's children.
23631      *
23632      * @param x hotspot x coordinate
23633      * @param y hotspot y coordinate
23634      * @see #drawableHotspotChanged(float, float)
23635      */
dispatchDrawableHotspotChanged(float x, float y)23636     public void dispatchDrawableHotspotChanged(float x, float y) {
23637     }
23638 
23639     /**
23640      * Call this to force a view to update its drawable state. This will cause
23641      * drawableStateChanged to be called on this view. Views that are interested
23642      * in the new state should call getDrawableState.
23643      *
23644      * @see #drawableStateChanged
23645      * @see #getDrawableState
23646      */
refreshDrawableState()23647     public void refreshDrawableState() {
23648         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
23649         drawableStateChanged();
23650 
23651         ViewParent parent = mParent;
23652         if (parent != null) {
23653             parent.childDrawableStateChanged(this);
23654         }
23655     }
23656 
23657     /**
23658      * Create a default focus highlight if it doesn't exist.
23659      * @return a default focus highlight.
23660      */
getDefaultFocusHighlightDrawable()23661     private Drawable getDefaultFocusHighlightDrawable() {
23662         if (mDefaultFocusHighlightCache == null) {
23663             if (mContext != null) {
23664                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
23665                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
23666                 mDefaultFocusHighlightCache = ta.getDrawable(0);
23667                 ta.recycle();
23668             }
23669         }
23670         return mDefaultFocusHighlightCache;
23671     }
23672 
23673     /**
23674      * Set the current default focus highlight.
23675      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
23676      */
setDefaultFocusHighlight(Drawable highlight)23677     private void setDefaultFocusHighlight(Drawable highlight) {
23678         mDefaultFocusHighlight = highlight;
23679         mDefaultFocusHighlightSizeChanged = true;
23680         if (highlight != null) {
23681             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23682                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23683             }
23684             highlight.setLayoutDirection(getLayoutDirection());
23685             if (highlight.isStateful()) {
23686                 highlight.setState(getDrawableState());
23687             }
23688             if (isAttachedToWindow()) {
23689                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23690             }
23691             // Set callback last, since the view may still be initializing.
23692             highlight.setCallback(this);
23693         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23694                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
23695             mPrivateFlags |= PFLAG_SKIP_DRAW;
23696         }
23697         invalidate();
23698     }
23699 
23700     /**
23701      * Check whether we need to draw a default focus highlight when this view gets focused,
23702      * which requires:
23703      * <ul>
23704      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
23705      *         is not defined.</li>
23706      *     <li>This view is not in touch mode.</li>
23707      *     <li>This view doesn't opt out for a default focus highlight, via
23708      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
23709      *     <li>This view is attached to window.</li>
23710      * </ul>
23711      * @return {@code true} if a default focus highlight is needed.
23712      * @hide
23713      */
23714     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)23715     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
23716         final boolean lackFocusState = (background == null || !background.isStateful()
23717                 || !background.hasFocusStateSpecified())
23718                 && (foreground == null || !foreground.isStateful()
23719                 || !foreground.hasFocusStateSpecified());
23720         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
23721                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
23722     }
23723 
23724     /**
23725      * When this view is focused, switches on/off the default focused highlight.
23726      * <p>
23727      * This always happens when this view is focused, and only at this moment the default focus
23728      * highlight can be visible.
23729      */
switchDefaultFocusHighlight()23730     private void switchDefaultFocusHighlight() {
23731         if (isFocused()) {
23732             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
23733                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
23734             final boolean active = mDefaultFocusHighlight != null;
23735             if (needed && !active) {
23736                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
23737             } else if (!needed && active) {
23738                 // The highlight is no longer needed, so tear it down.
23739                 setDefaultFocusHighlight(null);
23740             }
23741         }
23742     }
23743 
23744     /**
23745      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
23746      * @param canvas the canvas where we're drawing the highlight.
23747      */
drawDefaultFocusHighlight(Canvas canvas)23748     private void drawDefaultFocusHighlight(Canvas canvas) {
23749         if (mDefaultFocusHighlight != null && isFocused()) {
23750             if (mDefaultFocusHighlightSizeChanged) {
23751                 mDefaultFocusHighlightSizeChanged = false;
23752                 final int l = mScrollX;
23753                 final int r = l + mRight - mLeft;
23754                 final int t = mScrollY;
23755                 final int b = t + mBottom - mTop;
23756                 mDefaultFocusHighlight.setBounds(l, t, r, b);
23757             }
23758             mDefaultFocusHighlight.draw(canvas);
23759         }
23760     }
23761 
23762     /**
23763      * Return an array of resource IDs of the drawable states representing the
23764      * current state of the view.
23765      *
23766      * @return The current drawable state
23767      *
23768      * @see Drawable#setState(int[])
23769      * @see #drawableStateChanged()
23770      * @see #onCreateDrawableState(int)
23771      */
getDrawableState()23772     public final int[] getDrawableState() {
23773         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
23774             return mDrawableState;
23775         } else {
23776             mDrawableState = onCreateDrawableState(0);
23777             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
23778             return mDrawableState;
23779         }
23780     }
23781 
23782     /**
23783      * Generate the new {@link android.graphics.drawable.Drawable} state for
23784      * this view. This is called by the view
23785      * system when the cached Drawable state is determined to be invalid.  To
23786      * retrieve the current state, you should use {@link #getDrawableState}.
23787      *
23788      * @param extraSpace if non-zero, this is the number of extra entries you
23789      * would like in the returned array in which you can place your own
23790      * states.
23791      *
23792      * @return Returns an array holding the current {@link Drawable} state of
23793      * the view.
23794      *
23795      * @see #mergeDrawableStates(int[], int[])
23796      */
onCreateDrawableState(int extraSpace)23797     protected int[] onCreateDrawableState(int extraSpace) {
23798         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
23799                 mParent instanceof View) {
23800             return ((View) mParent).onCreateDrawableState(extraSpace);
23801         }
23802 
23803         int[] drawableState;
23804 
23805         int privateFlags = mPrivateFlags;
23806 
23807         int viewStateIndex = 0;
23808         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
23809         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
23810         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
23811         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
23812         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
23813         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
23814         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
23815             // This is set if HW acceleration is requested, even if the current
23816             // process doesn't allow it.  This is just to allow app preview
23817             // windows to better match their app.
23818             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
23819         }
23820         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
23821 
23822         final int privateFlags2 = mPrivateFlags2;
23823         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
23824             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
23825         }
23826         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
23827             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
23828         }
23829 
23830         drawableState = StateSet.get(viewStateIndex);
23831 
23832         //noinspection ConstantIfStatement
23833         if (false) {
23834             Log.i("View", "drawableStateIndex=" + viewStateIndex);
23835             Log.i("View", toString()
23836                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
23837                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
23838                     + " fo=" + hasFocus()
23839                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
23840                     + " wf=" + hasWindowFocus()
23841                     + ": " + Arrays.toString(drawableState));
23842         }
23843 
23844         if (extraSpace == 0) {
23845             return drawableState;
23846         }
23847 
23848         final int[] fullState;
23849         if (drawableState != null) {
23850             fullState = new int[drawableState.length + extraSpace];
23851             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
23852         } else {
23853             fullState = new int[extraSpace];
23854         }
23855 
23856         return fullState;
23857     }
23858 
23859     /**
23860      * Merge your own state values in <var>additionalState</var> into the base
23861      * state values <var>baseState</var> that were returned by
23862      * {@link #onCreateDrawableState(int)}.
23863      *
23864      * @param baseState The base state values returned by
23865      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
23866      * own additional state values.
23867      *
23868      * @param additionalState The additional state values you would like
23869      * added to <var>baseState</var>; this array is not modified.
23870      *
23871      * @return As a convenience, the <var>baseState</var> array you originally
23872      * passed into the function is returned.
23873      *
23874      * @see #onCreateDrawableState(int)
23875      */
mergeDrawableStates(int[] baseState, int[] additionalState)23876     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
23877         final int N = baseState.length;
23878         int i = N - 1;
23879         while (i >= 0 && baseState[i] == 0) {
23880             i--;
23881         }
23882         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
23883         return baseState;
23884     }
23885 
23886     /**
23887      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
23888      * on all Drawable objects associated with this view.
23889      * <p>
23890      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
23891      * attached to this view.
23892      */
23893     @CallSuper
jumpDrawablesToCurrentState()23894     public void jumpDrawablesToCurrentState() {
23895         if (mBackground != null) {
23896             mBackground.jumpToCurrentState();
23897         }
23898         if (mStateListAnimator != null) {
23899             mStateListAnimator.jumpToCurrentState();
23900         }
23901         if (mDefaultFocusHighlight != null) {
23902             mDefaultFocusHighlight.jumpToCurrentState();
23903         }
23904         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23905             mForegroundInfo.mDrawable.jumpToCurrentState();
23906         }
23907     }
23908 
23909     /**
23910      * Sets the background color for this view.
23911      * @param color the color of the background
23912      */
23913     @RemotableViewMethod
setBackgroundColor(@olorInt int color)23914     public void setBackgroundColor(@ColorInt int color) {
23915         if (mBackground instanceof ColorDrawable) {
23916             ((ColorDrawable) mBackground.mutate()).setColor(color);
23917             computeOpaqueFlags();
23918             mBackgroundResource = 0;
23919         } else {
23920             setBackground(new ColorDrawable(color));
23921         }
23922     }
23923 
23924     /**
23925      * Set the background to a given resource. The resource should refer to
23926      * a Drawable object or 0 to remove the background.
23927      * @param resid The identifier of the resource.
23928      *
23929      * @attr ref android.R.styleable#View_background
23930      */
23931     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)23932     public void setBackgroundResource(@DrawableRes int resid) {
23933         if (resid != 0 && resid == mBackgroundResource) {
23934             return;
23935         }
23936 
23937         Drawable d = null;
23938         if (resid != 0) {
23939             d = mContext.getDrawable(resid);
23940         }
23941         setBackground(d);
23942 
23943         mBackgroundResource = resid;
23944     }
23945 
23946     /**
23947      * Set the background to a given Drawable, or remove the background. If the
23948      * background has padding, this View's padding is set to the background's
23949      * padding. However, when a background is removed, this View's padding isn't
23950      * touched. If setting the padding is desired, please use
23951      * {@link #setPadding(int, int, int, int)}.
23952      *
23953      * @param background The Drawable to use as the background, or null to remove the
23954      *        background
23955      */
setBackground(Drawable background)23956     public void setBackground(Drawable background) {
23957         //noinspection deprecation
23958         setBackgroundDrawable(background);
23959     }
23960 
23961     /**
23962      * @deprecated use {@link #setBackground(Drawable)} instead
23963      */
23964     @Deprecated
setBackgroundDrawable(Drawable background)23965     public void setBackgroundDrawable(Drawable background) {
23966         computeOpaqueFlags();
23967 
23968         if (background == mBackground) {
23969             return;
23970         }
23971 
23972         boolean requestLayout = false;
23973 
23974         mBackgroundResource = 0;
23975 
23976         /*
23977          * Regardless of whether we're setting a new background or not, we want
23978          * to clear the previous drawable. setVisible first while we still have the callback set.
23979          */
23980         if (mBackground != null) {
23981             if (isAttachedToWindow()) {
23982                 mBackground.setVisible(false, false);
23983             }
23984             mBackground.setCallback(null);
23985             unscheduleDrawable(mBackground);
23986         }
23987 
23988         if (background != null) {
23989             Rect padding = sThreadLocal.get();
23990             if (padding == null) {
23991                 padding = new Rect();
23992                 sThreadLocal.set(padding);
23993             }
23994             resetResolvedDrawablesInternal();
23995             background.setLayoutDirection(getLayoutDirection());
23996             if (background.getPadding(padding)) {
23997                 resetResolvedPaddingInternal();
23998                 switch (background.getLayoutDirection()) {
23999                     case LAYOUT_DIRECTION_RTL:
24000                         mUserPaddingLeftInitial = padding.right;
24001                         mUserPaddingRightInitial = padding.left;
24002                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
24003                         break;
24004                     case LAYOUT_DIRECTION_LTR:
24005                     default:
24006                         mUserPaddingLeftInitial = padding.left;
24007                         mUserPaddingRightInitial = padding.right;
24008                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
24009                 }
24010                 mLeftPaddingDefined = false;
24011                 mRightPaddingDefined = false;
24012             }
24013 
24014             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
24015             // if it has a different minimum size, we should layout again
24016             if (mBackground == null
24017                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
24018                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
24019                 requestLayout = true;
24020             }
24021 
24022             // Set mBackground before we set this as the callback and start making other
24023             // background drawable state change calls. In particular, the setVisible call below
24024             // can result in drawables attempting to start animations or otherwise invalidate,
24025             // which requires the view set as the callback (us) to recognize the drawable as
24026             // belonging to it as per verifyDrawable.
24027             mBackground = background;
24028             if (background.isStateful()) {
24029                 background.setState(getDrawableState());
24030             }
24031             if (isAttachedToWindow()) {
24032                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24033             }
24034 
24035             applyBackgroundTint();
24036 
24037             // Set callback last, since the view may still be initializing.
24038             background.setCallback(this);
24039 
24040             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24041                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24042                 requestLayout = true;
24043             }
24044         } else {
24045             /* Remove the background */
24046             mBackground = null;
24047             if ((mViewFlags & WILL_NOT_DRAW) != 0
24048                     && (mDefaultFocusHighlight == null)
24049                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
24050                 mPrivateFlags |= PFLAG_SKIP_DRAW;
24051             }
24052 
24053             /*
24054              * When the background is set, we try to apply its padding to this
24055              * View. When the background is removed, we don't touch this View's
24056              * padding. This is noted in the Javadocs. Hence, we don't need to
24057              * requestLayout(), the invalidate() below is sufficient.
24058              */
24059 
24060             // The old background's minimum size could have affected this
24061             // View's layout, so let's requestLayout
24062             requestLayout = true;
24063         }
24064 
24065         computeOpaqueFlags();
24066 
24067         if (requestLayout) {
24068             requestLayout();
24069         }
24070 
24071         mBackgroundSizeChanged = true;
24072         invalidate(true);
24073         invalidateOutline();
24074     }
24075 
24076     /**
24077      * Gets the background drawable
24078      *
24079      * @return The drawable used as the background for this view, if any.
24080      *
24081      * @see #setBackground(Drawable)
24082      *
24083      * @attr ref android.R.styleable#View_background
24084      */
24085     @InspectableProperty
getBackground()24086     public Drawable getBackground() {
24087         return mBackground;
24088     }
24089 
24090     /**
24091      * Applies a tint to the background drawable. Does not modify the current tint
24092      * mode, which is {@link BlendMode#SRC_IN} by default.
24093      * <p>
24094      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
24095      * mutate the drawable and apply the specified tint and tint mode using
24096      * {@link Drawable#setTintList(ColorStateList)}.
24097      *
24098      * @param tint the tint to apply, may be {@code null} to clear tint
24099      *
24100      * @attr ref android.R.styleable#View_backgroundTint
24101      * @see #getBackgroundTintList()
24102      * @see Drawable#setTintList(ColorStateList)
24103      */
24104     @RemotableViewMethod
setBackgroundTintList(@ullable ColorStateList tint)24105     public void setBackgroundTintList(@Nullable ColorStateList tint) {
24106         if (mBackgroundTint == null) {
24107             mBackgroundTint = new TintInfo();
24108         }
24109         mBackgroundTint.mTintList = tint;
24110         mBackgroundTint.mHasTintList = true;
24111 
24112         applyBackgroundTint();
24113     }
24114 
24115     /**
24116      * Return the tint applied to the background drawable, if specified.
24117      *
24118      * @return the tint applied to the background drawable
24119      * @attr ref android.R.styleable#View_backgroundTint
24120      * @see #setBackgroundTintList(ColorStateList)
24121      */
24122     @InspectableProperty(name = "backgroundTint")
24123     @Nullable
getBackgroundTintList()24124     public ColorStateList getBackgroundTintList() {
24125         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
24126     }
24127 
24128     /**
24129      * Specifies the blending mode used to apply the tint specified by
24130      * {@link #setBackgroundTintList(ColorStateList)}} to the background
24131      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
24132      *
24133      * @param tintMode the blending mode used to apply the tint, may be
24134      *                 {@code null} to clear tint
24135      * @attr ref android.R.styleable#View_backgroundTintMode
24136      * @see #getBackgroundTintMode()
24137      * @see Drawable#setTintMode(PorterDuff.Mode)
24138      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)24139     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
24140         BlendMode mode = null;
24141         if (tintMode != null) {
24142             mode = BlendMode.fromValue(tintMode.nativeInt);
24143         }
24144 
24145         setBackgroundTintBlendMode(mode);
24146     }
24147 
24148     /**
24149      * Specifies the blending mode used to apply the tint specified by
24150      * {@link #setBackgroundTintList(ColorStateList)}} to the background
24151      * drawable. The default mode is {@link BlendMode#SRC_IN}.
24152      *
24153      * @param blendMode the blending mode used to apply the tint, may be
24154      *                 {@code null} to clear tint
24155      * @attr ref android.R.styleable#View_backgroundTintMode
24156      * @see #getBackgroundTintMode()
24157      * @see Drawable#setTintBlendMode(BlendMode)
24158      */
24159     @RemotableViewMethod
setBackgroundTintBlendMode(@ullable BlendMode blendMode)24160     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
24161         if (mBackgroundTint == null) {
24162             mBackgroundTint = new TintInfo();
24163         }
24164 
24165         mBackgroundTint.mBlendMode = blendMode;
24166         mBackgroundTint.mHasTintMode = true;
24167 
24168         applyBackgroundTint();
24169     }
24170 
24171     /**
24172      * Return the blending mode used to apply the tint to the background
24173      * drawable, if specified.
24174      *
24175      * @return the blending mode used to apply the tint to the background
24176      *         drawable
24177      * @attr ref android.R.styleable#View_backgroundTintMode
24178      * @see #setBackgroundTintBlendMode(BlendMode)
24179      *
24180      */
24181     @Nullable
24182     @InspectableProperty
getBackgroundTintMode()24183     public PorterDuff.Mode getBackgroundTintMode() {
24184         PorterDuff.Mode porterDuffMode;
24185         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
24186             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
24187         } else {
24188             porterDuffMode = null;
24189         }
24190         return porterDuffMode;
24191     }
24192 
24193     /**
24194      * Return the blending mode used to apply the tint to the background
24195      * drawable, if specified.
24196      *
24197      * @return the blending mode used to apply the tint to the background
24198      *         drawable, null if no blend has previously been configured
24199      * @attr ref android.R.styleable#View_backgroundTintMode
24200      * @see #setBackgroundTintBlendMode(BlendMode)
24201      */
getBackgroundTintBlendMode()24202     public @Nullable BlendMode getBackgroundTintBlendMode() {
24203         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
24204     }
24205 
applyBackgroundTint()24206     private void applyBackgroundTint() {
24207         if (mBackground != null && mBackgroundTint != null) {
24208             final TintInfo tintInfo = mBackgroundTint;
24209             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
24210                 mBackground = mBackground.mutate();
24211 
24212                 if (tintInfo.mHasTintList) {
24213                     mBackground.setTintList(tintInfo.mTintList);
24214                 }
24215 
24216                 if (tintInfo.mHasTintMode) {
24217                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
24218                 }
24219 
24220                 // The drawable (or one of its children) may not have been
24221                 // stateful before applying the tint, so let's try again.
24222                 if (mBackground.isStateful()) {
24223                     mBackground.setState(getDrawableState());
24224                 }
24225             }
24226         }
24227     }
24228 
24229     /**
24230      * Returns the drawable used as the foreground of this View. The
24231      * foreground drawable, if non-null, is always drawn on top of the view's content.
24232      *
24233      * @return a Drawable or null if no foreground was set
24234      *
24235      * @see #onDrawForeground(Canvas)
24236      */
24237     @InspectableProperty
getForeground()24238     public Drawable getForeground() {
24239         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24240     }
24241 
24242     /**
24243      * Supply a Drawable that is to be rendered on top of all of the content in the view.
24244      *
24245      * @param foreground the Drawable to be drawn on top of the children
24246      *
24247      * @attr ref android.R.styleable#View_foreground
24248      */
setForeground(Drawable foreground)24249     public void setForeground(Drawable foreground) {
24250         if (mForegroundInfo == null) {
24251             if (foreground == null) {
24252                 // Nothing to do.
24253                 return;
24254             }
24255             mForegroundInfo = new ForegroundInfo();
24256         }
24257 
24258         if (foreground == mForegroundInfo.mDrawable) {
24259             // Nothing to do
24260             return;
24261         }
24262 
24263         if (mForegroundInfo.mDrawable != null) {
24264             if (isAttachedToWindow()) {
24265                 mForegroundInfo.mDrawable.setVisible(false, false);
24266             }
24267             mForegroundInfo.mDrawable.setCallback(null);
24268             unscheduleDrawable(mForegroundInfo.mDrawable);
24269         }
24270 
24271         mForegroundInfo.mDrawable = foreground;
24272         mForegroundInfo.mBoundsChanged = true;
24273         if (foreground != null) {
24274             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24275                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24276             }
24277             foreground.setLayoutDirection(getLayoutDirection());
24278             if (foreground.isStateful()) {
24279                 foreground.setState(getDrawableState());
24280             }
24281             applyForegroundTint();
24282             if (isAttachedToWindow()) {
24283                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24284             }
24285             // Set callback last, since the view may still be initializing.
24286             foreground.setCallback(this);
24287         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
24288                 && (mDefaultFocusHighlight == null)) {
24289             mPrivateFlags |= PFLAG_SKIP_DRAW;
24290         }
24291         requestLayout();
24292         invalidate();
24293     }
24294 
24295     /**
24296      * Magic bit used to support features of framework-internal window decor implementation details.
24297      * This used to live exclusively in FrameLayout.
24298      *
24299      * @return true if the foreground should draw inside the padding region or false
24300      *         if it should draw inset by the view's padding
24301      * @hide internal use only; only used by FrameLayout and internal screen layouts.
24302      */
isForegroundInsidePadding()24303     public boolean isForegroundInsidePadding() {
24304         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
24305     }
24306 
24307     /**
24308      * Describes how the foreground is positioned.
24309      *
24310      * @return foreground gravity.
24311      *
24312      * @see #setForegroundGravity(int)
24313      *
24314      * @attr ref android.R.styleable#View_foregroundGravity
24315      */
24316     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()24317     public int getForegroundGravity() {
24318         return mForegroundInfo != null ? mForegroundInfo.mGravity
24319                 : Gravity.START | Gravity.TOP;
24320     }
24321 
24322     /**
24323      * Describes how the foreground is positioned. Defaults to START and TOP.
24324      *
24325      * @param gravity see {@link android.view.Gravity}
24326      *
24327      * @see #getForegroundGravity()
24328      *
24329      * @attr ref android.R.styleable#View_foregroundGravity
24330      */
setForegroundGravity(int gravity)24331     public void setForegroundGravity(int gravity) {
24332         if (mForegroundInfo == null) {
24333             mForegroundInfo = new ForegroundInfo();
24334         }
24335 
24336         if (mForegroundInfo.mGravity != gravity) {
24337             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
24338                 gravity |= Gravity.START;
24339             }
24340 
24341             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
24342                 gravity |= Gravity.TOP;
24343             }
24344 
24345             mForegroundInfo.mGravity = gravity;
24346             requestLayout();
24347         }
24348     }
24349 
24350     /**
24351      * Applies a tint to the foreground drawable. Does not modify the current tint
24352      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
24353      * <p>
24354      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
24355      * mutate the drawable and apply the specified tint and tint mode using
24356      * {@link Drawable#setTintList(ColorStateList)}.
24357      *
24358      * @param tint the tint to apply, may be {@code null} to clear tint
24359      *
24360      * @attr ref android.R.styleable#View_foregroundTint
24361      * @see #getForegroundTintList()
24362      * @see Drawable#setTintList(ColorStateList)
24363      */
24364     @RemotableViewMethod
setForegroundTintList(@ullable ColorStateList tint)24365     public void setForegroundTintList(@Nullable ColorStateList tint) {
24366         if (mForegroundInfo == null) {
24367             mForegroundInfo = new ForegroundInfo();
24368         }
24369         if (mForegroundInfo.mTintInfo == null) {
24370             mForegroundInfo.mTintInfo = new TintInfo();
24371         }
24372         mForegroundInfo.mTintInfo.mTintList = tint;
24373         mForegroundInfo.mTintInfo.mHasTintList = true;
24374 
24375         applyForegroundTint();
24376     }
24377 
24378     /**
24379      * Return the tint applied to the foreground drawable, if specified.
24380      *
24381      * @return the tint applied to the foreground drawable
24382      * @attr ref android.R.styleable#View_foregroundTint
24383      * @see #setForegroundTintList(ColorStateList)
24384      */
24385     @InspectableProperty(name = "foregroundTint")
24386     @Nullable
getForegroundTintList()24387     public ColorStateList getForegroundTintList() {
24388         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24389                 ? mForegroundInfo.mTintInfo.mTintList : null;
24390     }
24391 
24392     /**
24393      * Specifies the blending mode used to apply the tint specified by
24394      * {@link #setForegroundTintList(ColorStateList)}} to the background
24395      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
24396      *
24397      * @param tintMode the blending mode used to apply the tint, may be
24398      *                 {@code null} to clear tint
24399      * @attr ref android.R.styleable#View_foregroundTintMode
24400      * @see #getForegroundTintMode()
24401      * @see Drawable#setTintMode(PorterDuff.Mode)
24402      *
24403      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)24404     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
24405         BlendMode mode = null;
24406         if (tintMode != null) {
24407             mode = BlendMode.fromValue(tintMode.nativeInt);
24408         }
24409         setForegroundTintBlendMode(mode);
24410     }
24411 
24412     /**
24413      * Specifies the blending mode used to apply the tint specified by
24414      * {@link #setForegroundTintList(ColorStateList)}} to the background
24415      * drawable. The default mode is {@link BlendMode#SRC_IN}.
24416      *
24417      * @param blendMode the blending mode used to apply the tint, may be
24418      *                 {@code null} to clear tint
24419      * @attr ref android.R.styleable#View_foregroundTintMode
24420      * @see #getForegroundTintMode()
24421      * @see Drawable#setTintBlendMode(BlendMode)
24422      */
24423     @RemotableViewMethod
setForegroundTintBlendMode(@ullable BlendMode blendMode)24424     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
24425         if (mForegroundInfo == null) {
24426             mForegroundInfo = new ForegroundInfo();
24427         }
24428         if (mForegroundInfo.mTintInfo == null) {
24429             mForegroundInfo.mTintInfo = new TintInfo();
24430         }
24431         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
24432         mForegroundInfo.mTintInfo.mHasTintMode = true;
24433 
24434         applyForegroundTint();
24435     }
24436 
24437     /**
24438      * Return the blending mode used to apply the tint to the foreground
24439      * drawable, if specified.
24440      *
24441      * @return the blending mode used to apply the tint to the foreground
24442      *         drawable
24443      * @attr ref android.R.styleable#View_foregroundTintMode
24444      * @see #setForegroundTintMode(PorterDuff.Mode)
24445      */
24446     @InspectableProperty
24447     @Nullable
getForegroundTintMode()24448     public PorterDuff.Mode getForegroundTintMode() {
24449         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24450                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
24451         if (blendMode != null) {
24452             return BlendMode.blendModeToPorterDuffMode(blendMode);
24453         } else {
24454             return null;
24455         }
24456     }
24457 
24458     /**
24459      * Return the blending mode used to apply the tint to the foreground
24460      * drawable, if specified.
24461      *
24462      * @return the blending mode used to apply the tint to the foreground
24463      *         drawable
24464      * @attr ref android.R.styleable#View_foregroundTintMode
24465      * @see #setForegroundTintBlendMode(BlendMode)
24466      *
24467      */
getForegroundTintBlendMode()24468     public @Nullable BlendMode getForegroundTintBlendMode() {
24469         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24470                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
24471     }
24472 
applyForegroundTint()24473     private void applyForegroundTint() {
24474         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
24475                 && mForegroundInfo.mTintInfo != null) {
24476             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
24477             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
24478                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
24479 
24480                 if (tintInfo.mHasTintList) {
24481                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
24482                 }
24483 
24484                 if (tintInfo.mHasTintMode) {
24485                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
24486                 }
24487 
24488                 // The drawable (or one of its children) may not have been
24489                 // stateful before applying the tint, so let's try again.
24490                 if (mForegroundInfo.mDrawable.isStateful()) {
24491                     mForegroundInfo.mDrawable.setState(getDrawableState());
24492                 }
24493             }
24494         }
24495     }
24496 
24497     /**
24498      * Get the drawable to be overlayed when a view is autofilled
24499      *
24500      * @return The drawable
24501      *
24502      * @throws IllegalStateException if the drawable could not be found.
24503      */
getAutofilledDrawable()24504     @Nullable private Drawable getAutofilledDrawable() {
24505         if (mAttachInfo == null) {
24506             return null;
24507         }
24508         // Lazily load the isAutofilled drawable.
24509         if (mAttachInfo.mAutofilledDrawable == null) {
24510             Context rootContext = getRootView().getContext();
24511             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
24512             int attributeResourceId = a.getResourceId(0, 0);
24513             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
24514             a.recycle();
24515         }
24516 
24517         return mAttachInfo.mAutofilledDrawable;
24518     }
24519 
24520     /**
24521      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
24522      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
24523      *
24524      * @param canvas The canvas to draw on
24525      */
drawAutofilledHighlight(@onNull Canvas canvas)24526     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
24527         if (isAutofilled() && !hideAutofillHighlight()) {
24528             Drawable autofilledHighlight = getAutofilledDrawable();
24529 
24530             if (autofilledHighlight != null) {
24531                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
24532                 autofilledHighlight.draw(canvas);
24533             }
24534         }
24535     }
24536 
24537     /**
24538      * Draw any foreground content for this view.
24539      *
24540      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
24541      * drawable or other view-specific decorations. The foreground is drawn on top of the
24542      * primary view content.</p>
24543      *
24544      * @param canvas canvas to draw into
24545      */
onDrawForeground(Canvas canvas)24546     public void onDrawForeground(Canvas canvas) {
24547         onDrawScrollIndicators(canvas);
24548         onDrawScrollBars(canvas);
24549 
24550         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24551         if (foreground != null) {
24552             if (mForegroundInfo.mBoundsChanged) {
24553                 mForegroundInfo.mBoundsChanged = false;
24554                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
24555                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
24556 
24557                 if (mForegroundInfo.mInsidePadding) {
24558                     selfBounds.set(0, 0, getWidth(), getHeight());
24559                 } else {
24560                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
24561                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
24562                 }
24563 
24564                 final int ld = getLayoutDirection();
24565                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
24566                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
24567                 foreground.setBounds(overlayBounds);
24568             }
24569 
24570             foreground.draw(canvas);
24571         }
24572     }
24573 
24574     /**
24575      * Sets the padding. The view may add on the space required to display
24576      * the scrollbars, depending on the style and visibility of the scrollbars.
24577      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
24578      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
24579      * from the values set in this call.
24580      *
24581      * @attr ref android.R.styleable#View_padding
24582      * @attr ref android.R.styleable#View_paddingBottom
24583      * @attr ref android.R.styleable#View_paddingLeft
24584      * @attr ref android.R.styleable#View_paddingRight
24585      * @attr ref android.R.styleable#View_paddingTop
24586      * @param left the left padding in pixels
24587      * @param top the top padding in pixels
24588      * @param right the right padding in pixels
24589      * @param bottom the bottom padding in pixels
24590      */
setPadding(int left, int top, int right, int bottom)24591     public void setPadding(int left, int top, int right, int bottom) {
24592         resetResolvedPaddingInternal();
24593 
24594         mUserPaddingStart = UNDEFINED_PADDING;
24595         mUserPaddingEnd = UNDEFINED_PADDING;
24596 
24597         mUserPaddingLeftInitial = left;
24598         mUserPaddingRightInitial = right;
24599 
24600         mLeftPaddingDefined = true;
24601         mRightPaddingDefined = true;
24602 
24603         internalSetPadding(left, top, right, bottom);
24604     }
24605 
24606     /**
24607      * @hide
24608      */
24609     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)24610     protected void internalSetPadding(int left, int top, int right, int bottom) {
24611         mUserPaddingLeft = left;
24612         mUserPaddingRight = right;
24613         mUserPaddingBottom = bottom;
24614 
24615         final int viewFlags = mViewFlags;
24616         boolean changed = false;
24617 
24618         // Common case is there are no scroll bars.
24619         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
24620             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
24621                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
24622                         ? 0 : getVerticalScrollbarWidth();
24623                 switch (mVerticalScrollbarPosition) {
24624                     case SCROLLBAR_POSITION_DEFAULT:
24625                         if (isLayoutRtl()) {
24626                             left += offset;
24627                         } else {
24628                             right += offset;
24629                         }
24630                         break;
24631                     case SCROLLBAR_POSITION_RIGHT:
24632                         right += offset;
24633                         break;
24634                     case SCROLLBAR_POSITION_LEFT:
24635                         left += offset;
24636                         break;
24637                 }
24638             }
24639             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
24640                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
24641                         ? 0 : getHorizontalScrollbarHeight();
24642             }
24643         }
24644 
24645         if (mPaddingLeft != left) {
24646             changed = true;
24647             mPaddingLeft = left;
24648         }
24649         if (mPaddingTop != top) {
24650             changed = true;
24651             mPaddingTop = top;
24652         }
24653         if (mPaddingRight != right) {
24654             changed = true;
24655             mPaddingRight = right;
24656         }
24657         if (mPaddingBottom != bottom) {
24658             changed = true;
24659             mPaddingBottom = bottom;
24660         }
24661 
24662         if (changed) {
24663             requestLayout();
24664             invalidateOutline();
24665         }
24666     }
24667 
24668     /**
24669      * Sets the relative padding. The view may add on the space required to display
24670      * the scrollbars, depending on the style and visibility of the scrollbars.
24671      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
24672      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
24673      * from the values set in this call.
24674      *
24675      * @attr ref android.R.styleable#View_padding
24676      * @attr ref android.R.styleable#View_paddingBottom
24677      * @attr ref android.R.styleable#View_paddingStart
24678      * @attr ref android.R.styleable#View_paddingEnd
24679      * @attr ref android.R.styleable#View_paddingTop
24680      * @param start the start padding in pixels
24681      * @param top the top padding in pixels
24682      * @param end the end padding in pixels
24683      * @param bottom the bottom padding in pixels
24684      */
setPaddingRelative(int start, int top, int end, int bottom)24685     public void setPaddingRelative(int start, int top, int end, int bottom) {
24686         resetResolvedPaddingInternal();
24687 
24688         mUserPaddingStart = start;
24689         mUserPaddingEnd = end;
24690         mLeftPaddingDefined = true;
24691         mRightPaddingDefined = true;
24692 
24693         switch(getLayoutDirection()) {
24694             case LAYOUT_DIRECTION_RTL:
24695                 mUserPaddingLeftInitial = end;
24696                 mUserPaddingRightInitial = start;
24697                 internalSetPadding(end, top, start, bottom);
24698                 break;
24699             case LAYOUT_DIRECTION_LTR:
24700             default:
24701                 mUserPaddingLeftInitial = start;
24702                 mUserPaddingRightInitial = end;
24703                 internalSetPadding(start, top, end, bottom);
24704         }
24705     }
24706 
24707     /**
24708      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
24709      * resource ID of the source layout.
24710      *
24711      * @return The layout resource id if this view was inflated from XML, otherwise
24712      * {@link Resources#ID_NULL}.
24713      */
24714     @LayoutRes
getSourceLayoutResId()24715     public int getSourceLayoutResId() {
24716         return mSourceLayoutId;
24717     }
24718 
24719     /**
24720      * Returns the top padding of this view.
24721      *
24722      * @return the top padding in pixels
24723      */
24724     @InspectableProperty
getPaddingTop()24725     public int getPaddingTop() {
24726         return mPaddingTop;
24727     }
24728 
24729     /**
24730      * Returns the bottom padding of this view. If there are inset and enabled
24731      * scrollbars, this value may include the space required to display the
24732      * scrollbars as well.
24733      *
24734      * @return the bottom padding in pixels
24735      */
24736     @InspectableProperty
getPaddingBottom()24737     public int getPaddingBottom() {
24738         return mPaddingBottom;
24739     }
24740 
24741     /**
24742      * Returns the left padding of this view. If there are inset and enabled
24743      * scrollbars, this value may include the space required to display the
24744      * scrollbars as well.
24745      *
24746      * @return the left padding in pixels
24747      */
24748     @InspectableProperty
getPaddingLeft()24749     public int getPaddingLeft() {
24750         if (!isPaddingResolved()) {
24751             resolvePadding();
24752         }
24753         return mPaddingLeft;
24754     }
24755 
24756     /**
24757      * Returns the start padding of this view depending on its resolved layout direction.
24758      * If there are inset and enabled scrollbars, this value may include the space
24759      * required to display the scrollbars as well.
24760      *
24761      * @return the start padding in pixels
24762      */
getPaddingStart()24763     public int getPaddingStart() {
24764         if (!isPaddingResolved()) {
24765             resolvePadding();
24766         }
24767         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24768                 mPaddingRight : mPaddingLeft;
24769     }
24770 
24771     /**
24772      * Returns the right padding of this view. If there are inset and enabled
24773      * scrollbars, this value may include the space required to display the
24774      * scrollbars as well.
24775      *
24776      * @return the right padding in pixels
24777      */
24778     @InspectableProperty
getPaddingRight()24779     public int getPaddingRight() {
24780         if (!isPaddingResolved()) {
24781             resolvePadding();
24782         }
24783         return mPaddingRight;
24784     }
24785 
24786     /**
24787      * Returns the end padding of this view depending on its resolved layout direction.
24788      * If there are inset and enabled scrollbars, this value may include the space
24789      * required to display the scrollbars as well.
24790      *
24791      * @return the end padding in pixels
24792      */
getPaddingEnd()24793     public int getPaddingEnd() {
24794         if (!isPaddingResolved()) {
24795             resolvePadding();
24796         }
24797         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24798                 mPaddingLeft : mPaddingRight;
24799     }
24800 
24801     /**
24802      * Return if the padding has been set through relative values
24803      * {@link #setPaddingRelative(int, int, int, int)} or through
24804      * @attr ref android.R.styleable#View_paddingStart or
24805      * @attr ref android.R.styleable#View_paddingEnd
24806      *
24807      * @return true if the padding is relative or false if it is not.
24808      */
isPaddingRelative()24809     public boolean isPaddingRelative() {
24810         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
24811     }
24812 
computeOpticalInsets()24813     Insets computeOpticalInsets() {
24814         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
24815     }
24816 
24817     /**
24818      * @hide
24819      */
24820     @UnsupportedAppUsage
resetPaddingToInitialValues()24821     public void resetPaddingToInitialValues() {
24822         if (isRtlCompatibilityMode()) {
24823             mPaddingLeft = mUserPaddingLeftInitial;
24824             mPaddingRight = mUserPaddingRightInitial;
24825             return;
24826         }
24827         if (isLayoutRtl()) {
24828             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
24829             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
24830         } else {
24831             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
24832             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
24833         }
24834     }
24835 
24836     /**
24837      * @hide
24838      */
getOpticalInsets()24839     public Insets getOpticalInsets() {
24840         if (mLayoutInsets == null) {
24841             mLayoutInsets = computeOpticalInsets();
24842         }
24843         return mLayoutInsets;
24844     }
24845 
24846     /**
24847      * Set this view's optical insets.
24848      *
24849      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
24850      * property. Views that compute their own optical insets should call it as part of measurement.
24851      * This method does not request layout. If you are setting optical insets outside of
24852      * measure/layout itself you will want to call requestLayout() yourself.
24853      * </p>
24854      * @hide
24855      */
setOpticalInsets(Insets insets)24856     public void setOpticalInsets(Insets insets) {
24857         mLayoutInsets = insets;
24858     }
24859 
24860     /**
24861      * Changes the selection state of this view. A view can be selected or not.
24862      * Note that selection is not the same as focus. Views are typically
24863      * selected in the context of an AdapterView like ListView or GridView;
24864      * the selected view is the view that is highlighted.
24865      *
24866      * @param selected true if the view must be selected, false otherwise
24867      */
setSelected(boolean selected)24868     public void setSelected(boolean selected) {
24869         //noinspection DoubleNegation
24870         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
24871             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
24872             if (!selected) resetPressedState();
24873             invalidate(true);
24874             refreshDrawableState();
24875             dispatchSetSelected(selected);
24876             if (selected) {
24877                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
24878             } else {
24879                 notifyViewAccessibilityStateChangedIfNeeded(
24880                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
24881             }
24882         }
24883     }
24884 
24885     /**
24886      * Dispatch setSelected to all of this View's children.
24887      *
24888      * @see #setSelected(boolean)
24889      *
24890      * @param selected The new selected state
24891      */
dispatchSetSelected(boolean selected)24892     protected void dispatchSetSelected(boolean selected) {
24893     }
24894 
24895     /**
24896      * Indicates the selection state of this view.
24897      *
24898      * @return true if the view is selected, false otherwise
24899      */
24900     @ViewDebug.ExportedProperty
24901     @InspectableProperty(hasAttributeId = false)
isSelected()24902     public boolean isSelected() {
24903         return (mPrivateFlags & PFLAG_SELECTED) != 0;
24904     }
24905 
24906     /**
24907      * Changes the activated state of this view. A view can be activated or not.
24908      * Note that activation is not the same as selection.  Selection is
24909      * a transient property, representing the view (hierarchy) the user is
24910      * currently interacting with.  Activation is a longer-term state that the
24911      * user can move views in and out of.  For example, in a list view with
24912      * single or multiple selection enabled, the views in the current selection
24913      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
24914      * here.)  The activated state is propagated down to children of the view it
24915      * is set on.
24916      *
24917      * @param activated true if the view must be activated, false otherwise
24918      */
setActivated(boolean activated)24919     public void setActivated(boolean activated) {
24920         //noinspection DoubleNegation
24921         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
24922             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
24923             invalidate(true);
24924             refreshDrawableState();
24925             dispatchSetActivated(activated);
24926         }
24927     }
24928 
24929     /**
24930      * Dispatch setActivated to all of this View's children.
24931      *
24932      * @see #setActivated(boolean)
24933      *
24934      * @param activated The new activated state
24935      */
dispatchSetActivated(boolean activated)24936     protected void dispatchSetActivated(boolean activated) {
24937     }
24938 
24939     /**
24940      * Indicates the activation state of this view.
24941      *
24942      * @return true if the view is activated, false otherwise
24943      */
24944     @ViewDebug.ExportedProperty
24945     @InspectableProperty(hasAttributeId = false)
isActivated()24946     public boolean isActivated() {
24947         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
24948     }
24949 
24950     /**
24951      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
24952      * observer can be used to get notifications when global events, like
24953      * layout, happen.
24954      *
24955      * The returned ViewTreeObserver observer is not guaranteed to remain
24956      * valid for the lifetime of this View. If the caller of this method keeps
24957      * a long-lived reference to ViewTreeObserver, it should always check for
24958      * the return value of {@link ViewTreeObserver#isAlive()}.
24959      *
24960      * @return The ViewTreeObserver for this view's hierarchy.
24961      */
getViewTreeObserver()24962     public ViewTreeObserver getViewTreeObserver() {
24963         if (mAttachInfo != null) {
24964             return mAttachInfo.mTreeObserver;
24965         }
24966         if (mFloatingTreeObserver == null) {
24967             mFloatingTreeObserver = new ViewTreeObserver(mContext);
24968         }
24969         return mFloatingTreeObserver;
24970     }
24971 
24972     /**
24973      * <p>Finds the topmost view in the current view hierarchy.</p>
24974      *
24975      * @return the topmost view containing this view
24976      */
getRootView()24977     public View getRootView() {
24978         if (mAttachInfo != null) {
24979             final View v = mAttachInfo.mRootView;
24980             if (v != null) {
24981                 return v;
24982             }
24983         }
24984 
24985         View parent = this;
24986 
24987         while (parent.mParent != null && parent.mParent instanceof View) {
24988             parent = (View) parent.mParent;
24989         }
24990 
24991         return parent;
24992     }
24993 
24994     /**
24995      * Transforms a motion event from view-local coordinates to on-screen
24996      * coordinates.
24997      *
24998      * @param ev the view-local motion event
24999      * @return false if the transformation could not be applied
25000      * @hide
25001      */
25002     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toGlobalMotionEvent(MotionEvent ev)25003     public boolean toGlobalMotionEvent(MotionEvent ev) {
25004         final AttachInfo info = mAttachInfo;
25005         if (info == null) {
25006             return false;
25007         }
25008 
25009         final Matrix m = info.mTmpMatrix;
25010         m.set(Matrix.IDENTITY_MATRIX);
25011         transformMatrixToGlobal(m);
25012         ev.transform(m);
25013         return true;
25014     }
25015 
25016     /**
25017      * Transforms a motion event from on-screen coordinates to view-local
25018      * coordinates.
25019      *
25020      * @param ev the on-screen motion event
25021      * @return false if the transformation could not be applied
25022      * @hide
25023      */
25024     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toLocalMotionEvent(MotionEvent ev)25025     public boolean toLocalMotionEvent(MotionEvent ev) {
25026         final AttachInfo info = mAttachInfo;
25027         if (info == null) {
25028             return false;
25029         }
25030 
25031         final Matrix m = info.mTmpMatrix;
25032         m.set(Matrix.IDENTITY_MATRIX);
25033         transformMatrixToLocal(m);
25034         ev.transform(m);
25035         return true;
25036     }
25037 
25038     /**
25039      * Modifies the input matrix such that it maps view-local coordinates to
25040      * on-screen coordinates.
25041      *
25042      * @param matrix input matrix to modify
25043      */
transformMatrixToGlobal(@onNull Matrix matrix)25044     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
25045         final ViewParent parent = mParent;
25046         if (parent instanceof View) {
25047             final View vp = (View) parent;
25048             vp.transformMatrixToGlobal(matrix);
25049             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
25050         } else if (parent instanceof ViewRootImpl) {
25051             final ViewRootImpl vr = (ViewRootImpl) parent;
25052             vr.transformMatrixToGlobal(matrix);
25053             matrix.preTranslate(0, -vr.mCurScrollY);
25054         }
25055 
25056         matrix.preTranslate(mLeft, mTop);
25057 
25058         if (!hasIdentityMatrix()) {
25059             matrix.preConcat(getMatrix());
25060         }
25061     }
25062 
25063     /**
25064      * Modifies the input matrix such that it maps on-screen coordinates to
25065      * view-local coordinates.
25066      *
25067      * @param matrix input matrix to modify
25068      */
transformMatrixToLocal(@onNull Matrix matrix)25069     public void transformMatrixToLocal(@NonNull Matrix matrix) {
25070         final ViewParent parent = mParent;
25071         if (parent instanceof View) {
25072             final View vp = (View) parent;
25073             vp.transformMatrixToLocal(matrix);
25074             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
25075         } else if (parent instanceof ViewRootImpl) {
25076             final ViewRootImpl vr = (ViewRootImpl) parent;
25077             vr.transformMatrixToLocal(matrix);
25078             matrix.postTranslate(0, vr.mCurScrollY);
25079         }
25080 
25081         matrix.postTranslate(-mLeft, -mTop);
25082 
25083         if (!hasIdentityMatrix()) {
25084             matrix.postConcat(getInverseMatrix());
25085         }
25086     }
25087 
25088     /**
25089      * @hide
25090      */
25091     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
25092             @ViewDebug.IntToString(from = 0, to = "x"),
25093             @ViewDebug.IntToString(from = 1, to = "y")
25094     })
25095     @UnsupportedAppUsage
getLocationOnScreen()25096     public int[] getLocationOnScreen() {
25097         int[] location = new int[2];
25098         getLocationOnScreen(location);
25099         return location;
25100     }
25101 
25102     /**
25103      * <p>Computes the coordinates of this view on the screen. The argument
25104      * must be an array of two integers. After the method returns, the array
25105      * contains the x and y location in that order.</p>
25106      *
25107      * @param outLocation an array of two integers in which to hold the coordinates
25108      */
getLocationOnScreen(@ize2) int[] outLocation)25109     public void getLocationOnScreen(@Size(2) int[] outLocation) {
25110         getLocationInWindow(outLocation);
25111 
25112         final AttachInfo info = mAttachInfo;
25113         if (info != null) {
25114             outLocation[0] += info.mWindowLeft;
25115             outLocation[1] += info.mWindowTop;
25116         }
25117     }
25118 
25119     /**
25120      * <p>Computes the coordinates of this view in its window. The argument
25121      * must be an array of two integers. After the method returns, the array
25122      * contains the x and y location in that order.</p>
25123      *
25124      * @param outLocation an array of two integers in which to hold the coordinates
25125      */
getLocationInWindow(@ize2) int[] outLocation)25126     public void getLocationInWindow(@Size(2) int[] outLocation) {
25127         if (outLocation == null || outLocation.length < 2) {
25128             throw new IllegalArgumentException("outLocation must be an array of two integers");
25129         }
25130 
25131         outLocation[0] = 0;
25132         outLocation[1] = 0;
25133 
25134         transformFromViewToWindowSpace(outLocation);
25135     }
25136 
25137     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)25138     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
25139         if (inOutLocation == null || inOutLocation.length < 2) {
25140             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
25141         }
25142 
25143         if (mAttachInfo == null) {
25144             // When the view is not attached to a window, this method does not make sense
25145             inOutLocation[0] = inOutLocation[1] = 0;
25146             return;
25147         }
25148 
25149         float position[] = mAttachInfo.mTmpTransformLocation;
25150         position[0] = inOutLocation[0];
25151         position[1] = inOutLocation[1];
25152 
25153         if (!hasIdentityMatrix()) {
25154             getMatrix().mapPoints(position);
25155         }
25156 
25157         position[0] += mLeft;
25158         position[1] += mTop;
25159 
25160         ViewParent viewParent = mParent;
25161         while (viewParent instanceof View) {
25162             final View view = (View) viewParent;
25163 
25164             position[0] -= view.mScrollX;
25165             position[1] -= view.mScrollY;
25166 
25167             if (!view.hasIdentityMatrix()) {
25168                 view.getMatrix().mapPoints(position);
25169             }
25170 
25171             position[0] += view.mLeft;
25172             position[1] += view.mTop;
25173 
25174             viewParent = view.mParent;
25175          }
25176 
25177         if (viewParent instanceof ViewRootImpl) {
25178             // *cough*
25179             final ViewRootImpl vr = (ViewRootImpl) viewParent;
25180             position[1] -= vr.mCurScrollY;
25181         }
25182 
25183         inOutLocation[0] = Math.round(position[0]);
25184         inOutLocation[1] = Math.round(position[1]);
25185     }
25186 
25187     /**
25188      * @param id the id of the view to be found
25189      * @return the view of the specified id, null if cannot be found
25190      * @hide
25191      */
findViewTraversal(@dRes int id)25192     protected <T extends View> T findViewTraversal(@IdRes int id) {
25193         if (id == mID) {
25194             return (T) this;
25195         }
25196         return null;
25197     }
25198 
25199     /**
25200      * @param tag the tag of the view to be found
25201      * @return the view of specified tag, null if cannot be found
25202      * @hide
25203      */
findViewWithTagTraversal(Object tag)25204     protected <T extends View> T findViewWithTagTraversal(Object tag) {
25205         if (tag != null && tag.equals(mTag)) {
25206             return (T) this;
25207         }
25208         return null;
25209     }
25210 
25211     /**
25212      * @param predicate The predicate to evaluate.
25213      * @param childToSkip If not null, ignores this child during the recursive traversal.
25214      * @return The first view that matches the predicate or null.
25215      * @hide
25216      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)25217     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
25218             View childToSkip) {
25219         if (predicate.test(this)) {
25220             return (T) this;
25221         }
25222         return null;
25223     }
25224 
25225     /**
25226      * Finds the first descendant view with the given ID, the view itself if
25227      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
25228      * (< 0) or there is no matching view in the hierarchy.
25229      * <p>
25230      * <strong>Note:</strong> In most cases -- depending on compiler support --
25231      * the resulting view is automatically cast to the target class type. If
25232      * the target class type is unconstrained, an explicit cast may be
25233      * necessary.
25234      *
25235      * @param id the ID to search for
25236      * @return a view with given ID if found, or {@code null} otherwise
25237      * @see View#requireViewById(int)
25238      */
25239     @Nullable
findViewById(@dRes int id)25240     public final <T extends View> T findViewById(@IdRes int id) {
25241         if (id == NO_ID) {
25242             return null;
25243         }
25244         return findViewTraversal(id);
25245     }
25246 
25247     /**
25248      * Finds the first descendant view with the given ID, the view itself if the ID matches
25249      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
25250      * matching view in the hierarchy.
25251      * <p>
25252      * <strong>Note:</strong> In most cases -- depending on compiler support --
25253      * the resulting view is automatically cast to the target class type. If
25254      * the target class type is unconstrained, an explicit cast may be
25255      * necessary.
25256      *
25257      * @param id the ID to search for
25258      * @return a view with given ID
25259      * @see View#findViewById(int)
25260      */
25261     @NonNull
requireViewById(@dRes int id)25262     public final <T extends View> T requireViewById(@IdRes int id) {
25263         T view = findViewById(id);
25264         if (view == null) {
25265             throw new IllegalArgumentException("ID does not reference a View inside this View");
25266         }
25267         return view;
25268     }
25269 
25270     /**
25271      * Performs the traversal to find a view by its unique and stable accessibility id.
25272      *
25273      * <strong>Note:</strong>This method does not stop at the root namespace
25274      * boundary since the user can touch the screen at an arbitrary location
25275      * potentially crossing the root namespace boundary which will send an
25276      * accessibility event to accessibility services and they should be able
25277      * to obtain the event source. Also accessibility ids are guaranteed to be
25278      * unique in the window.
25279      *
25280      * @param accessibilityId The accessibility id.
25281      * @return The found view.
25282      * @hide
25283      */
findViewByAccessibilityIdTraversal(int accessibilityId)25284     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
25285         if (getAccessibilityViewId() == accessibilityId) {
25286             return (T) this;
25287         }
25288         return null;
25289     }
25290 
25291     /**
25292      * Performs the traversal to find a view by its autofill id.
25293      *
25294      * <strong>Note:</strong>This method does not stop at the root namespace
25295      * boundary.
25296      *
25297      * @param autofillId The autofill id.
25298      * @return The found view.
25299      * @hide
25300      */
findViewByAutofillIdTraversal(int autofillId)25301     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
25302         if (getAutofillViewId() == autofillId) {
25303             return (T) this;
25304         }
25305         return null;
25306     }
25307 
25308     /**
25309      * Look for a child view with the given tag.  If this view has the given
25310      * tag, return this view.
25311      *
25312      * @param tag The tag to search for, using "tag.equals(getTag())".
25313      * @return The View that has the given tag in the hierarchy or null
25314      */
findViewWithTag(Object tag)25315     public final <T extends View> T findViewWithTag(Object tag) {
25316         if (tag == null) {
25317             return null;
25318         }
25319         return findViewWithTagTraversal(tag);
25320     }
25321 
25322     /**
25323      * Look for a child view that matches the specified predicate.
25324      * If this view matches the predicate, return this view.
25325      *
25326      * @param predicate The predicate to evaluate.
25327      * @return The first view that matches the predicate or null.
25328      * @hide
25329      */
findViewByPredicate(Predicate<View> predicate)25330     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
25331         return findViewByPredicateTraversal(predicate, null);
25332     }
25333 
25334     /**
25335      * Look for a child view that matches the specified predicate,
25336      * starting with the specified view and its descendents and then
25337      * recusively searching the ancestors and siblings of that view
25338      * until this view is reached.
25339      *
25340      * This method is useful in cases where the predicate does not match
25341      * a single unique view (perhaps multiple views use the same id)
25342      * and we are trying to find the view that is "closest" in scope to the
25343      * starting view.
25344      *
25345      * @param start The view to start from.
25346      * @param predicate The predicate to evaluate.
25347      * @return The first view that matches the predicate or null.
25348      * @hide
25349      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)25350     public final <T extends View> T findViewByPredicateInsideOut(
25351             View start, Predicate<View> predicate) {
25352         View childToSkip = null;
25353         for (;;) {
25354             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
25355             if (view != null || start == this) {
25356                 return view;
25357             }
25358 
25359             ViewParent parent = start.getParent();
25360             if (parent == null || !(parent instanceof View)) {
25361                 return null;
25362             }
25363 
25364             childToSkip = start;
25365             start = (View) parent;
25366         }
25367     }
25368 
25369     /**
25370      * Sets the identifier for this view. The identifier does not have to be
25371      * unique in this view's hierarchy. The identifier should be a positive
25372      * number.
25373      *
25374      * @see #NO_ID
25375      * @see #getId()
25376      * @see #findViewById(int)
25377      *
25378      * @param id a number used to identify the view
25379      *
25380      * @attr ref android.R.styleable#View_id
25381      */
setId(@dRes int id)25382     public void setId(@IdRes int id) {
25383         mID = id;
25384         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
25385             mID = generateViewId();
25386         }
25387     }
25388 
25389     /**
25390      * {@hide}
25391      *
25392      * @param isRoot true if the view belongs to the root namespace, false
25393      *        otherwise
25394      */
25395     @UnsupportedAppUsage
25396     @TestApi
setIsRootNamespace(boolean isRoot)25397     public void setIsRootNamespace(boolean isRoot) {
25398         if (isRoot) {
25399             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
25400         } else {
25401             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
25402         }
25403     }
25404 
25405     /**
25406      * {@hide}
25407      *
25408      * @return true if the view belongs to the root namespace, false otherwise
25409      */
25410     @UnsupportedAppUsage
isRootNamespace()25411     public boolean isRootNamespace() {
25412         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
25413     }
25414 
25415     /**
25416      * Returns this view's identifier.
25417      *
25418      * @return a positive integer used to identify the view or {@link #NO_ID}
25419      *         if the view has no ID
25420      *
25421      * @see #setId(int)
25422      * @see #findViewById(int)
25423      * @attr ref android.R.styleable#View_id
25424      */
25425     @IdRes
25426     @ViewDebug.CapturedViewProperty
25427     @InspectableProperty
getId()25428     public int getId() {
25429         return mID;
25430     }
25431 
25432     /**
25433      * Get the identifier used for this view by the drawing system.
25434      *
25435      * @see RenderNode#getUniqueId()
25436      * @return A long that uniquely identifies this view's drawing component
25437      */
getUniqueDrawingId()25438     public long getUniqueDrawingId() {
25439         return mRenderNode.getUniqueId();
25440     }
25441 
25442     /**
25443      * Returns this view's tag.
25444      *
25445      * @return the Object stored in this view as a tag, or {@code null} if not
25446      *         set
25447      *
25448      * @see #setTag(Object)
25449      * @see #getTag(int)
25450      */
25451     @ViewDebug.ExportedProperty
25452     @InspectableProperty
getTag()25453     public Object getTag() {
25454         return mTag;
25455     }
25456 
25457     /**
25458      * Sets the tag associated with this view. A tag can be used to mark
25459      * a view in its hierarchy and does not have to be unique within the
25460      * hierarchy. Tags can also be used to store data within a view without
25461      * resorting to another data structure.
25462      *
25463      * @param tag an Object to tag the view with
25464      *
25465      * @see #getTag()
25466      * @see #setTag(int, Object)
25467      */
setTag(final Object tag)25468     public void setTag(final Object tag) {
25469         mTag = tag;
25470     }
25471 
25472     /**
25473      * Returns the tag associated with this view and the specified key.
25474      *
25475      * @param key The key identifying the tag
25476      *
25477      * @return the Object stored in this view as a tag, or {@code null} if not
25478      *         set
25479      *
25480      * @see #setTag(int, Object)
25481      * @see #getTag()
25482      */
getTag(int key)25483     public Object getTag(int key) {
25484         if (mKeyedTags != null) return mKeyedTags.get(key);
25485         return null;
25486     }
25487 
25488     /**
25489      * Sets a tag associated with this view and a key. A tag can be used
25490      * to mark a view in its hierarchy and does not have to be unique within
25491      * the hierarchy. Tags can also be used to store data within a view
25492      * without resorting to another data structure.
25493      *
25494      * The specified key should be an id declared in the resources of the
25495      * application to ensure it is unique (see the <a
25496      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
25497      * Keys identified as belonging to
25498      * the Android framework or not associated with any package will cause
25499      * an {@link IllegalArgumentException} to be thrown.
25500      *
25501      * @param key The key identifying the tag
25502      * @param tag An Object to tag the view with
25503      *
25504      * @throws IllegalArgumentException If they specified key is not valid
25505      *
25506      * @see #setTag(Object)
25507      * @see #getTag(int)
25508      */
setTag(int key, final Object tag)25509     public void setTag(int key, final Object tag) {
25510         // If the package id is 0x00 or 0x01, it's either an undefined package
25511         // or a framework id
25512         if ((key >>> 24) < 2) {
25513             throw new IllegalArgumentException("The key must be an application-specific "
25514                     + "resource id.");
25515         }
25516 
25517         setKeyedTag(key, tag);
25518     }
25519 
25520     /**
25521      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
25522      * framework id.
25523      *
25524      * @hide
25525      */
25526     @UnsupportedAppUsage
setTagInternal(int key, Object tag)25527     public void setTagInternal(int key, Object tag) {
25528         if ((key >>> 24) != 0x1) {
25529             throw new IllegalArgumentException("The key must be a framework-specific "
25530                     + "resource id.");
25531         }
25532 
25533         setKeyedTag(key, tag);
25534     }
25535 
setKeyedTag(int key, Object tag)25536     private void setKeyedTag(int key, Object tag) {
25537         if (mKeyedTags == null) {
25538             mKeyedTags = new SparseArray<Object>(2);
25539         }
25540 
25541         mKeyedTags.put(key, tag);
25542     }
25543 
25544     /**
25545      * Prints information about this view in the log output, with the tag
25546      * {@link #VIEW_LOG_TAG}.
25547      *
25548      * @hide
25549      */
25550     @UnsupportedAppUsage
debug()25551     public void debug() {
25552         debug(0);
25553     }
25554 
25555     /**
25556      * Prints information about this view in the log output, with the tag
25557      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
25558      * indentation defined by the <code>depth</code>.
25559      *
25560      * @param depth the indentation level
25561      *
25562      * @hide
25563      */
25564     @UnsupportedAppUsage
debug(int depth)25565     protected void debug(int depth) {
25566         String output = debugIndent(depth - 1);
25567 
25568         output += "+ " + this;
25569         int id = getId();
25570         if (id != -1) {
25571             output += " (id=" + id + ")";
25572         }
25573         Object tag = getTag();
25574         if (tag != null) {
25575             output += " (tag=" + tag + ")";
25576         }
25577         Log.d(VIEW_LOG_TAG, output);
25578 
25579         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
25580             output = debugIndent(depth) + " FOCUSED";
25581             Log.d(VIEW_LOG_TAG, output);
25582         }
25583 
25584         output = debugIndent(depth);
25585         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
25586                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
25587                 + "} ";
25588         Log.d(VIEW_LOG_TAG, output);
25589 
25590         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
25591                 || mPaddingBottom != 0) {
25592             output = debugIndent(depth);
25593             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
25594                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
25595             Log.d(VIEW_LOG_TAG, output);
25596         }
25597 
25598         output = debugIndent(depth);
25599         output += "mMeasureWidth=" + mMeasuredWidth +
25600                 " mMeasureHeight=" + mMeasuredHeight;
25601         Log.d(VIEW_LOG_TAG, output);
25602 
25603         output = debugIndent(depth);
25604         if (mLayoutParams == null) {
25605             output += "BAD! no layout params";
25606         } else {
25607             output = mLayoutParams.debug(output);
25608         }
25609         Log.d(VIEW_LOG_TAG, output);
25610 
25611         output = debugIndent(depth);
25612         output += "flags={";
25613         output += View.printFlags(mViewFlags);
25614         output += "}";
25615         Log.d(VIEW_LOG_TAG, output);
25616 
25617         output = debugIndent(depth);
25618         output += "privateFlags={";
25619         output += View.printPrivateFlags(mPrivateFlags);
25620         output += "}";
25621         Log.d(VIEW_LOG_TAG, output);
25622     }
25623 
25624     /**
25625      * Creates a string of whitespaces used for indentation.
25626      *
25627      * @param depth the indentation level
25628      * @return a String containing (depth * 2 + 3) * 2 white spaces
25629      *
25630      * @hide
25631      */
debugIndent(int depth)25632     protected static String debugIndent(int depth) {
25633         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
25634         for (int i = 0; i < (depth * 2) + 3; i++) {
25635             spaces.append(' ').append(' ');
25636         }
25637         return spaces.toString();
25638     }
25639 
25640     /**
25641      * <p>Return the offset of the widget's text baseline from the widget's top
25642      * boundary. If this widget does not support baseline alignment, this
25643      * method returns -1. </p>
25644      *
25645      * @return the offset of the baseline within the widget's bounds or -1
25646      *         if baseline alignment is not supported
25647      */
25648     @ViewDebug.ExportedProperty(category = "layout")
25649     @InspectableProperty
getBaseline()25650     public int getBaseline() {
25651         return -1;
25652     }
25653 
25654     /**
25655      * Returns whether the view hierarchy is currently undergoing a layout pass. This
25656      * information is useful to avoid situations such as calling {@link #requestLayout()} during
25657      * a layout pass.
25658      *
25659      * @return whether the view hierarchy is currently undergoing a layout pass
25660      */
isInLayout()25661     public boolean isInLayout() {
25662         ViewRootImpl viewRoot = getViewRootImpl();
25663         return (viewRoot != null && viewRoot.isInLayout());
25664     }
25665 
25666     /**
25667      * Call this when something has changed which has invalidated the
25668      * layout of this view. This will schedule a layout pass of the view
25669      * tree. This should not be called while the view hierarchy is currently in a layout
25670      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
25671      * end of the current layout pass (and then layout will run again) or after the current
25672      * frame is drawn and the next layout occurs.
25673      *
25674      * <p>Subclasses which override this method should call the superclass method to
25675      * handle possible request-during-layout errors correctly.</p>
25676      */
25677     @CallSuper
requestLayout()25678     public void requestLayout() {
25679         if (mMeasureCache != null) mMeasureCache.clear();
25680 
25681         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
25682             // Only trigger request-during-layout logic if this is the view requesting it,
25683             // not the views in its parent hierarchy
25684             ViewRootImpl viewRoot = getViewRootImpl();
25685             if (viewRoot != null && viewRoot.isInLayout()) {
25686                 if (!viewRoot.requestLayoutDuringLayout(this)) {
25687                     return;
25688                 }
25689             }
25690             mAttachInfo.mViewRequestingLayout = this;
25691         }
25692 
25693         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25694         mPrivateFlags |= PFLAG_INVALIDATED;
25695 
25696         if (mParent != null && !mParent.isLayoutRequested()) {
25697             mParent.requestLayout();
25698         }
25699         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
25700             mAttachInfo.mViewRequestingLayout = null;
25701         }
25702     }
25703 
25704     /**
25705      * Forces this view to be laid out during the next layout pass.
25706      * This method does not call requestLayout() or forceLayout()
25707      * on the parent.
25708      */
forceLayout()25709     public void forceLayout() {
25710         if (mMeasureCache != null) mMeasureCache.clear();
25711 
25712         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25713         mPrivateFlags |= PFLAG_INVALIDATED;
25714     }
25715 
25716     /**
25717      * <p>
25718      * This is called to find out how big a view should be. The parent
25719      * supplies constraint information in the width and height parameters.
25720      * </p>
25721      *
25722      * <p>
25723      * The actual measurement work of a view is performed in
25724      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
25725      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
25726      * </p>
25727      *
25728      *
25729      * @param widthMeasureSpec Horizontal space requirements as imposed by the
25730      *        parent
25731      * @param heightMeasureSpec Vertical space requirements as imposed by the
25732      *        parent
25733      *
25734      * @see #onMeasure(int, int)
25735      */
measure(int widthMeasureSpec, int heightMeasureSpec)25736     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
25737         boolean optical = isLayoutModeOptical(this);
25738         if (optical != isLayoutModeOptical(mParent)) {
25739             Insets insets = getOpticalInsets();
25740             int oWidth  = insets.left + insets.right;
25741             int oHeight = insets.top  + insets.bottom;
25742             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
25743             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
25744         }
25745 
25746         // Suppress sign extension for the low bytes
25747         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
25748         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
25749 
25750         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
25751 
25752         // Optimize layout by avoiding an extra EXACTLY pass when the view is
25753         // already measured as the correct size. In API 23 and below, this
25754         // extra pass is required to make LinearLayout re-distribute weight.
25755         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
25756                 || heightMeasureSpec != mOldHeightMeasureSpec;
25757         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
25758                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
25759         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
25760                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
25761         final boolean needsLayout = specChanged
25762                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
25763 
25764         if (forceLayout || needsLayout) {
25765             // first clears the measured dimension flag
25766             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
25767 
25768             resolveRtlPropertiesIfNeeded();
25769 
25770             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
25771             if (cacheIndex < 0 || sIgnoreMeasureCache) {
25772                 // measure ourselves, this should set the measured dimension flag back
25773                 onMeasure(widthMeasureSpec, heightMeasureSpec);
25774                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25775             } else {
25776                 long value = mMeasureCache.valueAt(cacheIndex);
25777                 // Casting a long to int drops the high 32 bits, no mask needed
25778                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
25779                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25780             }
25781 
25782             // flag not set, setMeasuredDimension() was not invoked, we raise
25783             // an exception to warn the developer
25784             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
25785                 throw new IllegalStateException("View with id " + getId() + ": "
25786                         + getClass().getName() + "#onMeasure() did not set the"
25787                         + " measured dimension by calling"
25788                         + " setMeasuredDimension()");
25789             }
25790 
25791             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
25792         }
25793 
25794         mOldWidthMeasureSpec = widthMeasureSpec;
25795         mOldHeightMeasureSpec = heightMeasureSpec;
25796 
25797         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
25798                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
25799     }
25800 
25801     /**
25802      * <p>
25803      * Measure the view and its content to determine the measured width and the
25804      * measured height. This method is invoked by {@link #measure(int, int)} and
25805      * should be overridden by subclasses to provide accurate and efficient
25806      * measurement of their contents.
25807      * </p>
25808      *
25809      * <p>
25810      * <strong>CONTRACT:</strong> When overriding this method, you
25811      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
25812      * measured width and height of this view. Failure to do so will trigger an
25813      * <code>IllegalStateException</code>, thrown by
25814      * {@link #measure(int, int)}. Calling the superclass'
25815      * {@link #onMeasure(int, int)} is a valid use.
25816      * </p>
25817      *
25818      * <p>
25819      * The base class implementation of measure defaults to the background size,
25820      * unless a larger size is allowed by the MeasureSpec. Subclasses should
25821      * override {@link #onMeasure(int, int)} to provide better measurements of
25822      * their content.
25823      * </p>
25824      *
25825      * <p>
25826      * If this method is overridden, it is the subclass's responsibility to make
25827      * sure the measured height and width are at least the view's minimum height
25828      * and width ({@link #getSuggestedMinimumHeight()} and
25829      * {@link #getSuggestedMinimumWidth()}).
25830      * </p>
25831      *
25832      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
25833      *                         The requirements are encoded with
25834      *                         {@link android.view.View.MeasureSpec}.
25835      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
25836      *                         The requirements are encoded with
25837      *                         {@link android.view.View.MeasureSpec}.
25838      *
25839      * @see #getMeasuredWidth()
25840      * @see #getMeasuredHeight()
25841      * @see #setMeasuredDimension(int, int)
25842      * @see #getSuggestedMinimumHeight()
25843      * @see #getSuggestedMinimumWidth()
25844      * @see android.view.View.MeasureSpec#getMode(int)
25845      * @see android.view.View.MeasureSpec#getSize(int)
25846      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)25847     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
25848         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
25849                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
25850     }
25851 
25852     /**
25853      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
25854      * measured width and measured height. Failing to do so will trigger an
25855      * exception at measurement time.</p>
25856      *
25857      * @param measuredWidth The measured width of this view.  May be a complex
25858      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25859      * {@link #MEASURED_STATE_TOO_SMALL}.
25860      * @param measuredHeight The measured height of this view.  May be a complex
25861      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25862      * {@link #MEASURED_STATE_TOO_SMALL}.
25863      */
setMeasuredDimension(int measuredWidth, int measuredHeight)25864     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
25865         boolean optical = isLayoutModeOptical(this);
25866         if (optical != isLayoutModeOptical(mParent)) {
25867             Insets insets = getOpticalInsets();
25868             int opticalWidth  = insets.left + insets.right;
25869             int opticalHeight = insets.top  + insets.bottom;
25870 
25871             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
25872             measuredHeight += optical ? opticalHeight : -opticalHeight;
25873         }
25874         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
25875     }
25876 
25877     /**
25878      * Sets the measured dimension without extra processing for things like optical bounds.
25879      * Useful for reapplying consistent values that have already been cooked with adjustments
25880      * for optical bounds, etc. such as those from the measurement cache.
25881      *
25882      * @param measuredWidth The measured width of this view.  May be a complex
25883      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25884      * {@link #MEASURED_STATE_TOO_SMALL}.
25885      * @param measuredHeight The measured height of this view.  May be a complex
25886      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25887      * {@link #MEASURED_STATE_TOO_SMALL}.
25888      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)25889     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
25890         mMeasuredWidth = measuredWidth;
25891         mMeasuredHeight = measuredHeight;
25892 
25893         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
25894     }
25895 
25896     /**
25897      * Merge two states as returned by {@link #getMeasuredState()}.
25898      * @param curState The current state as returned from a view or the result
25899      * of combining multiple views.
25900      * @param newState The new view state to combine.
25901      * @return Returns a new integer reflecting the combination of the two
25902      * states.
25903      */
combineMeasuredStates(int curState, int newState)25904     public static int combineMeasuredStates(int curState, int newState) {
25905         return curState | newState;
25906     }
25907 
25908     /**
25909      * Version of {@link #resolveSizeAndState(int, int, int)}
25910      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
25911      */
resolveSize(int size, int measureSpec)25912     public static int resolveSize(int size, int measureSpec) {
25913         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
25914     }
25915 
25916     /**
25917      * Utility to reconcile a desired size and state, with constraints imposed
25918      * by a MeasureSpec. Will take the desired size, unless a different size
25919      * is imposed by the constraints. The returned value is a compound integer,
25920      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
25921      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
25922      * resulting size is smaller than the size the view wants to be.
25923      *
25924      * @param size How big the view wants to be.
25925      * @param measureSpec Constraints imposed by the parent.
25926      * @param childMeasuredState Size information bit mask for the view's
25927      *                           children.
25928      * @return Size information bit mask as defined by
25929      *         {@link #MEASURED_SIZE_MASK} and
25930      *         {@link #MEASURED_STATE_TOO_SMALL}.
25931      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)25932     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
25933         final int specMode = MeasureSpec.getMode(measureSpec);
25934         final int specSize = MeasureSpec.getSize(measureSpec);
25935         final int result;
25936         switch (specMode) {
25937             case MeasureSpec.AT_MOST:
25938                 if (specSize < size) {
25939                     result = specSize | MEASURED_STATE_TOO_SMALL;
25940                 } else {
25941                     result = size;
25942                 }
25943                 break;
25944             case MeasureSpec.EXACTLY:
25945                 result = specSize;
25946                 break;
25947             case MeasureSpec.UNSPECIFIED:
25948             default:
25949                 result = size;
25950         }
25951         return result | (childMeasuredState & MEASURED_STATE_MASK);
25952     }
25953 
25954     /**
25955      * Utility to return a default size. Uses the supplied size if the
25956      * MeasureSpec imposed no constraints. Will get larger if allowed
25957      * by the MeasureSpec.
25958      *
25959      * @param size Default size for this view
25960      * @param measureSpec Constraints imposed by the parent
25961      * @return The size this view should be.
25962      */
getDefaultSize(int size, int measureSpec)25963     public static int getDefaultSize(int size, int measureSpec) {
25964         int result = size;
25965         int specMode = MeasureSpec.getMode(measureSpec);
25966         int specSize = MeasureSpec.getSize(measureSpec);
25967 
25968         switch (specMode) {
25969         case MeasureSpec.UNSPECIFIED:
25970             result = size;
25971             break;
25972         case MeasureSpec.AT_MOST:
25973         case MeasureSpec.EXACTLY:
25974             result = specSize;
25975             break;
25976         }
25977         return result;
25978     }
25979 
25980     /**
25981      * Returns the suggested minimum height that the view should use. This
25982      * returns the maximum of the view's minimum height
25983      * and the background's minimum height
25984      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
25985      * <p>
25986      * When being used in {@link #onMeasure(int, int)}, the caller should still
25987      * ensure the returned height is within the requirements of the parent.
25988      *
25989      * @return The suggested minimum height of the view.
25990      */
getSuggestedMinimumHeight()25991     protected int getSuggestedMinimumHeight() {
25992         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
25993 
25994     }
25995 
25996     /**
25997      * Returns the suggested minimum width that the view should use. This
25998      * returns the maximum of the view's minimum width
25999      * and the background's minimum width
26000      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
26001      * <p>
26002      * When being used in {@link #onMeasure(int, int)}, the caller should still
26003      * ensure the returned width is within the requirements of the parent.
26004      *
26005      * @return The suggested minimum width of the view.
26006      */
getSuggestedMinimumWidth()26007     protected int getSuggestedMinimumWidth() {
26008         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
26009     }
26010 
26011     /**
26012      * Returns the minimum height of the view.
26013      *
26014      * @return the minimum height the view will try to be, in pixels
26015      *
26016      * @see #setMinimumHeight(int)
26017      *
26018      * @attr ref android.R.styleable#View_minHeight
26019      */
26020     @InspectableProperty(name = "minHeight")
getMinimumHeight()26021     public int getMinimumHeight() {
26022         return mMinHeight;
26023     }
26024 
26025     /**
26026      * Sets the minimum height of the view. It is not guaranteed the view will
26027      * be able to achieve this minimum height (for example, if its parent layout
26028      * constrains it with less available height).
26029      *
26030      * @param minHeight The minimum height the view will try to be, in pixels
26031      *
26032      * @see #getMinimumHeight()
26033      *
26034      * @attr ref android.R.styleable#View_minHeight
26035      */
26036     @RemotableViewMethod
setMinimumHeight(int minHeight)26037     public void setMinimumHeight(int minHeight) {
26038         mMinHeight = minHeight;
26039         requestLayout();
26040     }
26041 
26042     /**
26043      * Returns the minimum width of the view.
26044      *
26045      * @return the minimum width the view will try to be, in pixels
26046      *
26047      * @see #setMinimumWidth(int)
26048      *
26049      * @attr ref android.R.styleable#View_minWidth
26050      */
26051     @InspectableProperty(name = "minWidth")
getMinimumWidth()26052     public int getMinimumWidth() {
26053         return mMinWidth;
26054     }
26055 
26056     /**
26057      * Sets the minimum width of the view. It is not guaranteed the view will
26058      * be able to achieve this minimum width (for example, if its parent layout
26059      * constrains it with less available width).
26060      *
26061      * @param minWidth The minimum width the view will try to be, in pixels
26062      *
26063      * @see #getMinimumWidth()
26064      *
26065      * @attr ref android.R.styleable#View_minWidth
26066      */
26067     @RemotableViewMethod
setMinimumWidth(int minWidth)26068     public void setMinimumWidth(int minWidth) {
26069         mMinWidth = minWidth;
26070         requestLayout();
26071 
26072     }
26073 
26074     /**
26075      * Get the animation currently associated with this view.
26076      *
26077      * @return The animation that is currently playing or
26078      *         scheduled to play for this view.
26079      */
getAnimation()26080     public Animation getAnimation() {
26081         return mCurrentAnimation;
26082     }
26083 
26084     /**
26085      * Start the specified animation now.
26086      *
26087      * @param animation the animation to start now
26088      */
startAnimation(Animation animation)26089     public void startAnimation(Animation animation) {
26090         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
26091         setAnimation(animation);
26092         invalidateParentCaches();
26093         invalidate(true);
26094     }
26095 
26096     /**
26097      * Cancels any animations for this view.
26098      */
clearAnimation()26099     public void clearAnimation() {
26100         if (mCurrentAnimation != null) {
26101             mCurrentAnimation.detach();
26102         }
26103         mCurrentAnimation = null;
26104         invalidateParentIfNeeded();
26105     }
26106 
26107     /**
26108      * Sets the next animation to play for this view.
26109      * If you want the animation to play immediately, use
26110      * {@link #startAnimation(android.view.animation.Animation)} instead.
26111      * This method provides allows fine-grained
26112      * control over the start time and invalidation, but you
26113      * must make sure that 1) the animation has a start time set, and
26114      * 2) the view's parent (which controls animations on its children)
26115      * will be invalidated when the animation is supposed to
26116      * start.
26117      *
26118      * @param animation The next animation, or null.
26119      */
setAnimation(Animation animation)26120     public void setAnimation(Animation animation) {
26121         mCurrentAnimation = animation;
26122 
26123         if (animation != null) {
26124             // If the screen is off assume the animation start time is now instead of
26125             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
26126             // would cause the animation to start when the screen turns back on
26127             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
26128                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
26129                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
26130             }
26131             animation.reset();
26132         }
26133     }
26134 
26135     /**
26136      * Invoked by a parent ViewGroup to notify the start of the animation
26137      * currently associated with this view. If you override this method,
26138      * always call super.onAnimationStart();
26139      *
26140      * @see #setAnimation(android.view.animation.Animation)
26141      * @see #getAnimation()
26142      */
26143     @CallSuper
onAnimationStart()26144     protected void onAnimationStart() {
26145         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
26146     }
26147 
26148     /**
26149      * Invoked by a parent ViewGroup to notify the end of the animation
26150      * currently associated with this view. If you override this method,
26151      * always call super.onAnimationEnd();
26152      *
26153      * @see #setAnimation(android.view.animation.Animation)
26154      * @see #getAnimation()
26155      */
26156     @CallSuper
onAnimationEnd()26157     protected void onAnimationEnd() {
26158         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
26159     }
26160 
26161     /**
26162      * Invoked if there is a Transform that involves alpha. Subclass that can
26163      * draw themselves with the specified alpha should return true, and then
26164      * respect that alpha when their onDraw() is called. If this returns false
26165      * then the view may be redirected to draw into an offscreen buffer to
26166      * fulfill the request, which will look fine, but may be slower than if the
26167      * subclass handles it internally. The default implementation returns false.
26168      *
26169      * @param alpha The alpha (0..255) to apply to the view's drawing
26170      * @return true if the view can draw with the specified alpha.
26171      */
onSetAlpha(int alpha)26172     protected boolean onSetAlpha(int alpha) {
26173         return false;
26174     }
26175 
26176     /**
26177      * This is used by the ViewRoot to perform an optimization when
26178      * the view hierarchy contains one or several SurfaceView.
26179      * SurfaceView is always considered transparent, but its children are not,
26180      * therefore all View objects remove themselves from the global transparent
26181      * region (passed as a parameter to this function).
26182      *
26183      * @param region The transparent region for this ViewAncestor (window).
26184      *
26185      * @return Returns true if the effective visibility of the view at this
26186      * point is opaque, regardless of the transparent region; returns false
26187      * if it is possible for underlying windows to be seen behind the view.
26188      *
26189      */
gatherTransparentRegion(@ullable Region region)26190     public boolean gatherTransparentRegion(@Nullable Region region) {
26191         final AttachInfo attachInfo = mAttachInfo;
26192         if (region != null && attachInfo != null) {
26193             final int pflags = mPrivateFlags;
26194             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
26195                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
26196                 // remove it from the transparent region.
26197                 final int[] location = attachInfo.mTransparentLocation;
26198                 getLocationInWindow(location);
26199                 // When a view has Z value, then it will be better to leave some area below the view
26200                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
26201                 // the bottom part needs more offset than the left, top and right parts due to the
26202                 // spot light effects.
26203                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
26204                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
26205                         location[0] + mRight - mLeft + shadowOffset,
26206                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
26207             } else {
26208                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
26209                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
26210                     // the background drawable's non-transparent parts from this transparent region.
26211                     applyDrawableToTransparentRegion(mBackground, region);
26212                 }
26213                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
26214                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
26215                     // Similarly, we remove the foreground drawable's non-transparent parts.
26216                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
26217                 }
26218                 if (mDefaultFocusHighlight != null
26219                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
26220                     // Similarly, we remove the default focus highlight's non-transparent parts.
26221                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
26222                 }
26223             }
26224         }
26225         return true;
26226     }
26227 
26228     /**
26229      * Play a sound effect for this view.
26230      *
26231      * <p>The framework will play sound effects for some built in actions, such as
26232      * clicking, but you may wish to play these effects in your widget,
26233      * for instance, for internal navigation.
26234      *
26235      * <p>The sound effect will only be played if sound effects are enabled by the user, and
26236      * {@link #isSoundEffectsEnabled()} is true.
26237      *
26238      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}.
26239      */
playSoundEffect(@oundEffectConstants.SoundEffect int soundConstant)26240     public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
26241         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
26242             return;
26243         }
26244         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
26245     }
26246 
26247     /**
26248      * BZZZTT!!1!
26249      *
26250      * <p>Provide haptic feedback to the user for this view.
26251      *
26252      * <p>The framework will provide haptic feedback for some built in actions,
26253      * such as long presses, but you may wish to provide feedback for your
26254      * own widget.
26255      *
26256      * <p>The feedback will only be performed if
26257      * {@link #isHapticFeedbackEnabled()} is true.
26258      *
26259      * @param feedbackConstant One of the constants defined in
26260      * {@link HapticFeedbackConstants}
26261      */
performHapticFeedback(int feedbackConstant)26262     public boolean performHapticFeedback(int feedbackConstant) {
26263         return performHapticFeedback(feedbackConstant, 0);
26264     }
26265 
26266     /**
26267      * BZZZTT!!1!
26268      *
26269      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
26270      *
26271      * @param feedbackConstant One of the constants defined in
26272      * {@link HapticFeedbackConstants}
26273      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
26274      */
performHapticFeedback(int feedbackConstant, int flags)26275     public boolean performHapticFeedback(int feedbackConstant, int flags) {
26276         if (mAttachInfo == null) {
26277             return false;
26278         }
26279         //noinspection SimplifiableIfStatement
26280         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
26281                 && !isHapticFeedbackEnabled()) {
26282             return false;
26283         }
26284         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
26285                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
26286     }
26287 
26288     /**
26289      * Request that the visibility of the status bar or other screen/window
26290      * decorations be changed.
26291      *
26292      * <p>This method is used to put the over device UI into temporary modes
26293      * where the user's attention is focused more on the application content,
26294      * by dimming or hiding surrounding system affordances.  This is typically
26295      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
26296      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
26297      * to be placed behind the action bar (and with these flags other system
26298      * affordances) so that smooth transitions between hiding and showing them
26299      * can be done.
26300      *
26301      * <p>Two representative examples of the use of system UI visibility is
26302      * implementing a content browsing application (like a magazine reader)
26303      * and a video playing application.
26304      *
26305      * <p>The first code shows a typical implementation of a View in a content
26306      * browsing application.  In this implementation, the application goes
26307      * into a content-oriented mode by hiding the status bar and action bar,
26308      * and putting the navigation elements into lights out mode.  The user can
26309      * then interact with content while in this mode.  Such an application should
26310      * provide an easy way for the user to toggle out of the mode (such as to
26311      * check information in the status bar or access notifications).  In the
26312      * implementation here, this is done simply by tapping on the content.
26313      *
26314      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
26315      *      content}
26316      *
26317      * <p>This second code sample shows a typical implementation of a View
26318      * in a video playing application.  In this situation, while the video is
26319      * playing the application would like to go into a complete full-screen mode,
26320      * to use as much of the display as possible for the video.  When in this state
26321      * the user can not interact with the application; the system intercepts
26322      * touching on the screen to pop the UI out of full screen mode.  See
26323      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
26324      *
26325      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
26326      *      content}
26327      *
26328      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26329      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
26330      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
26331      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
26332      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
26333      *
26334      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26335      * instead.
26336      */
26337     @Deprecated
setSystemUiVisibility(int visibility)26338     public void setSystemUiVisibility(int visibility) {
26339         if (visibility != mSystemUiVisibility) {
26340             mSystemUiVisibility = visibility;
26341             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
26342                 mParent.recomputeViewAttributes(this);
26343             }
26344         }
26345     }
26346 
26347     /**
26348      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
26349      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26350      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
26351      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
26352      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
26353      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
26354      *
26355      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26356      * instead.
26357      */
26358     @Deprecated
getSystemUiVisibility()26359     public int getSystemUiVisibility() {
26360         return mSystemUiVisibility;
26361     }
26362 
26363     /**
26364      * Returns the current system UI visibility that is currently set for
26365      * the entire window.  This is the combination of the
26366      * {@link #setSystemUiVisibility(int)} values supplied by all of the
26367      * views in the window.
26368      *
26369      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26370      * instead.
26371      */
26372     @Deprecated
getWindowSystemUiVisibility()26373     public int getWindowSystemUiVisibility() {
26374         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
26375     }
26376 
26377     /**
26378      * Override to find out when the window's requested system UI visibility
26379      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
26380      * This is different from the callbacks received through
26381      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
26382      * in that this is only telling you about the local request of the window,
26383      * not the actual values applied by the system.
26384      *
26385      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26386      * instead.
26387      */
26388     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)26389     public void onWindowSystemUiVisibilityChanged(int visible) {
26390     }
26391 
26392     /**
26393      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
26394      * the view hierarchy.
26395      *
26396      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26397      * instead.
26398      */
26399     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)26400     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
26401         onWindowSystemUiVisibilityChanged(visible);
26402     }
26403 
26404     /**
26405      * Set a listener to receive callbacks when the visibility of the system bar changes.
26406      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
26407      *
26408      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
26409      * by setting a {@link OnApplyWindowInsetsListener} on this view.
26410      */
26411     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)26412     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
26413         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
26414         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
26415             mParent.recomputeViewAttributes(this);
26416         }
26417     }
26418 
26419     /**
26420      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
26421      * the view hierarchy.
26422      *
26423      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
26424      * by setting a {@link OnApplyWindowInsetsListener} on this view.
26425      */
26426     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)26427     public void dispatchSystemUiVisibilityChanged(int visibility) {
26428         ListenerInfo li = mListenerInfo;
26429         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
26430             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
26431                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
26432         }
26433     }
26434 
updateLocalSystemUiVisibility(int localValue, int localChanges)26435     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
26436         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
26437         if (val != mSystemUiVisibility) {
26438             setSystemUiVisibility(val);
26439             return true;
26440         }
26441         return false;
26442     }
26443 
26444     /** @hide */
26445     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDisabledSystemUiVisibility(int flags)26446     public void setDisabledSystemUiVisibility(int flags) {
26447         if (mAttachInfo != null) {
26448             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
26449                 mAttachInfo.mDisabledSystemUiVisibility = flags;
26450                 if (mParent != null) {
26451                     mParent.recomputeViewAttributes(this);
26452                 }
26453             }
26454         }
26455     }
26456 
26457     /**
26458      * This needs to be a better API before it is exposed. For now, only the root view will get
26459      * notified.
26460      * @hide
26461      */
onSystemBarAppearanceChanged(@indowInsetsController.Appearance int appearance)26462     public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
26463     }
26464 
26465     /**
26466      * Creates an image that the system displays during the drag and drop
26467      * operation. This is called a &quot;drag shadow&quot;. The default implementation
26468      * for a DragShadowBuilder based on a View returns an image that has exactly the same
26469      * appearance as the given View. The default also positions the center of the drag shadow
26470      * directly under the touch point. If no View is provided (the constructor with no parameters
26471      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
26472      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
26473      * default is an invisible drag shadow.
26474      * <p>
26475      * You are not required to use the View you provide to the constructor as the basis of the
26476      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
26477      * anything you want as the drag shadow.
26478      * </p>
26479      * <p>
26480      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
26481      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
26482      *  size and position of the drag shadow. It uses this data to construct a
26483      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
26484      *  so that your application can draw the shadow image in the Canvas.
26485      * </p>
26486      *
26487      * <div class="special reference">
26488      * <h3>Developer Guides</h3>
26489      * <p>For a guide to implementing drag and drop features, read the
26490      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
26491      * </div>
26492      */
26493     public static class DragShadowBuilder {
26494         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
26495         private final WeakReference<View> mView;
26496 
26497         /**
26498          * Constructs a shadow image builder based on a View. By default, the resulting drag
26499          * shadow will have the same appearance and dimensions as the View, with the touch point
26500          * over the center of the View.
26501          * @param view A View. Any View in scope can be used.
26502          */
DragShadowBuilder(View view)26503         public DragShadowBuilder(View view) {
26504             mView = new WeakReference<View>(view);
26505         }
26506 
26507         /**
26508          * Construct a shadow builder object with no associated View.  This
26509          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
26510          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
26511          * to supply the drag shadow's dimensions and appearance without
26512          * reference to any View object.
26513          */
DragShadowBuilder()26514         public DragShadowBuilder() {
26515             mView = new WeakReference<View>(null);
26516         }
26517 
26518         /**
26519          * Returns the View object that had been passed to the
26520          * {@link #DragShadowBuilder(View)}
26521          * constructor.  If that View parameter was {@code null} or if the
26522          * {@link #DragShadowBuilder()}
26523          * constructor was used to instantiate the builder object, this method will return
26524          * null.
26525          *
26526          * @return The View object associate with this builder object.
26527          */
26528         @SuppressWarnings({"JavadocReference"})
getView()26529         final public View getView() {
26530             return mView.get();
26531         }
26532 
26533         /**
26534          * Provides the metrics for the shadow image. These include the dimensions of
26535          * the shadow image, and the point within that shadow that should
26536          * be centered under the touch location while dragging.
26537          * <p>
26538          * The default implementation sets the dimensions of the shadow to be the
26539          * same as the dimensions of the View itself and centers the shadow under
26540          * the touch point.
26541          * </p>
26542          *
26543          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
26544          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
26545          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
26546          * image. Since Android P, the width and height must be positive values.
26547          *
26548          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
26549          * shadow image that should be underneath the touch point during the drag and drop
26550          * operation. Your application must set {@link android.graphics.Point#x} to the
26551          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
26552          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)26553         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
26554             final View view = mView.get();
26555             if (view != null) {
26556                 outShadowSize.set(view.getWidth(), view.getHeight());
26557                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
26558             } else {
26559                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
26560             }
26561         }
26562 
26563         /**
26564          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
26565          * based on the dimensions it received from the
26566          * {@link #onProvideShadowMetrics(Point, Point)} callback.
26567          *
26568          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
26569          */
onDrawShadow(Canvas canvas)26570         public void onDrawShadow(Canvas canvas) {
26571             final View view = mView.get();
26572             if (view != null) {
26573                 view.draw(canvas);
26574             } else {
26575                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
26576             }
26577         }
26578     }
26579 
26580     /**
26581      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
26582      * startDragAndDrop()} for newer platform versions.
26583      */
26584     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)26585     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
26586                                    Object myLocalState, int flags) {
26587         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
26588     }
26589 
26590     /**
26591      * Starts a drag and drop operation. When your application calls this method, it passes a
26592      * {@link android.view.View.DragShadowBuilder} object to the system. The
26593      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
26594      * to get metrics for the drag shadow, and then calls the object's
26595      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
26596      * <p>
26597      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
26598      *  drag events to all the View objects in your application that are currently visible. It does
26599      *  this either by calling the View object's drag listener (an implementation of
26600      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
26601      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
26602      *  Both are passed a {@link android.view.DragEvent} object that has a
26603      *  {@link android.view.DragEvent#getAction()} value of
26604      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
26605      * </p>
26606      * <p>
26607      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
26608      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
26609      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
26610      * to the View the user selected for dragging.
26611      * </p>
26612      * @param data A {@link android.content.ClipData} object pointing to the data to be
26613      * transferred by the drag and drop operation.
26614      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26615      * drag shadow.
26616      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
26617      * drop operation. When dispatching drag events to views in the same activity this object
26618      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
26619      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
26620      * will return null).
26621      * <p>
26622      * myLocalState is a lightweight mechanism for the sending information from the dragged View
26623      * to the target Views. For example, it can contain flags that differentiate between a
26624      * a copy operation and a move operation.
26625      * </p>
26626      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
26627      * flags, or any combination of the following:
26628      *     <ul>
26629      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
26630      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
26631      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
26632      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
26633      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
26634      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
26635      *     </ul>
26636      * @return {@code true} if the method completes successfully, or
26637      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
26638      * do a drag because of another ongoing operation or some other reasons.
26639      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)26640     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
26641             Object myLocalState, int flags) {
26642         if (ViewDebug.DEBUG_DRAG) {
26643             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
26644         }
26645         if (mAttachInfo == null) {
26646             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
26647             return false;
26648         }
26649         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
26650             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
26651             return false;
26652         }
26653 
26654         if (data != null) {
26655             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
26656         }
26657 
26658         Point shadowSize = new Point();
26659         Point shadowTouchPoint = new Point();
26660         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
26661 
26662         if ((shadowSize.x < 0) || (shadowSize.y < 0)
26663                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
26664             throw new IllegalStateException("Drag shadow dimensions must not be negative");
26665         }
26666 
26667         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
26668         // does not accept zero size surface.
26669         if (shadowSize.x == 0  || shadowSize.y == 0) {
26670             if (!sAcceptZeroSizeDragShadow) {
26671                 throw new IllegalStateException("Drag shadow dimensions must be positive");
26672             }
26673             shadowSize.x = 1;
26674             shadowSize.y = 1;
26675         }
26676 
26677         if (ViewDebug.DEBUG_DRAG) {
26678             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
26679                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
26680         }
26681 
26682         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
26683         final SurfaceSession session = new SurfaceSession();
26684         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
26685                 .setName("drag surface")
26686                 .setParent(root.getSurfaceControl())
26687                 .setBufferSize(shadowSize.x, shadowSize.y)
26688                 .setFormat(PixelFormat.TRANSLUCENT)
26689                 .setCallsite("View.startDragAndDrop")
26690                 .build();
26691         final Surface surface = new Surface();
26692         surface.copyFrom(surfaceControl);
26693         IBinder token = null;
26694         try {
26695             final Canvas canvas = isHardwareAccelerated()
26696                     ? surface.lockHardwareCanvas()
26697                     : surface.lockCanvas(null);
26698             try {
26699                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26700                 shadowBuilder.onDrawShadow(canvas);
26701             } finally {
26702                 surface.unlockCanvasAndPost(canvas);
26703             }
26704 
26705             // repurpose 'shadowSize' for the last touch point
26706             root.getLastTouchPoint(shadowSize);
26707 
26708             token = mAttachInfo.mSession.performDrag(
26709                     mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(),
26710                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
26711             if (ViewDebug.DEBUG_DRAG) {
26712                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
26713             }
26714             if (token != null) {
26715                 if (mAttachInfo.mDragSurface != null) {
26716                     mAttachInfo.mDragSurface.release();
26717                 }
26718                 mAttachInfo.mDragSurface = surface;
26719                 mAttachInfo.mDragToken = token;
26720                 // Cache the local state object for delivery with DragEvents
26721                 root.setLocalDragState(myLocalState);
26722             }
26723             return token != null;
26724         } catch (Exception e) {
26725             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
26726             return false;
26727         } finally {
26728             if (token == null) {
26729                 surface.destroy();
26730             }
26731             session.kill();
26732         }
26733     }
26734 
26735     /**
26736      * Cancels an ongoing drag and drop operation.
26737      * <p>
26738      * A {@link android.view.DragEvent} object with
26739      * {@link android.view.DragEvent#getAction()} value of
26740      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
26741      * {@link android.view.DragEvent#getResult()} value of {@code false}
26742      * will be sent to every
26743      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
26744      * even if they are not currently visible.
26745      * </p>
26746      * <p>
26747      * This method can be called on any View in the same window as the View on which
26748      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
26749      * was called.
26750      * </p>
26751      */
cancelDragAndDrop()26752     public final void cancelDragAndDrop() {
26753         if (ViewDebug.DEBUG_DRAG) {
26754             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
26755         }
26756         if (mAttachInfo == null) {
26757             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
26758             return;
26759         }
26760         if (mAttachInfo.mDragToken != null) {
26761             try {
26762                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
26763             } catch (Exception e) {
26764                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
26765             }
26766             mAttachInfo.mDragToken = null;
26767         } else {
26768             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
26769         }
26770     }
26771 
26772     /**
26773      * Updates the drag shadow for the ongoing drag and drop operation.
26774      *
26775      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26776      * new drag shadow.
26777      */
updateDragShadow(DragShadowBuilder shadowBuilder)26778     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
26779         if (ViewDebug.DEBUG_DRAG) {
26780             Log.d(VIEW_LOG_TAG, "updateDragShadow");
26781         }
26782         if (mAttachInfo == null) {
26783             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
26784             return;
26785         }
26786         if (mAttachInfo.mDragToken != null) {
26787             try {
26788                 Canvas canvas = isHardwareAccelerated()
26789                         ? mAttachInfo.mDragSurface.lockHardwareCanvas()
26790                         : mAttachInfo.mDragSurface.lockCanvas(null);
26791                 try {
26792                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26793                     shadowBuilder.onDrawShadow(canvas);
26794                 } finally {
26795                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
26796                 }
26797             } catch (Exception e) {
26798                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
26799             }
26800         } else {
26801             Log.e(VIEW_LOG_TAG, "No active drag");
26802         }
26803     }
26804 
26805     /**
26806      * Starts a move from {startX, startY}, the amount of the movement will be the offset
26807      * between {startX, startY} and the new cursor positon.
26808      * @param startX horizontal coordinate where the move started.
26809      * @param startY vertical coordinate where the move started.
26810      * @return whether moving was started successfully.
26811      * @hide
26812      */
startMovingTask(float startX, float startY)26813     public final boolean startMovingTask(float startX, float startY) {
26814         if (ViewDebug.DEBUG_POSITIONING) {
26815             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
26816         }
26817         try {
26818             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
26819         } catch (RemoteException e) {
26820             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
26821         }
26822         return false;
26823     }
26824 
26825     /**
26826      * Finish a window move task.
26827      * @hide
26828      */
finishMovingTask()26829     public void finishMovingTask() {
26830         if (ViewDebug.DEBUG_POSITIONING) {
26831             Log.d(VIEW_LOG_TAG, "finishMovingTask");
26832         }
26833         try {
26834             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
26835         } catch (RemoteException e) {
26836             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
26837         }
26838     }
26839 
26840     /**
26841      * Handles drag events sent by the system following a call to
26842      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
26843      * startDragAndDrop()}.
26844      *<p>
26845      * When the system calls this method, it passes a
26846      * {@link android.view.DragEvent} object. A call to
26847      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
26848      * in DragEvent. The method uses these to determine what is happening in the drag and drop
26849      * operation.
26850      * </p>
26851      * <p>
26852      * The default implementation returns false, except if an {@link OnReceiveContentListener}
26853      * is {@link #setOnReceiveContentListener set} for this view. If an
26854      * {@link OnReceiveContentListener} is set, the default implementation...
26855      * <ul>
26856      * <li>returns true for an
26857      * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
26858      * <li>calls {@link #performReceiveContent} for an
26859      * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event
26860      * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if
26861      * the listener consumed some or all of the content
26862      * </ul>
26863      * </p>
26864      *
26865      * @param event The {@link android.view.DragEvent} sent by the system.
26866      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
26867      * in DragEvent, indicating the type of drag event represented by this object.
26868      * @return {@code true} if the method was successful, otherwise {@code false}.
26869      * <p>
26870      *  The method should return {@code true} in response to an action type of
26871      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
26872      *  operation.
26873      * </p>
26874      * <p>
26875      *  The method should also return {@code true} in response to an action type of
26876      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
26877      *  {@code false} if it didn't.
26878      * </p>
26879      * <p>
26880      *  For all other events, the return value is ignored.
26881      * </p>
26882      */
onDragEvent(DragEvent event)26883     public boolean onDragEvent(DragEvent event) {
26884         if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
26885             return false;
26886         }
26887         // Accept drag events by default if there's an OnReceiveContentListener set.
26888         if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
26889             return true;
26890         }
26891         if (event.getAction() == DragEvent.ACTION_DROP) {
26892             final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
26893             if (permissions != null) {
26894                 permissions.takeTransient();
26895             }
26896             final ContentInfo payload =
26897                     new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
26898                             .setDragAndDropPermissions(permissions)
26899                             .build();
26900             ContentInfo remainingPayload = performReceiveContent(payload);
26901             // Return true unless none of the payload was consumed.
26902             return remainingPayload != payload;
26903         }
26904         return false;
26905     }
26906 
26907     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)26908     boolean dispatchDragEnterExitInPreN(DragEvent event) {
26909         return callDragEventHandler(event);
26910     }
26911 
26912     /**
26913      * Detects if this View is enabled and has a drag event listener.
26914      * If both are true, then it calls the drag event listener with the
26915      * {@link android.view.DragEvent} it received. If the drag event listener returns
26916      * {@code true}, then dispatchDragEvent() returns {@code true}.
26917      * <p>
26918      * For all other cases, the method calls the
26919      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
26920      * method and returns its result.
26921      * </p>
26922      * <p>
26923      * This ensures that a drag event is always consumed, even if the View does not have a drag
26924      * event listener. However, if the View has a listener and the listener returns true, then
26925      * onDragEvent() is not called.
26926      * </p>
26927      */
dispatchDragEvent(DragEvent event)26928     public boolean dispatchDragEvent(DragEvent event) {
26929         event.mEventHandlerWasCalled = true;
26930         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
26931             event.mAction == DragEvent.ACTION_DROP) {
26932             // About to deliver an event with coordinates to this view. Notify that now this view
26933             // has drag focus. This will send exit/enter events as needed.
26934             getViewRootImpl().setDragFocus(this, event);
26935         }
26936         return callDragEventHandler(event);
26937     }
26938 
callDragEventHandler(DragEvent event)26939     final boolean callDragEventHandler(DragEvent event) {
26940         final boolean result;
26941 
26942         ListenerInfo li = mListenerInfo;
26943         //noinspection SimplifiableIfStatement
26944         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
26945                 && li.mOnDragListener.onDrag(this, event)) {
26946             result = true;
26947         } else {
26948             result = onDragEvent(event);
26949         }
26950 
26951         switch (event.mAction) {
26952             case DragEvent.ACTION_DRAG_ENTERED: {
26953                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
26954                 refreshDrawableState();
26955             } break;
26956             case DragEvent.ACTION_DRAG_EXITED: {
26957                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
26958                 refreshDrawableState();
26959             } break;
26960             case DragEvent.ACTION_DRAG_ENDED: {
26961                 mPrivateFlags2 &= ~View.DRAG_MASK;
26962                 refreshDrawableState();
26963             } break;
26964         }
26965 
26966         return result;
26967     }
26968 
canAcceptDrag()26969     boolean canAcceptDrag() {
26970         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
26971     }
26972 
26973     /**
26974      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
26975      * it is ever exposed at all.
26976      * @hide
26977      */
26978     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)26979     public void onCloseSystemDialogs(String reason) {
26980     }
26981 
26982     /**
26983      * Given a Drawable whose bounds have been set to draw into this view,
26984      * update a Region being computed for
26985      * {@link #gatherTransparentRegion(android.graphics.Region)} so
26986      * that any non-transparent parts of the Drawable are removed from the
26987      * given transparent region.
26988      *
26989      * @param dr The Drawable whose transparency is to be applied to the region.
26990      * @param region A Region holding the current transparency information,
26991      * where any parts of the region that are set are considered to be
26992      * transparent.  On return, this region will be modified to have the
26993      * transparency information reduced by the corresponding parts of the
26994      * Drawable that are not transparent.
26995      * {@hide}
26996      */
26997     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
applyDrawableToTransparentRegion(Drawable dr, Region region)26998     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
26999         if (DBG) {
27000             Log.i("View", "Getting transparent region for: " + this);
27001         }
27002         final Region r = dr.getTransparentRegion();
27003         final Rect db = dr.getBounds();
27004         final AttachInfo attachInfo = mAttachInfo;
27005         if (r != null && attachInfo != null) {
27006             final int w = getRight()-getLeft();
27007             final int h = getBottom()-getTop();
27008             if (db.left > 0) {
27009                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
27010                 r.op(0, 0, db.left, h, Region.Op.UNION);
27011             }
27012             if (db.right < w) {
27013                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
27014                 r.op(db.right, 0, w, h, Region.Op.UNION);
27015             }
27016             if (db.top > 0) {
27017                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
27018                 r.op(0, 0, w, db.top, Region.Op.UNION);
27019             }
27020             if (db.bottom < h) {
27021                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
27022                 r.op(0, db.bottom, w, h, Region.Op.UNION);
27023             }
27024             final int[] location = attachInfo.mTransparentLocation;
27025             getLocationInWindow(location);
27026             r.translate(location[0], location[1]);
27027             region.op(r, Region.Op.INTERSECT);
27028         } else {
27029             region.op(db, Region.Op.DIFFERENCE);
27030         }
27031     }
27032 
checkForLongClick(long delay, float x, float y, int classification)27033     private void checkForLongClick(long delay, float x, float y, int classification) {
27034         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
27035             mHasPerformedLongPress = false;
27036 
27037             if (mPendingCheckForLongPress == null) {
27038                 mPendingCheckForLongPress = new CheckForLongPress();
27039             }
27040             mPendingCheckForLongPress.setAnchor(x, y);
27041             mPendingCheckForLongPress.rememberWindowAttachCount();
27042             mPendingCheckForLongPress.rememberPressedState();
27043             mPendingCheckForLongPress.setClassification(classification);
27044             postDelayed(mPendingCheckForLongPress, delay);
27045         }
27046     }
27047 
27048     /**
27049      * Inflate a view from an XML resource.  This convenience method wraps the {@link
27050      * LayoutInflater} class, which provides a full range of options for view inflation.
27051      *
27052      * @param context The Context object for your activity or application.
27053      * @param resource The resource ID to inflate
27054      * @param root A view group that will be the parent.  Used to properly inflate the
27055      * layout_* parameters.
27056      * @see LayoutInflater
27057      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)27058     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
27059         LayoutInflater factory = LayoutInflater.from(context);
27060         return factory.inflate(resource, root);
27061     }
27062 
27063     /**
27064      * Scroll the view with standard behavior for scrolling beyond the normal
27065      * content boundaries. Views that call this method should override
27066      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
27067      * results of an over-scroll operation.
27068      *
27069      * Views can use this method to handle any touch or fling-based scrolling.
27070      *
27071      * @param deltaX Change in X in pixels
27072      * @param deltaY Change in Y in pixels
27073      * @param scrollX Current X scroll value in pixels before applying deltaX
27074      * @param scrollY Current Y scroll value in pixels before applying deltaY
27075      * @param scrollRangeX Maximum content scroll range along the X axis
27076      * @param scrollRangeY Maximum content scroll range along the Y axis
27077      * @param maxOverScrollX Number of pixels to overscroll by in either direction
27078      *          along the X axis.
27079      * @param maxOverScrollY Number of pixels to overscroll by in either direction
27080      *          along the Y axis.
27081      * @param isTouchEvent true if this scroll operation is the result of a touch event.
27082      * @return true if scrolling was clamped to an over-scroll boundary along either
27083      *          axis, false otherwise.
27084      */
27085     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)27086     protected boolean overScrollBy(int deltaX, int deltaY,
27087             int scrollX, int scrollY,
27088             int scrollRangeX, int scrollRangeY,
27089             int maxOverScrollX, int maxOverScrollY,
27090             boolean isTouchEvent) {
27091         final int overScrollMode = mOverScrollMode;
27092         final boolean canScrollHorizontal =
27093                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
27094         final boolean canScrollVertical =
27095                 computeVerticalScrollRange() > computeVerticalScrollExtent();
27096         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
27097                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
27098         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
27099                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
27100 
27101         int newScrollX = scrollX + deltaX;
27102         if (!overScrollHorizontal) {
27103             maxOverScrollX = 0;
27104         }
27105 
27106         int newScrollY = scrollY + deltaY;
27107         if (!overScrollVertical) {
27108             maxOverScrollY = 0;
27109         }
27110 
27111         // Clamp values if at the limits and record
27112         final int left = -maxOverScrollX;
27113         final int right = maxOverScrollX + scrollRangeX;
27114         final int top = -maxOverScrollY;
27115         final int bottom = maxOverScrollY + scrollRangeY;
27116 
27117         boolean clampedX = false;
27118         if (newScrollX > right) {
27119             newScrollX = right;
27120             clampedX = true;
27121         } else if (newScrollX < left) {
27122             newScrollX = left;
27123             clampedX = true;
27124         }
27125 
27126         boolean clampedY = false;
27127         if (newScrollY > bottom) {
27128             newScrollY = bottom;
27129             clampedY = true;
27130         } else if (newScrollY < top) {
27131             newScrollY = top;
27132             clampedY = true;
27133         }
27134 
27135         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
27136 
27137         return clampedX || clampedY;
27138     }
27139 
27140     /**
27141      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
27142      * respond to the results of an over-scroll operation.
27143      *
27144      * @param scrollX New X scroll value in pixels
27145      * @param scrollY New Y scroll value in pixels
27146      * @param clampedX True if scrollX was clamped to an over-scroll boundary
27147      * @param clampedY True if scrollY was clamped to an over-scroll boundary
27148      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)27149     protected void onOverScrolled(int scrollX, int scrollY,
27150             boolean clampedX, boolean clampedY) {
27151         // Intentionally empty.
27152     }
27153 
27154     /**
27155      * Returns the over-scroll mode for this view. The result will be
27156      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
27157      * (allow over-scrolling only if the view content is larger than the container),
27158      * or {@link #OVER_SCROLL_NEVER}.
27159      *
27160      * @return This view's over-scroll mode.
27161      */
27162     @InspectableProperty(enumMapping = {
27163             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
27164             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
27165             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
27166     })
getOverScrollMode()27167     public int getOverScrollMode() {
27168         return mOverScrollMode;
27169     }
27170 
27171     /**
27172      * Set the over-scroll mode for this view. Valid over-scroll modes are
27173      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
27174      * (allow over-scrolling only if the view content is larger than the container),
27175      * or {@link #OVER_SCROLL_NEVER}.
27176      *
27177      * Setting the over-scroll mode of a view will have an effect only if the
27178      * view is capable of scrolling.
27179      *
27180      * @param overScrollMode The new over-scroll mode for this view.
27181      */
setOverScrollMode(int overScrollMode)27182     public void setOverScrollMode(int overScrollMode) {
27183         if (overScrollMode != OVER_SCROLL_ALWAYS &&
27184                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
27185                 overScrollMode != OVER_SCROLL_NEVER) {
27186             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
27187         }
27188         mOverScrollMode = overScrollMode;
27189     }
27190 
27191     /**
27192      * Enable or disable nested scrolling for this view.
27193      *
27194      * <p>If this property is set to true the view will be permitted to initiate nested
27195      * scrolling operations with a compatible parent view in the current hierarchy. If this
27196      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
27197      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
27198      * the nested scroll.</p>
27199      *
27200      * @param enabled true to enable nested scrolling, false to disable
27201      *
27202      * @see #isNestedScrollingEnabled()
27203      */
setNestedScrollingEnabled(boolean enabled)27204     public void setNestedScrollingEnabled(boolean enabled) {
27205         if (enabled) {
27206             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
27207         } else {
27208             stopNestedScroll();
27209             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
27210         }
27211     }
27212 
27213     /**
27214      * Returns true if nested scrolling is enabled for this view.
27215      *
27216      * <p>If nested scrolling is enabled and this View class implementation supports it,
27217      * this view will act as a nested scrolling child view when applicable, forwarding data
27218      * about the scroll operation in progress to a compatible and cooperating nested scrolling
27219      * parent.</p>
27220      *
27221      * @return true if nested scrolling is enabled
27222      *
27223      * @see #setNestedScrollingEnabled(boolean)
27224      */
27225     @InspectableProperty
isNestedScrollingEnabled()27226     public boolean isNestedScrollingEnabled() {
27227         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
27228                 PFLAG3_NESTED_SCROLLING_ENABLED;
27229     }
27230 
27231     /**
27232      * Begin a nestable scroll operation along the given axes.
27233      *
27234      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
27235      *
27236      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
27237      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
27238      * In the case of touch scrolling the nested scroll will be terminated automatically in
27239      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
27240      * In the event of programmatic scrolling the caller must explicitly call
27241      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
27242      *
27243      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
27244      * If it returns false the caller may ignore the rest of this contract until the next scroll.
27245      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
27246      *
27247      * <p>At each incremental step of the scroll the caller should invoke
27248      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
27249      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
27250      * parent at least partially consumed the scroll and the caller should adjust the amount it
27251      * scrolls by.</p>
27252      *
27253      * <p>After applying the remainder of the scroll delta the caller should invoke
27254      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
27255      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
27256      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
27257      * </p>
27258      *
27259      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
27260      *             {@link #SCROLL_AXIS_VERTICAL}.
27261      * @return true if a cooperative parent was found and nested scrolling has been enabled for
27262      *         the current gesture.
27263      *
27264      * @see #stopNestedScroll()
27265      * @see #dispatchNestedPreScroll(int, int, int[], int[])
27266      * @see #dispatchNestedScroll(int, int, int, int, int[])
27267      */
startNestedScroll(int axes)27268     public boolean startNestedScroll(int axes) {
27269         if (hasNestedScrollingParent()) {
27270             // Already in progress
27271             return true;
27272         }
27273         if (isNestedScrollingEnabled()) {
27274             ViewParent p = getParent();
27275             View child = this;
27276             while (p != null) {
27277                 try {
27278                     if (p.onStartNestedScroll(child, this, axes)) {
27279                         mNestedScrollingParent = p;
27280                         p.onNestedScrollAccepted(child, this, axes);
27281                         return true;
27282                     }
27283                 } catch (AbstractMethodError e) {
27284                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
27285                             "method onStartNestedScroll", e);
27286                     // Allow the search upward to continue
27287                 }
27288                 if (p instanceof View) {
27289                     child = (View) p;
27290                 }
27291                 p = p.getParent();
27292             }
27293         }
27294         return false;
27295     }
27296 
27297     /**
27298      * Stop a nested scroll in progress.
27299      *
27300      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
27301      *
27302      * @see #startNestedScroll(int)
27303      */
stopNestedScroll()27304     public void stopNestedScroll() {
27305         if (mNestedScrollingParent != null) {
27306             mNestedScrollingParent.onStopNestedScroll(this);
27307             mNestedScrollingParent = null;
27308         }
27309     }
27310 
27311     /**
27312      * Returns true if this view has a nested scrolling parent.
27313      *
27314      * <p>The presence of a nested scrolling parent indicates that this view has initiated
27315      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
27316      *
27317      * @return whether this view has a nested scrolling parent
27318      */
hasNestedScrollingParent()27319     public boolean hasNestedScrollingParent() {
27320         return mNestedScrollingParent != null;
27321     }
27322 
27323     /**
27324      * Dispatch one step of a nested scroll in progress.
27325      *
27326      * <p>Implementations of views that support nested scrolling should call this to report
27327      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
27328      * is not currently in progress or nested scrolling is not
27329      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
27330      *
27331      * <p>Compatible View implementations should also call
27332      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
27333      * consuming a component of the scroll event themselves.</p>
27334      *
27335      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
27336      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
27337      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
27338      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
27339      * @param offsetInWindow Optional. If not null, on return this will contain the offset
27340      *                       in local view coordinates of this view from before this operation
27341      *                       to after it completes. View implementations may use this to adjust
27342      *                       expected input coordinate tracking.
27343      * @return true if the event was dispatched, false if it could not be dispatched.
27344      * @see #dispatchNestedPreScroll(int, int, int[], int[])
27345      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)27346     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
27347             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
27348         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27349             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
27350                 int startX = 0;
27351                 int startY = 0;
27352                 if (offsetInWindow != null) {
27353                     getLocationInWindow(offsetInWindow);
27354                     startX = offsetInWindow[0];
27355                     startY = offsetInWindow[1];
27356                 }
27357 
27358                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
27359                         dxUnconsumed, dyUnconsumed);
27360 
27361                 if (offsetInWindow != null) {
27362                     getLocationInWindow(offsetInWindow);
27363                     offsetInWindow[0] -= startX;
27364                     offsetInWindow[1] -= startY;
27365                 }
27366                 return true;
27367             } else if (offsetInWindow != null) {
27368                 // No motion, no dispatch. Keep offsetInWindow up to date.
27369                 offsetInWindow[0] = 0;
27370                 offsetInWindow[1] = 0;
27371             }
27372         }
27373         return false;
27374     }
27375 
27376     /**
27377      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
27378      *
27379      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
27380      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
27381      * scrolling operation to consume some or all of the scroll operation before the child view
27382      * consumes it.</p>
27383      *
27384      * @param dx Horizontal scroll distance in pixels
27385      * @param dy Vertical scroll distance in pixels
27386      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
27387      *                 and consumed[1] the consumed dy.
27388      * @param offsetInWindow Optional. If not null, on return this will contain the offset
27389      *                       in local view coordinates of this view from before this operation
27390      *                       to after it completes. View implementations may use this to adjust
27391      *                       expected input coordinate tracking.
27392      * @return true if the parent consumed some or all of the scroll delta
27393      * @see #dispatchNestedScroll(int, int, int, int, int[])
27394      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)27395     public boolean dispatchNestedPreScroll(int dx, int dy,
27396             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
27397         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27398             if (dx != 0 || dy != 0) {
27399                 int startX = 0;
27400                 int startY = 0;
27401                 if (offsetInWindow != null) {
27402                     getLocationInWindow(offsetInWindow);
27403                     startX = offsetInWindow[0];
27404                     startY = offsetInWindow[1];
27405                 }
27406 
27407                 if (consumed == null) {
27408                     if (mTempNestedScrollConsumed == null) {
27409                         mTempNestedScrollConsumed = new int[2];
27410                     }
27411                     consumed = mTempNestedScrollConsumed;
27412                 }
27413                 consumed[0] = 0;
27414                 consumed[1] = 0;
27415                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
27416 
27417                 if (offsetInWindow != null) {
27418                     getLocationInWindow(offsetInWindow);
27419                     offsetInWindow[0] -= startX;
27420                     offsetInWindow[1] -= startY;
27421                 }
27422                 return consumed[0] != 0 || consumed[1] != 0;
27423             } else if (offsetInWindow != null) {
27424                 offsetInWindow[0] = 0;
27425                 offsetInWindow[1] = 0;
27426             }
27427         }
27428         return false;
27429     }
27430 
27431     /**
27432      * Dispatch a fling to a nested scrolling parent.
27433      *
27434      * <p>This method should be used to indicate that a nested scrolling child has detected
27435      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
27436      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
27437      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
27438      * along a scrollable axis.</p>
27439      *
27440      * <p>If a nested scrolling child view would normally fling but it is at the edge of
27441      * its own content, it can use this method to delegate the fling to its nested scrolling
27442      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
27443      *
27444      * @param velocityX Horizontal fling velocity in pixels per second
27445      * @param velocityY Vertical fling velocity in pixels per second
27446      * @param consumed true if the child consumed the fling, false otherwise
27447      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
27448      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)27449     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
27450         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27451             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
27452         }
27453         return false;
27454     }
27455 
27456     /**
27457      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
27458      *
27459      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
27460      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
27461      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
27462      * before the child view consumes it. If this method returns <code>true</code>, a nested
27463      * parent view consumed the fling and this view should not scroll as a result.</p>
27464      *
27465      * <p>For a better user experience, only one view in a nested scrolling chain should consume
27466      * the fling at a time. If a parent view consumed the fling this method will return false.
27467      * Custom view implementations should account for this in two ways:</p>
27468      *
27469      * <ul>
27470      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
27471      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
27472      *     position regardless.</li>
27473      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
27474      *     even to settle back to a valid idle position.</li>
27475      * </ul>
27476      *
27477      * <p>Views should also not offer fling velocities to nested parent views along an axis
27478      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
27479      * should not offer a horizontal fling velocity to its parents since scrolling along that
27480      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
27481      *
27482      * @param velocityX Horizontal fling velocity in pixels per second
27483      * @param velocityY Vertical fling velocity in pixels per second
27484      * @return true if a nested scrolling parent consumed the fling
27485      */
dispatchNestedPreFling(float velocityX, float velocityY)27486     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
27487         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27488             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
27489         }
27490         return false;
27491     }
27492 
27493     /**
27494      * Gets a scale factor that determines the distance the view should scroll
27495      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
27496      * @return The vertical scroll scale factor.
27497      * @hide
27498      */
27499     @UnsupportedAppUsage
getVerticalScrollFactor()27500     protected float getVerticalScrollFactor() {
27501         if (mVerticalScrollFactor == 0) {
27502             TypedValue outValue = new TypedValue();
27503             if (!mContext.getTheme().resolveAttribute(
27504                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
27505                 throw new IllegalStateException(
27506                         "Expected theme to define listPreferredItemHeight.");
27507             }
27508             mVerticalScrollFactor = outValue.getDimension(
27509                     mContext.getResources().getDisplayMetrics());
27510         }
27511         return mVerticalScrollFactor;
27512     }
27513 
27514     /**
27515      * Gets a scale factor that determines the distance the view should scroll
27516      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
27517      * @return The horizontal scroll scale factor.
27518      * @hide
27519      */
27520     @UnsupportedAppUsage
getHorizontalScrollFactor()27521     protected float getHorizontalScrollFactor() {
27522         // TODO: Should use something else.
27523         return getVerticalScrollFactor();
27524     }
27525 
27526     /**
27527      * Return the value specifying the text direction or policy that was set with
27528      * {@link #setTextDirection(int)}.
27529      *
27530      * @return the defined text direction. It can be one of:
27531      *
27532      * {@link #TEXT_DIRECTION_INHERIT},
27533      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27534      * {@link #TEXT_DIRECTION_ANY_RTL},
27535      * {@link #TEXT_DIRECTION_LTR},
27536      * {@link #TEXT_DIRECTION_RTL},
27537      * {@link #TEXT_DIRECTION_LOCALE},
27538      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27539      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
27540      *
27541      * @attr ref android.R.styleable#View_textDirection
27542      *
27543      * @hide
27544      */
27545     @ViewDebug.ExportedProperty(category = "text", mapping = {
27546             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
27547             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
27548             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
27549             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
27550             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
27551             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
27552             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
27553             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
27554     })
27555     @InspectableProperty(hasAttributeId = false, enumMapping = {
27556             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
27557             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
27558             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
27559             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
27560             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
27561             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
27562             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
27563             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
27564     })
27565     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextDirection()27566     public int getRawTextDirection() {
27567         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
27568     }
27569 
27570     /**
27571      * Set the text direction.
27572      *
27573      * @param textDirection the direction to set. Should be one of:
27574      *
27575      * {@link #TEXT_DIRECTION_INHERIT},
27576      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27577      * {@link #TEXT_DIRECTION_ANY_RTL},
27578      * {@link #TEXT_DIRECTION_LTR},
27579      * {@link #TEXT_DIRECTION_RTL},
27580      * {@link #TEXT_DIRECTION_LOCALE}
27581      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27582      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
27583      *
27584      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
27585      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
27586      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
27587      *
27588      * @attr ref android.R.styleable#View_textDirection
27589      */
setTextDirection(int textDirection)27590     public void setTextDirection(int textDirection) {
27591         if (getRawTextDirection() != textDirection) {
27592             // Reset the current text direction and the resolved one
27593             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
27594             resetResolvedTextDirection();
27595             // Set the new text direction
27596             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
27597             // Do resolution
27598             resolveTextDirection();
27599             // Notify change
27600             onRtlPropertiesChanged(getLayoutDirection());
27601             // Refresh
27602             requestLayout();
27603             invalidate(true);
27604         }
27605     }
27606 
27607     /**
27608      * Return the resolved text direction.
27609      *
27610      * @return the resolved text direction. Returns one of:
27611      *
27612      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27613      * {@link #TEXT_DIRECTION_ANY_RTL},
27614      * {@link #TEXT_DIRECTION_LTR},
27615      * {@link #TEXT_DIRECTION_RTL},
27616      * {@link #TEXT_DIRECTION_LOCALE},
27617      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27618      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
27619      *
27620      * @attr ref android.R.styleable#View_textDirection
27621      */
27622     @ViewDebug.ExportedProperty(category = "text", mapping = {
27623             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
27624             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
27625             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
27626             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
27627             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
27628             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
27629             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
27630             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
27631     })
27632     @InspectableProperty(hasAttributeId = false, enumMapping = {
27633             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
27634             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
27635             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
27636             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
27637             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
27638             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
27639             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
27640     })
getTextDirection()27641     public int getTextDirection() {
27642         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
27643     }
27644 
27645     /**
27646      * Resolve the text direction.
27647      *
27648      * @return true if resolution has been done, false otherwise.
27649      *
27650      * @hide
27651      */
resolveTextDirection()27652     public boolean resolveTextDirection() {
27653         // Reset any previous text direction resolution
27654         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27655 
27656         if (hasRtlSupport()) {
27657             // Set resolved text direction flag depending on text direction flag
27658             final int textDirection = getRawTextDirection();
27659             switch(textDirection) {
27660                 case TEXT_DIRECTION_INHERIT:
27661                     if (!canResolveTextDirection()) {
27662                         // We cannot do the resolution if there is no parent, so use the default one
27663                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27664                         // Resolution will need to happen again later
27665                         return false;
27666                     }
27667 
27668                     // Parent has not yet resolved, so we still return the default
27669                     try {
27670                         if (!mParent.isTextDirectionResolved()) {
27671                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27672                             // Resolution will need to happen again later
27673                             return false;
27674                         }
27675                     } catch (AbstractMethodError e) {
27676                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27677                                 " does not fully implement ViewParent", e);
27678                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
27679                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27680                         return true;
27681                     }
27682 
27683                     // Set current resolved direction to the same value as the parent's one
27684                     int parentResolvedDirection;
27685                     try {
27686                         parentResolvedDirection = mParent.getTextDirection();
27687                     } catch (AbstractMethodError e) {
27688                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27689                                 " does not fully implement ViewParent", e);
27690                         parentResolvedDirection = TEXT_DIRECTION_LTR;
27691                     }
27692                     switch (parentResolvedDirection) {
27693                         case TEXT_DIRECTION_FIRST_STRONG:
27694                         case TEXT_DIRECTION_ANY_RTL:
27695                         case TEXT_DIRECTION_LTR:
27696                         case TEXT_DIRECTION_RTL:
27697                         case TEXT_DIRECTION_LOCALE:
27698                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
27699                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
27700                             mPrivateFlags2 |=
27701                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
27702                             break;
27703                         default:
27704                             // Default resolved direction is "first strong" heuristic
27705                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27706                     }
27707                     break;
27708                 case TEXT_DIRECTION_FIRST_STRONG:
27709                 case TEXT_DIRECTION_ANY_RTL:
27710                 case TEXT_DIRECTION_LTR:
27711                 case TEXT_DIRECTION_RTL:
27712                 case TEXT_DIRECTION_LOCALE:
27713                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
27714                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
27715                     // Resolved direction is the same as text direction
27716                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
27717                     break;
27718                 default:
27719                     // Default resolved direction is "first strong" heuristic
27720                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27721             }
27722         } else {
27723             // Default resolved direction is "first strong" heuristic
27724             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27725         }
27726 
27727         // Set to resolved
27728         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
27729         return true;
27730     }
27731 
27732     /**
27733      * Check if text direction resolution can be done.
27734      *
27735      * @return true if text direction resolution can be done otherwise return false.
27736      */
canResolveTextDirection()27737     public boolean canResolveTextDirection() {
27738         switch (getRawTextDirection()) {
27739             case TEXT_DIRECTION_INHERIT:
27740                 if (mParent != null) {
27741                     try {
27742                         return mParent.canResolveTextDirection();
27743                     } catch (AbstractMethodError e) {
27744                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27745                                 " does not fully implement ViewParent", e);
27746                     }
27747                 }
27748                 return false;
27749 
27750             default:
27751                 return true;
27752         }
27753     }
27754 
27755     /**
27756      * Reset resolved text direction. Text direction will be resolved during a call to
27757      * {@link #onMeasure(int, int)}.
27758      *
27759      * @hide
27760      */
27761     @TestApi
resetResolvedTextDirection()27762     public void resetResolvedTextDirection() {
27763         // Reset any previous text direction resolution
27764         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27765         // Set to default value
27766         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27767     }
27768 
27769     /**
27770      * @return true if text direction is inherited.
27771      *
27772      * @hide
27773      */
isTextDirectionInherited()27774     public boolean isTextDirectionInherited() {
27775         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
27776     }
27777 
27778     /**
27779      * @return true if text direction is resolved.
27780      */
isTextDirectionResolved()27781     public boolean isTextDirectionResolved() {
27782         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
27783     }
27784 
27785     /**
27786      * Return the value specifying the text alignment or policy that was set with
27787      * {@link #setTextAlignment(int)}.
27788      *
27789      * @return the defined text alignment. It can be one of:
27790      *
27791      * {@link #TEXT_ALIGNMENT_INHERIT},
27792      * {@link #TEXT_ALIGNMENT_GRAVITY},
27793      * {@link #TEXT_ALIGNMENT_CENTER},
27794      * {@link #TEXT_ALIGNMENT_TEXT_START},
27795      * {@link #TEXT_ALIGNMENT_TEXT_END},
27796      * {@link #TEXT_ALIGNMENT_VIEW_START},
27797      * {@link #TEXT_ALIGNMENT_VIEW_END}
27798      *
27799      * @attr ref android.R.styleable#View_textAlignment
27800      *
27801      * @hide
27802      */
27803     @ViewDebug.ExportedProperty(category = "text", mapping = {
27804             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27805             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27806             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27807             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27808             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27809             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27810             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27811     })
27812     @InspectableProperty(hasAttributeId = false, enumMapping = {
27813             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
27814             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27815             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27816             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27817             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27818             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27819             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27820     })
27821     @TextAlignment
27822     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextAlignment()27823     public int getRawTextAlignment() {
27824         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
27825     }
27826 
27827     /**
27828      * Set the text alignment.
27829      *
27830      * @param textAlignment The text alignment to set. Should be one of
27831      *
27832      * {@link #TEXT_ALIGNMENT_INHERIT},
27833      * {@link #TEXT_ALIGNMENT_GRAVITY},
27834      * {@link #TEXT_ALIGNMENT_CENTER},
27835      * {@link #TEXT_ALIGNMENT_TEXT_START},
27836      * {@link #TEXT_ALIGNMENT_TEXT_END},
27837      * {@link #TEXT_ALIGNMENT_VIEW_START},
27838      * {@link #TEXT_ALIGNMENT_VIEW_END}
27839      *
27840      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
27841      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
27842      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
27843      *
27844      * @attr ref android.R.styleable#View_textAlignment
27845      */
setTextAlignment(@extAlignment int textAlignment)27846     public void setTextAlignment(@TextAlignment int textAlignment) {
27847         if (textAlignment != getRawTextAlignment()) {
27848             // Reset the current and resolved text alignment
27849             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
27850             resetResolvedTextAlignment();
27851             // Set the new text alignment
27852             mPrivateFlags2 |=
27853                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
27854             // Do resolution
27855             resolveTextAlignment();
27856             // Notify change
27857             onRtlPropertiesChanged(getLayoutDirection());
27858             // Refresh
27859             requestLayout();
27860             invalidate(true);
27861         }
27862     }
27863 
27864     /**
27865      * Return the resolved text alignment.
27866      *
27867      * @return the resolved text alignment. Returns one of:
27868      *
27869      * {@link #TEXT_ALIGNMENT_GRAVITY},
27870      * {@link #TEXT_ALIGNMENT_CENTER},
27871      * {@link #TEXT_ALIGNMENT_TEXT_START},
27872      * {@link #TEXT_ALIGNMENT_TEXT_END},
27873      * {@link #TEXT_ALIGNMENT_VIEW_START},
27874      * {@link #TEXT_ALIGNMENT_VIEW_END}
27875      *
27876      * @attr ref android.R.styleable#View_textAlignment
27877      */
27878     @ViewDebug.ExportedProperty(category = "text", mapping = {
27879             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27880             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27881             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27882             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27883             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27884             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27885             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27886     })
27887     @InspectableProperty(enumMapping = {
27888             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27889             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27890             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27891             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27892             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27893             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27894     })
27895     @TextAlignment
getTextAlignment()27896     public int getTextAlignment() {
27897         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
27898                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
27899     }
27900 
27901     /**
27902      * Resolve the text alignment.
27903      *
27904      * @return true if resolution has been done, false otherwise.
27905      *
27906      * @hide
27907      */
resolveTextAlignment()27908     public boolean resolveTextAlignment() {
27909         // Reset any previous text alignment resolution
27910         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
27911 
27912         if (hasRtlSupport()) {
27913             // Set resolved text alignment flag depending on text alignment flag
27914             final int textAlignment = getRawTextAlignment();
27915             switch (textAlignment) {
27916                 case TEXT_ALIGNMENT_INHERIT:
27917                     // Check if we can resolve the text alignment
27918                     if (!canResolveTextAlignment()) {
27919                         // We cannot do the resolution if there is no parent so use the default
27920                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27921                         // Resolution will need to happen again later
27922                         return false;
27923                     }
27924 
27925                     // Parent has not yet resolved, so we still return the default
27926                     try {
27927                         if (!mParent.isTextAlignmentResolved()) {
27928                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27929                             // Resolution will need to happen again later
27930                             return false;
27931                         }
27932                     } catch (AbstractMethodError e) {
27933                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27934                                 " does not fully implement ViewParent", e);
27935                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
27936                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27937                         return true;
27938                     }
27939 
27940                     int parentResolvedTextAlignment;
27941                     try {
27942                         parentResolvedTextAlignment = mParent.getTextAlignment();
27943                     } catch (AbstractMethodError e) {
27944                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27945                                 " does not fully implement ViewParent", e);
27946                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
27947                     }
27948                     switch (parentResolvedTextAlignment) {
27949                         case TEXT_ALIGNMENT_GRAVITY:
27950                         case TEXT_ALIGNMENT_TEXT_START:
27951                         case TEXT_ALIGNMENT_TEXT_END:
27952                         case TEXT_ALIGNMENT_CENTER:
27953                         case TEXT_ALIGNMENT_VIEW_START:
27954                         case TEXT_ALIGNMENT_VIEW_END:
27955                             // Resolved text alignment is the same as the parent resolved
27956                             // text alignment
27957                             mPrivateFlags2 |=
27958                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
27959                             break;
27960                         default:
27961                             // Use default resolved text alignment
27962                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27963                     }
27964                     break;
27965                 case TEXT_ALIGNMENT_GRAVITY:
27966                 case TEXT_ALIGNMENT_TEXT_START:
27967                 case TEXT_ALIGNMENT_TEXT_END:
27968                 case TEXT_ALIGNMENT_CENTER:
27969                 case TEXT_ALIGNMENT_VIEW_START:
27970                 case TEXT_ALIGNMENT_VIEW_END:
27971                     // Resolved text alignment is the same as text alignment
27972                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
27973                     break;
27974                 default:
27975                     // Use default resolved text alignment
27976                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27977             }
27978         } else {
27979             // Use default resolved text alignment
27980             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27981         }
27982 
27983         // Set the resolved
27984         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
27985         return true;
27986     }
27987 
27988     /**
27989      * Check if text alignment resolution can be done.
27990      *
27991      * @return true if text alignment resolution can be done otherwise return false.
27992      */
canResolveTextAlignment()27993     public boolean canResolveTextAlignment() {
27994         switch (getRawTextAlignment()) {
27995             case TEXT_DIRECTION_INHERIT:
27996                 if (mParent != null) {
27997                     try {
27998                         return mParent.canResolveTextAlignment();
27999                     } catch (AbstractMethodError e) {
28000                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
28001                                 " does not fully implement ViewParent", e);
28002                     }
28003                 }
28004                 return false;
28005 
28006             default:
28007                 return true;
28008         }
28009     }
28010 
28011     /**
28012      * Reset resolved text alignment. Text alignment will be resolved during a call to
28013      * {@link #onMeasure(int, int)}.
28014      *
28015      * @hide
28016      */
28017     @TestApi
resetResolvedTextAlignment()28018     public void resetResolvedTextAlignment() {
28019         // Reset any previous text alignment resolution
28020         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
28021         // Set to default
28022         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
28023     }
28024 
28025     /**
28026      * @return true if text alignment is inherited.
28027      *
28028      * @hide
28029      */
isTextAlignmentInherited()28030     public boolean isTextAlignmentInherited() {
28031         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
28032     }
28033 
28034     /**
28035      * @return true if text alignment is resolved.
28036      */
isTextAlignmentResolved()28037     public boolean isTextAlignmentResolved() {
28038         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
28039     }
28040 
28041     /**
28042      * Generate a value suitable for use in {@link #setId(int)}.
28043      * This value will not collide with ID values generated at build time by aapt for R.id.
28044      *
28045      * @return a generated ID value
28046      */
generateViewId()28047     public static int generateViewId() {
28048         for (;;) {
28049             final int result = sNextGeneratedId.get();
28050             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
28051             int newValue = result + 1;
28052             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
28053             if (sNextGeneratedId.compareAndSet(result, newValue)) {
28054                 return result;
28055             }
28056         }
28057     }
28058 
isViewIdGenerated(int id)28059     private static boolean isViewIdGenerated(int id) {
28060         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
28061     }
28062 
28063     /**
28064      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
28065      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
28066      *                           a normal View or a ViewGroup with
28067      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
28068      * @hide
28069      */
captureTransitioningViews(List<View> transitioningViews)28070     public void captureTransitioningViews(List<View> transitioningViews) {
28071         if (getVisibility() == View.VISIBLE) {
28072             transitioningViews.add(this);
28073         }
28074     }
28075 
28076     /**
28077      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
28078      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
28079      * @hide
28080      */
findNamedViews(Map<String, View> namedElements)28081     public void findNamedViews(Map<String, View> namedElements) {
28082         if (getVisibility() == VISIBLE || mGhostView != null) {
28083             String transitionName = getTransitionName();
28084             if (transitionName != null) {
28085                 namedElements.put(transitionName, this);
28086             }
28087         }
28088     }
28089 
28090     /**
28091      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
28092      * The default implementation does not care the location or event types, but some subclasses
28093      * may use it (such as WebViews).
28094      * @param event The MotionEvent from a mouse
28095      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
28096      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
28097      * @see PointerIcon
28098      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)28099     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
28100         final float x = event.getX(pointerIndex);
28101         final float y = event.getY(pointerIndex);
28102         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
28103             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
28104         }
28105         return mPointerIcon;
28106     }
28107 
28108     /**
28109      * Set the pointer icon for the current view.
28110      * Passing {@code null} will restore the pointer icon to its default value.
28111      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
28112      */
setPointerIcon(PointerIcon pointerIcon)28113     public void setPointerIcon(PointerIcon pointerIcon) {
28114         mPointerIcon = pointerIcon;
28115         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
28116             return;
28117         }
28118         try {
28119             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
28120         } catch (RemoteException e) {
28121         }
28122     }
28123 
28124     /**
28125      * Gets the pointer icon for the current view.
28126      */
28127     @InspectableProperty
getPointerIcon()28128     public PointerIcon getPointerIcon() {
28129         return mPointerIcon;
28130     }
28131 
28132     /**
28133      * Checks pointer capture status.
28134      *
28135      * @return true if the view has pointer capture.
28136      * @see #requestPointerCapture()
28137      * @see #hasPointerCapture()
28138      */
hasPointerCapture()28139     public boolean hasPointerCapture() {
28140         final ViewRootImpl viewRootImpl = getViewRootImpl();
28141         if (viewRootImpl == null) {
28142             return false;
28143         }
28144         return viewRootImpl.hasPointerCapture();
28145     }
28146 
28147     /**
28148      * Requests pointer capture mode.
28149      * <p>
28150      * When the window has pointer capture, the mouse pointer icon will disappear and will not
28151      * change its position. Enabling pointer capture will change the behavior of input devices in
28152      * the following ways:
28153      * <ul>
28154      *     <li>Events from a mouse will be delivered with the source
28155      *     {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
28156      *     available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
28157      *
28158      *     <li>Events from a touchpad will be delivered with the source
28159      *     {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
28160      *     on the touchpad will be available through {@link MotionEvent#getX(int)} and
28161      *     {@link MotionEvent#getY(int)}, and their relative movements are stored in
28162      *     {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li>
28163      *
28164      *     <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
28165      * </ul>
28166      * <p>
28167      * Events captured through pointer capture will be dispatched to
28168      * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
28169      * {@link OnCapturedPointerListener} is set, and otherwise to
28170      * {@link #onCapturedPointerEvent(MotionEvent)}.
28171      * <p>
28172      * If the window already has pointer capture, this call does nothing.
28173      * <p>
28174      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
28175      * automatically when the window loses focus.
28176      *
28177      * @see #releasePointerCapture()
28178      * @see #hasPointerCapture()
28179      * @see #onPointerCaptureChange(boolean)
28180      */
requestPointerCapture()28181     public void requestPointerCapture() {
28182         final ViewRootImpl viewRootImpl = getViewRootImpl();
28183         if (viewRootImpl != null) {
28184             viewRootImpl.requestPointerCapture(true);
28185         }
28186     }
28187 
28188 
28189     /**
28190      * Releases the pointer capture.
28191      * <p>
28192      * If the window does not have pointer capture, this call will do nothing.
28193      * @see #requestPointerCapture()
28194      * @see #hasPointerCapture()
28195      * @see #onPointerCaptureChange(boolean)
28196      */
releasePointerCapture()28197     public void releasePointerCapture() {
28198         final ViewRootImpl viewRootImpl = getViewRootImpl();
28199         if (viewRootImpl != null) {
28200             viewRootImpl.requestPointerCapture(false);
28201         }
28202     }
28203 
28204     /**
28205      * Called when the window has just acquired or lost pointer capture.
28206      *
28207      * @param hasCapture True if the view now has pointerCapture, false otherwise.
28208      */
28209     @CallSuper
onPointerCaptureChange(boolean hasCapture)28210     public void onPointerCaptureChange(boolean hasCapture) {
28211     }
28212 
28213     /**
28214      * @see #onPointerCaptureChange
28215      */
dispatchPointerCaptureChanged(boolean hasCapture)28216     public void dispatchPointerCaptureChanged(boolean hasCapture) {
28217         onPointerCaptureChange(hasCapture);
28218     }
28219 
28220     /**
28221      * Implement this method to handle captured pointer events
28222      *
28223      * @param event The captured pointer event.
28224      * @return True if the event was handled, false otherwise.
28225      * @see #requestPointerCapture()
28226      */
onCapturedPointerEvent(MotionEvent event)28227     public boolean onCapturedPointerEvent(MotionEvent event) {
28228         return false;
28229     }
28230 
28231     /**
28232      * Interface definition for a callback to be invoked when a captured pointer event
28233      * is being dispatched this view. The callback will be invoked before the event is
28234      * given to the view.
28235      */
28236     public interface OnCapturedPointerListener {
28237         /**
28238          * Called when a captured pointer event is dispatched to a view.
28239          * @param view The view this event has been dispatched to.
28240          * @param event The captured event.
28241          * @return True if the listener has consumed the event, false otherwise.
28242          */
onCapturedPointer(View view, MotionEvent event)28243         boolean onCapturedPointer(View view, MotionEvent event);
28244     }
28245 
28246     /**
28247      * Set a listener to receive callbacks when the pointer capture state of a view changes.
28248      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
28249      */
setOnCapturedPointerListener(OnCapturedPointerListener l)28250     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
28251         getListenerInfo().mOnCapturedPointerListener = l;
28252     }
28253 
28254     // Properties
28255     //
28256     /**
28257      * A Property wrapper around the <code>alpha</code> functionality handled by the
28258      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
28259      */
28260     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
28261         @Override
28262         public void setValue(View object, float value) {
28263             object.setAlpha(value);
28264         }
28265 
28266         @Override
28267         public Float get(View object) {
28268             return object.getAlpha();
28269         }
28270     };
28271 
28272     /**
28273      * A Property wrapper around the <code>translationX</code> functionality handled by the
28274      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
28275      */
28276     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
28277         @Override
28278         public void setValue(View object, float value) {
28279             object.setTranslationX(value);
28280         }
28281 
28282                 @Override
28283         public Float get(View object) {
28284             return object.getTranslationX();
28285         }
28286     };
28287 
28288     /**
28289      * A Property wrapper around the <code>translationY</code> functionality handled by the
28290      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
28291      */
28292     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
28293         @Override
28294         public void setValue(View object, float value) {
28295             object.setTranslationY(value);
28296         }
28297 
28298         @Override
28299         public Float get(View object) {
28300             return object.getTranslationY();
28301         }
28302     };
28303 
28304     /**
28305      * A Property wrapper around the <code>translationZ</code> functionality handled by the
28306      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
28307      */
28308     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
28309         @Override
28310         public void setValue(View object, float value) {
28311             object.setTranslationZ(value);
28312         }
28313 
28314         @Override
28315         public Float get(View object) {
28316             return object.getTranslationZ();
28317         }
28318     };
28319 
28320     /**
28321      * A Property wrapper around the <code>x</code> functionality handled by the
28322      * {@link View#setX(float)} and {@link View#getX()} methods.
28323      */
28324     public static final Property<View, Float> X = new FloatProperty<View>("x") {
28325         @Override
28326         public void setValue(View object, float value) {
28327             object.setX(value);
28328         }
28329 
28330         @Override
28331         public Float get(View object) {
28332             return object.getX();
28333         }
28334     };
28335 
28336     /**
28337      * A Property wrapper around the <code>y</code> functionality handled by the
28338      * {@link View#setY(float)} and {@link View#getY()} methods.
28339      */
28340     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
28341         @Override
28342         public void setValue(View object, float value) {
28343             object.setY(value);
28344         }
28345 
28346         @Override
28347         public Float get(View object) {
28348             return object.getY();
28349         }
28350     };
28351 
28352     /**
28353      * A Property wrapper around the <code>z</code> functionality handled by the
28354      * {@link View#setZ(float)} and {@link View#getZ()} methods.
28355      */
28356     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
28357         @Override
28358         public void setValue(View object, float value) {
28359             object.setZ(value);
28360         }
28361 
28362         @Override
28363         public Float get(View object) {
28364             return object.getZ();
28365         }
28366     };
28367 
28368     /**
28369      * A Property wrapper around the <code>rotation</code> functionality handled by the
28370      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
28371      */
28372     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
28373         @Override
28374         public void setValue(View object, float value) {
28375             object.setRotation(value);
28376         }
28377 
28378         @Override
28379         public Float get(View object) {
28380             return object.getRotation();
28381         }
28382     };
28383 
28384     /**
28385      * A Property wrapper around the <code>rotationX</code> functionality handled by the
28386      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
28387      */
28388     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
28389         @Override
28390         public void setValue(View object, float value) {
28391             object.setRotationX(value);
28392         }
28393 
28394         @Override
28395         public Float get(View object) {
28396             return object.getRotationX();
28397         }
28398     };
28399 
28400     /**
28401      * A Property wrapper around the <code>rotationY</code> functionality handled by the
28402      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
28403      */
28404     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
28405         @Override
28406         public void setValue(View object, float value) {
28407             object.setRotationY(value);
28408         }
28409 
28410         @Override
28411         public Float get(View object) {
28412             return object.getRotationY();
28413         }
28414     };
28415 
28416     /**
28417      * A Property wrapper around the <code>scaleX</code> functionality handled by the
28418      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
28419      */
28420     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
28421         @Override
28422         public void setValue(View object, float value) {
28423             object.setScaleX(value);
28424         }
28425 
28426         @Override
28427         public Float get(View object) {
28428             return object.getScaleX();
28429         }
28430     };
28431 
28432     /**
28433      * A Property wrapper around the <code>scaleY</code> functionality handled by the
28434      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
28435      */
28436     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
28437         @Override
28438         public void setValue(View object, float value) {
28439             object.setScaleY(value);
28440         }
28441 
28442         @Override
28443         public Float get(View object) {
28444             return object.getScaleY();
28445         }
28446     };
28447 
28448     /**
28449      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
28450      * Each MeasureSpec represents a requirement for either the width or the height.
28451      * A MeasureSpec is comprised of a size and a mode. There are three possible
28452      * modes:
28453      * <dl>
28454      * <dt>UNSPECIFIED</dt>
28455      * <dd>
28456      * The parent has not imposed any constraint on the child. It can be whatever size
28457      * it wants.
28458      * </dd>
28459      *
28460      * <dt>EXACTLY</dt>
28461      * <dd>
28462      * The parent has determined an exact size for the child. The child is going to be
28463      * given those bounds regardless of how big it wants to be.
28464      * </dd>
28465      *
28466      * <dt>AT_MOST</dt>
28467      * <dd>
28468      * The child can be as large as it wants up to the specified size.
28469      * </dd>
28470      * </dl>
28471      *
28472      * MeasureSpecs are implemented as ints to reduce object allocation. This class
28473      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
28474      */
28475     public static class MeasureSpec {
28476         private static final int MODE_SHIFT = 30;
28477         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
28478 
28479         /** @hide */
28480         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
28481         @Retention(RetentionPolicy.SOURCE)
28482         public @interface MeasureSpecMode {}
28483 
28484         /**
28485          * Measure specification mode: The parent has not imposed any constraint
28486          * on the child. It can be whatever size it wants.
28487          */
28488         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
28489 
28490         /**
28491          * Measure specification mode: The parent has determined an exact size
28492          * for the child. The child is going to be given those bounds regardless
28493          * of how big it wants to be.
28494          */
28495         public static final int EXACTLY     = 1 << MODE_SHIFT;
28496 
28497         /**
28498          * Measure specification mode: The child can be as large as it wants up
28499          * to the specified size.
28500          */
28501         public static final int AT_MOST     = 2 << MODE_SHIFT;
28502 
28503         /**
28504          * Creates a measure specification based on the supplied size and mode.
28505          *
28506          * The mode must always be one of the following:
28507          * <ul>
28508          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
28509          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
28510          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
28511          * </ul>
28512          *
28513          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
28514          * implementation was such that the order of arguments did not matter
28515          * and overflow in either value could impact the resulting MeasureSpec.
28516          * {@link android.widget.RelativeLayout} was affected by this bug.
28517          * Apps targeting API levels greater than 17 will get the fixed, more strict
28518          * behavior.</p>
28519          *
28520          * @param size the size of the measure specification
28521          * @param mode the mode of the measure specification
28522          * @return the measure specification based on size and mode
28523          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)28524         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
28525                                           @MeasureSpecMode int mode) {
28526             if (sUseBrokenMakeMeasureSpec) {
28527                 return size + mode;
28528             } else {
28529                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
28530             }
28531         }
28532 
28533         /**
28534          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
28535          * will automatically get a size of 0. Older apps expect this.
28536          *
28537          * @hide internal use only for compatibility with system widgets and older apps
28538          */
28539         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)28540         public static int makeSafeMeasureSpec(int size, int mode) {
28541             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
28542                 return 0;
28543             }
28544             return makeMeasureSpec(size, mode);
28545         }
28546 
28547         /**
28548          * Extracts the mode from the supplied measure specification.
28549          *
28550          * @param measureSpec the measure specification to extract the mode from
28551          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
28552          *         {@link android.view.View.MeasureSpec#AT_MOST} or
28553          *         {@link android.view.View.MeasureSpec#EXACTLY}
28554          */
28555         @MeasureSpecMode
getMode(int measureSpec)28556         public static int getMode(int measureSpec) {
28557             //noinspection ResourceType
28558             return (measureSpec & MODE_MASK);
28559         }
28560 
28561         /**
28562          * Extracts the size from the supplied measure specification.
28563          *
28564          * @param measureSpec the measure specification to extract the size from
28565          * @return the size in pixels defined in the supplied measure specification
28566          */
getSize(int measureSpec)28567         public static int getSize(int measureSpec) {
28568             return (measureSpec & ~MODE_MASK);
28569         }
28570 
adjust(int measureSpec, int delta)28571         static int adjust(int measureSpec, int delta) {
28572             final int mode = getMode(measureSpec);
28573             int size = getSize(measureSpec);
28574             if (mode == UNSPECIFIED) {
28575                 // No need to adjust size for UNSPECIFIED mode.
28576                 return makeMeasureSpec(size, UNSPECIFIED);
28577             }
28578             size += delta;
28579             if (size < 0) {
28580                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
28581                         ") spec: " + toString(measureSpec) + " delta: " + delta);
28582                 size = 0;
28583             }
28584             return makeMeasureSpec(size, mode);
28585         }
28586 
28587         /**
28588          * Returns a String representation of the specified measure
28589          * specification.
28590          *
28591          * @param measureSpec the measure specification to convert to a String
28592          * @return a String with the following format: "MeasureSpec: MODE SIZE"
28593          */
toString(int measureSpec)28594         public static String toString(int measureSpec) {
28595             int mode = getMode(measureSpec);
28596             int size = getSize(measureSpec);
28597 
28598             StringBuilder sb = new StringBuilder("MeasureSpec: ");
28599 
28600             if (mode == UNSPECIFIED)
28601                 sb.append("UNSPECIFIED ");
28602             else if (mode == EXACTLY)
28603                 sb.append("EXACTLY ");
28604             else if (mode == AT_MOST)
28605                 sb.append("AT_MOST ");
28606             else
28607                 sb.append(mode).append(" ");
28608 
28609             sb.append(size);
28610             return sb.toString();
28611         }
28612     }
28613 
28614     private final class CheckForLongPress implements Runnable {
28615         private int mOriginalWindowAttachCount;
28616         private float mX;
28617         private float mY;
28618         private boolean mOriginalPressedState;
28619         /**
28620          * The classification of the long click being checked: one of the
28621          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
28622          */
28623         private int mClassification;
28624 
28625         @UnsupportedAppUsage
CheckForLongPress()28626         private CheckForLongPress() {
28627         }
28628 
28629         @Override
run()28630         public void run() {
28631             if ((mOriginalPressedState == isPressed()) && (mParent != null)
28632                     && mOriginalWindowAttachCount == mWindowAttachCount) {
28633                 recordGestureClassification(mClassification);
28634                 if (performLongClick(mX, mY)) {
28635                     mHasPerformedLongPress = true;
28636                 }
28637             }
28638         }
28639 
setAnchor(float x, float y)28640         public void setAnchor(float x, float y) {
28641             mX = x;
28642             mY = y;
28643         }
28644 
rememberWindowAttachCount()28645         public void rememberWindowAttachCount() {
28646             mOriginalWindowAttachCount = mWindowAttachCount;
28647         }
28648 
rememberPressedState()28649         public void rememberPressedState() {
28650             mOriginalPressedState = isPressed();
28651         }
28652 
setClassification(int classification)28653         public void setClassification(int classification) {
28654             mClassification = classification;
28655         }
28656     }
28657 
28658     private final class CheckForTap implements Runnable {
28659         public float x;
28660         public float y;
28661 
28662         @Override
run()28663         public void run() {
28664             mPrivateFlags &= ~PFLAG_PREPRESSED;
28665             setPressed(true, x, y);
28666             final long delay =
28667                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
28668             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
28669         }
28670     }
28671 
28672     private final class PerformClick implements Runnable {
28673         @Override
run()28674         public void run() {
28675             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
28676             performClickInternal();
28677         }
28678     }
28679 
28680     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)28681     private void recordGestureClassification(int classification) {
28682         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
28683             return;
28684         }
28685         // To avoid negatively impacting View performance, the latency and displacement metrics
28686         // are omitted.
28687         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
28688                 classification);
28689     }
28690 
28691     /**
28692      * This method returns a ViewPropertyAnimator object, which can be used to animate
28693      * specific properties on this View.
28694      *
28695      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
28696      */
animate()28697     public ViewPropertyAnimator animate() {
28698         if (mAnimator == null) {
28699             mAnimator = new ViewPropertyAnimator(this);
28700         }
28701         return mAnimator;
28702     }
28703 
28704     /**
28705      * Sets the name of the View to be used to identify Views in Transitions.
28706      * Names should be unique in the View hierarchy.
28707      *
28708      * @param transitionName The name of the View to uniquely identify it for Transitions.
28709      */
setTransitionName(String transitionName)28710     public final void setTransitionName(String transitionName) {
28711         mTransitionName = transitionName;
28712     }
28713 
28714     /**
28715      * Returns the name of the View to be used to identify Views in Transitions.
28716      * Names should be unique in the View hierarchy.
28717      *
28718      * <p>This returns null if the View has not been given a name.</p>
28719      *
28720      * @return The name used of the View to be used to identify Views in Transitions or null
28721      * if no name has been given.
28722      */
28723     @ViewDebug.ExportedProperty
28724     @InspectableProperty
getTransitionName()28725     public String getTransitionName() {
28726         return mTransitionName;
28727     }
28728 
28729     /**
28730      * @hide
28731      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)28732     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
28733         // Do nothing.
28734     }
28735 
28736     /**
28737      * Interface definition for a callback to be invoked when a hardware key event is
28738      * dispatched to this view. The callback will be invoked before the key event is
28739      * given to the view. This is only useful for hardware keyboards; a software input
28740      * method has no obligation to trigger this listener.
28741      */
28742     public interface OnKeyListener {
28743         /**
28744          * Called when a hardware key is dispatched to a view. This allows listeners to
28745          * get a chance to respond before the target view.
28746          * <p>Key presses in software keyboards will generally NOT trigger this method,
28747          * although some may elect to do so in some situations. Do not assume a
28748          * software input method has to be key-based; even if it is, it may use key presses
28749          * in a different way than you expect, so there is no way to reliably catch soft
28750          * input key presses.
28751          *
28752          * @param v The view the key has been dispatched to.
28753          * @param keyCode The code for the physical key that was pressed
28754          * @param event The KeyEvent object containing full information about
28755          *        the event.
28756          * @return True if the listener has consumed the event, false otherwise.
28757          */
onKey(View v, int keyCode, KeyEvent event)28758         boolean onKey(View v, int keyCode, KeyEvent event);
28759     }
28760 
28761     /**
28762      * Interface definition for a callback to be invoked when a hardware key event hasn't
28763      * been handled by the view hierarchy.
28764      */
28765     public interface OnUnhandledKeyEventListener {
28766         /**
28767          * Called when a hardware key is dispatched to a view after being unhandled during normal
28768          * {@link KeyEvent} dispatch.
28769          *
28770          * @param v The view the key has been dispatched to.
28771          * @param event The KeyEvent object containing information about the event.
28772          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
28773          */
onUnhandledKeyEvent(View v, KeyEvent event)28774         boolean onUnhandledKeyEvent(View v, KeyEvent event);
28775     }
28776 
28777     /**
28778      * Interface definition for a callback to be invoked when a touch event is
28779      * dispatched to this view. The callback will be invoked before the touch
28780      * event is given to the view.
28781      */
28782     public interface OnTouchListener {
28783         /**
28784          * Called when a touch event is dispatched to a view. This allows listeners to
28785          * get a chance to respond before the target view.
28786          *
28787          * @param v The view the touch event has been dispatched to.
28788          * @param event The MotionEvent object containing full information about
28789          *        the event.
28790          * @return True if the listener has consumed the event, false otherwise.
28791          */
onTouch(View v, MotionEvent event)28792         boolean onTouch(View v, MotionEvent event);
28793     }
28794 
28795     /**
28796      * Interface definition for a callback to be invoked when a hover event is
28797      * dispatched to this view. The callback will be invoked before the hover
28798      * event is given to the view.
28799      */
28800     public interface OnHoverListener {
28801         /**
28802          * Called when a hover event is dispatched to a view. This allows listeners to
28803          * get a chance to respond before the target view.
28804          *
28805          * @param v The view the hover event has been dispatched to.
28806          * @param event The MotionEvent object containing full information about
28807          *        the event.
28808          * @return True if the listener has consumed the event, false otherwise.
28809          */
onHover(View v, MotionEvent event)28810         boolean onHover(View v, MotionEvent event);
28811     }
28812 
28813     /**
28814      * Interface definition for a callback to be invoked when a generic motion event is
28815      * dispatched to this view. The callback will be invoked before the generic motion
28816      * event is given to the view.
28817      */
28818     public interface OnGenericMotionListener {
28819         /**
28820          * Called when a generic motion event is dispatched to a view. This allows listeners to
28821          * get a chance to respond before the target view.
28822          *
28823          * @param v The view the generic motion event has been dispatched to.
28824          * @param event The MotionEvent object containing full information about
28825          *        the event.
28826          * @return True if the listener has consumed the event, false otherwise.
28827          */
onGenericMotion(View v, MotionEvent event)28828         boolean onGenericMotion(View v, MotionEvent event);
28829     }
28830 
28831     /**
28832      * Interface definition for a callback to be invoked when a view has been clicked and held.
28833      */
28834     public interface OnLongClickListener {
28835         /**
28836          * Called when a view has been clicked and held.
28837          *
28838          * @param v The view that was clicked and held.
28839          *
28840          * @return true if the callback consumed the long click, false otherwise.
28841          */
onLongClick(View v)28842         boolean onLongClick(View v);
28843     }
28844 
28845     /**
28846      * Interface definition for a callback to be invoked when a drag is being dispatched
28847      * to this view.  The callback will be invoked before the hosting view's own
28848      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
28849      * onDrag(event) behavior, it should return 'false' from this callback.
28850      *
28851      * <div class="special reference">
28852      * <h3>Developer Guides</h3>
28853      * <p>For a guide to implementing drag and drop features, read the
28854      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
28855      * </div>
28856      */
28857     public interface OnDragListener {
28858         /**
28859          * Called when a drag event is dispatched to a view. This allows listeners
28860          * to get a chance to override base View behavior.
28861          *
28862          * @param v The View that received the drag event.
28863          * @param event The {@link android.view.DragEvent} object for the drag event.
28864          * @return {@code true} if the drag event was handled successfully, or {@code false}
28865          * if the drag event was not handled. Note that {@code false} will trigger the View
28866          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
28867          */
onDrag(View v, DragEvent event)28868         boolean onDrag(View v, DragEvent event);
28869     }
28870 
28871     /**
28872      * Interface definition for a callback to be invoked when the focus state of
28873      * a view changed.
28874      */
28875     public interface OnFocusChangeListener {
28876         /**
28877          * Called when the focus state of a view has changed.
28878          *
28879          * @param v The view whose state has changed.
28880          * @param hasFocus The new focus state of v.
28881          */
onFocusChange(View v, boolean hasFocus)28882         void onFocusChange(View v, boolean hasFocus);
28883     }
28884 
28885     /**
28886      * Interface definition for a callback to be invoked when a view is clicked.
28887      */
28888     public interface OnClickListener {
28889         /**
28890          * Called when a view has been clicked.
28891          *
28892          * @param v The view that was clicked.
28893          */
onClick(View v)28894         void onClick(View v);
28895     }
28896 
28897     /**
28898      * Interface definition for a callback to be invoked when a view is context clicked.
28899      */
28900     public interface OnContextClickListener {
28901         /**
28902          * Called when a view is context clicked.
28903          *
28904          * @param v The view that has been context clicked.
28905          * @return true if the callback consumed the context click, false otherwise.
28906          */
onContextClick(View v)28907         boolean onContextClick(View v);
28908     }
28909 
28910     /**
28911      * Interface definition for a callback to be invoked when the context menu
28912      * for this view is being built.
28913      */
28914     public interface OnCreateContextMenuListener {
28915         /**
28916          * Called when the context menu for this view is being built. It is not
28917          * safe to hold onto the menu after this method returns.
28918          *
28919          * @param menu The context menu that is being built
28920          * @param v The view for which the context menu is being built
28921          * @param menuInfo Extra information about the item for which the
28922          *            context menu should be shown. This information will vary
28923          *            depending on the class of v.
28924          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)28925         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
28926     }
28927 
28928     /**
28929      * Interface definition for a callback to be invoked when the status bar changes
28930      * visibility.  This reports <strong>global</strong> changes to the system UI
28931      * state, not what the application is requesting.
28932      *
28933      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
28934      *
28935      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
28936      * by setting a {@link OnApplyWindowInsetsListener} on this view.
28937      */
28938     @Deprecated
28939     public interface OnSystemUiVisibilityChangeListener {
28940         /**
28941          * Called when the status bar changes visibility because of a call to
28942          * {@link View#setSystemUiVisibility(int)}.
28943          *
28944          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
28945          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
28946          * This tells you the <strong>global</strong> state of these UI visibility
28947          * flags, not what your app is currently applying.
28948          */
onSystemUiVisibilityChange(int visibility)28949         public void onSystemUiVisibilityChange(int visibility);
28950     }
28951 
28952     /**
28953      * Interface definition for a callback to be invoked when this view is attached
28954      * or detached from its window.
28955      */
28956     public interface OnAttachStateChangeListener {
28957         /**
28958          * Called when the view is attached to a window.
28959          * @param v The view that was attached
28960          */
onViewAttachedToWindow(View v)28961         public void onViewAttachedToWindow(View v);
28962         /**
28963          * Called when the view is detached from a window.
28964          * @param v The view that was detached
28965          */
onViewDetachedFromWindow(View v)28966         public void onViewDetachedFromWindow(View v);
28967     }
28968 
28969     /**
28970      * Listener for applying window insets on a view in a custom way.
28971      *
28972      * <p>Apps may choose to implement this interface if they want to apply custom policy
28973      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
28974      * is set, its
28975      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
28976      * method will be called instead of the View's own
28977      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
28978      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
28979      * the View's normal behavior as part of its own.</p>
28980      */
28981     public interface OnApplyWindowInsetsListener {
28982         /**
28983          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
28984          * on a View, this listener method will be called instead of the view's own
28985          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
28986          *
28987          * @param v The view applying window insets
28988          * @param insets The insets to apply
28989          * @return The insets supplied, minus any insets that were consumed
28990          */
onApplyWindowInsets(View v, WindowInsets insets)28991         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
28992     }
28993 
28994     private final class UnsetPressedState implements Runnable {
28995         @Override
run()28996         public void run() {
28997             setPressed(false);
28998         }
28999     }
29000 
29001     /**
29002      * When a view becomes invisible checks if autofill considers the view invisible too. This
29003      * happens after the regular removal operation to make sure the operation is finished by the
29004      * time this is called.
29005      */
29006     private static class VisibilityChangeForAutofillHandler extends Handler {
29007         private final AutofillManager mAfm;
29008         private final View mView;
29009 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)29010         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
29011                 @NonNull View view) {
29012             mAfm = afm;
29013             mView = view;
29014         }
29015 
29016         @Override
handleMessage(Message msg)29017         public void handleMessage(Message msg) {
29018             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
29019         }
29020     }
29021 
29022     /**
29023      * Base class for derived classes that want to save and restore their own
29024      * state in {@link android.view.View#onSaveInstanceState()}.
29025      */
29026     public static class BaseSavedState extends AbsSavedState {
29027         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
29028         static final int IS_AUTOFILLED = 0b10;
29029         static final int AUTOFILL_ID = 0b100;
29030 
29031         // Flags that describe what data in this state is valid
29032         int mSavedData;
29033         String mStartActivityRequestWhoSaved;
29034         boolean mIsAutofilled;
29035         boolean mHideHighlight;
29036         int mAutofillViewId;
29037 
29038         /**
29039          * Constructor used when reading from a parcel. Reads the state of the superclass.
29040          *
29041          * @param source parcel to read from
29042          */
BaseSavedState(Parcel source)29043         public BaseSavedState(Parcel source) {
29044             this(source, null);
29045         }
29046 
29047         /**
29048          * Constructor used when reading from a parcel using a given class loader.
29049          * Reads the state of the superclass.
29050          *
29051          * @param source parcel to read from
29052          * @param loader ClassLoader to use for reading
29053          */
BaseSavedState(Parcel source, ClassLoader loader)29054         public BaseSavedState(Parcel source, ClassLoader loader) {
29055             super(source, loader);
29056             mSavedData = source.readInt();
29057             mStartActivityRequestWhoSaved = source.readString();
29058             mIsAutofilled = source.readBoolean();
29059             mHideHighlight = source.readBoolean();
29060             mAutofillViewId = source.readInt();
29061         }
29062 
29063         /**
29064          * Constructor called by derived classes when creating their SavedState objects
29065          *
29066          * @param superState The state of the superclass of this view
29067          */
BaseSavedState(Parcelable superState)29068         public BaseSavedState(Parcelable superState) {
29069             super(superState);
29070         }
29071 
29072         @Override
writeToParcel(Parcel out, int flags)29073         public void writeToParcel(Parcel out, int flags) {
29074             super.writeToParcel(out, flags);
29075 
29076             out.writeInt(mSavedData);
29077             out.writeString(mStartActivityRequestWhoSaved);
29078             out.writeBoolean(mIsAutofilled);
29079             out.writeBoolean(mHideHighlight);
29080             out.writeInt(mAutofillViewId);
29081         }
29082 
29083         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
29084                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
29085             @Override
29086             public BaseSavedState createFromParcel(Parcel in) {
29087                 return new BaseSavedState(in);
29088             }
29089 
29090             @Override
29091             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
29092                 return new BaseSavedState(in, loader);
29093             }
29094 
29095             @Override
29096             public BaseSavedState[] newArray(int size) {
29097                 return new BaseSavedState[size];
29098             }
29099         };
29100     }
29101 
29102     /**
29103      * A set of information given to a view when it is attached to its parent
29104      * window.
29105      */
29106     final static class AttachInfo {
29107 
29108         interface Callbacks {
playSoundEffect(int effectId)29109             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)29110             boolean performHapticFeedback(int effectId, boolean always);
29111         }
29112 
29113         /**
29114          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
29115          * to a Handler. This class contains the target (View) to invalidate and
29116          * the coordinates of the dirty rectangle.
29117          *
29118          * For performance purposes, this class also implements a pool of up to
29119          * POOL_LIMIT objects that get reused. This reduces memory allocations
29120          * whenever possible.
29121          */
29122         static class InvalidateInfo {
29123 
29124             @UnsupportedAppUsage
InvalidateInfo()29125             InvalidateInfo() {
29126             }
29127 
29128             private static final int POOL_LIMIT = 10;
29129 
29130             private static final SynchronizedPool<InvalidateInfo> sPool =
29131                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
29132 
29133             @UnsupportedAppUsage
29134             View target;
29135 
29136             @UnsupportedAppUsage
29137             int left;
29138             @UnsupportedAppUsage
29139             int top;
29140             @UnsupportedAppUsage
29141             int right;
29142             @UnsupportedAppUsage
29143             int bottom;
29144 
obtain()29145             public static InvalidateInfo obtain() {
29146                 InvalidateInfo instance = sPool.acquire();
29147                 return (instance != null) ? instance : new InvalidateInfo();
29148             }
29149 
recycle()29150             public void recycle() {
29151                 target = null;
29152                 sPool.release(this);
29153             }
29154         }
29155 
29156         @UnsupportedAppUsage
29157         final IWindowSession mSession;
29158 
29159         @UnsupportedAppUsage
29160         final IWindow mWindow;
29161 
29162         final IBinder mWindowToken;
29163 
29164         Display mDisplay;
29165 
29166         final Callbacks mRootCallbacks;
29167 
29168         IWindowId mIWindowId;
29169         WindowId mWindowId;
29170 
29171         /**
29172          * The top view of the hierarchy.
29173          */
29174         View mRootView;
29175 
29176         IBinder mPanelParentWindowToken;
29177 
29178         boolean mHardwareAccelerated;
29179         boolean mHardwareAccelerationRequested;
29180         ThreadedRenderer mThreadedRenderer;
29181         List<RenderNode> mPendingAnimatingRenderNodes;
29182 
29183         /**
29184          * The state of the display to which the window is attached, as reported
29185          * by {@link Display#getState()}.  Note that the display state constants
29186          * declared by {@link Display} do not exactly line up with the screen state
29187          * constants declared by {@link View} (there are more display states than
29188          * screen states).
29189          */
29190         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
29191         int mDisplayState = Display.STATE_UNKNOWN;
29192 
29193         /**
29194          * Scale factor used by the compatibility mode
29195          */
29196         @UnsupportedAppUsage
29197         float mApplicationScale;
29198 
29199         /**
29200          * Indicates whether the application is in compatibility mode
29201          */
29202         @UnsupportedAppUsage
29203         boolean mScalingRequired;
29204 
29205         /**
29206          * Left position of this view's window
29207          */
29208         int mWindowLeft;
29209 
29210         /**
29211          * Top position of this view's window
29212          */
29213         int mWindowTop;
29214 
29215         /**
29216          * Indicates whether views need to use 32-bit drawing caches
29217          */
29218         boolean mUse32BitDrawingCache;
29219 
29220         /**
29221          * For windows that are full-screen but using insets to layout inside
29222          * of the screen decorations, these are the current insets for the
29223          * content of the window.
29224          */
29225         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
29226                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
29227         final Rect mContentInsets = new Rect();
29228 
29229         /**
29230          * For windows that are full-screen but using insets to layout inside
29231          * of the screen decorations, these are the current insets for the
29232          * actual visible parts of the window.
29233          */
29234         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
29235                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
29236         final Rect mVisibleInsets = new Rect();
29237 
29238         /**
29239          * For windows that are full-screen but using insets to layout inside
29240          * of the screen decorations, these are the current insets for the
29241          * stable system windows.
29242          */
29243         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
29244                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
29245         final Rect mStableInsets = new Rect();
29246 
29247         /**
29248          * Current caption insets to the display coordinate.
29249          */
29250         final Rect mCaptionInsets = new Rect();
29251 
29252         /**
29253          * In multi-window we force show the system bars. Because we don't want that the surface
29254          * size changes in this mode, we instead have a flag whether the system bars sizes should
29255          * always be consumed, so the app is treated like there are no virtual system bars at all.
29256          */
29257         boolean mAlwaysConsumeSystemBars;
29258 
29259         /**
29260          * The internal insets given by this window.  This value is
29261          * supplied by the client (through
29262          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
29263          * be given to the window manager when changed to be used in laying
29264          * out windows behind it.
29265          */
29266         @UnsupportedAppUsage
29267         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
29268                 = new ViewTreeObserver.InternalInsetsInfo();
29269 
29270         /**
29271          * Set to true when mGivenInternalInsets is non-empty.
29272          */
29273         boolean mHasNonEmptyGivenInternalInsets;
29274 
29275         /**
29276          * All views in the window's hierarchy that serve as scroll containers,
29277          * used to determine if the window can be resized or must be panned
29278          * to adjust for a soft input area.
29279          */
29280         @UnsupportedAppUsage
29281         final ArrayList<View> mScrollContainers = new ArrayList<View>();
29282 
29283         @UnsupportedAppUsage
29284         final KeyEvent.DispatcherState mKeyDispatchState
29285                 = new KeyEvent.DispatcherState();
29286 
29287         /**
29288          * Indicates whether the view's window currently has the focus.
29289          */
29290         @UnsupportedAppUsage
29291         boolean mHasWindowFocus;
29292 
29293         /**
29294          * The current visibility of the window.
29295          */
29296         int mWindowVisibility;
29297 
29298         /**
29299          * Indicates the time at which drawing started to occur.
29300          */
29301         @UnsupportedAppUsage
29302         long mDrawingTime;
29303 
29304         /**
29305          * Indicates whether the view's window is currently in touch mode.
29306          */
29307         @UnsupportedAppUsage
29308         boolean mInTouchMode;
29309 
29310         /**
29311          * Indicates whether the view has requested unbuffered input dispatching for the current
29312          * event stream.
29313          */
29314         boolean mUnbufferedDispatchRequested;
29315 
29316         /**
29317          * Indicates that ViewAncestor should trigger a global layout change
29318          * the next time it performs a traversal
29319          */
29320         @UnsupportedAppUsage
29321         boolean mRecomputeGlobalAttributes;
29322 
29323         /**
29324          * Always report new attributes at next traversal.
29325          */
29326         boolean mForceReportNewAttributes;
29327 
29328         /**
29329          * Set during a traveral if any views want to keep the screen on.
29330          */
29331         @UnsupportedAppUsage
29332         boolean mKeepScreenOn;
29333 
29334         /**
29335          * Set during a traveral if the light center needs to be updated.
29336          */
29337         boolean mNeedsUpdateLightCenter;
29338 
29339         /**
29340          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
29341          */
29342         int mSystemUiVisibility;
29343 
29344         /**
29345          * Hack to force certain system UI visibility flags to be cleared.
29346          */
29347         int mDisabledSystemUiVisibility;
29348 
29349         /**
29350          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
29351          * attached.
29352          */
29353         boolean mHasSystemUiListeners;
29354 
29355         /**
29356          * Set if the visibility of any views has changed.
29357          */
29358         @UnsupportedAppUsage
29359         boolean mViewVisibilityChanged;
29360 
29361         /**
29362          * Set to true if a view has been scrolled.
29363          */
29364         @UnsupportedAppUsage
29365         boolean mViewScrollChanged;
29366 
29367         /**
29368          * Set to true if a pointer event is currently being handled.
29369          */
29370         boolean mHandlingPointerEvent;
29371 
29372         /**
29373          * The offset of this view's window when it's on an embedded display that is re-parented
29374          * to another window.
29375          */
29376         final Point mLocationInParentDisplay = new Point();
29377 
29378         /**
29379          * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is
29380          * embedded within a SurfaceView.
29381          */
29382         Matrix mScreenMatrixInEmbeddedHierarchy;
29383 
29384         /**
29385          * Global to the view hierarchy used as a temporary for dealing with
29386          * x/y points in the transparent region computations.
29387          */
29388         final int[] mTransparentLocation = new int[2];
29389 
29390         /**
29391          * Global to the view hierarchy used as a temporary for dealing with
29392          * x/y points in the ViewGroup.invalidateChild implementation.
29393          */
29394         final int[] mInvalidateChildLocation = new int[2];
29395 
29396         /**
29397          * Global to the view hierarchy used as a temporary for dealing with
29398          * computing absolute on-screen location.
29399          */
29400         final int[] mTmpLocation = new int[2];
29401 
29402         /**
29403          * Global to the view hierarchy used as a temporary for dealing with
29404          * x/y location when view is transformed.
29405          */
29406         final float[] mTmpTransformLocation = new float[2];
29407 
29408         /**
29409          * The view tree observer used to dispatch global events like
29410          * layout, pre-draw, touch mode change, etc.
29411          */
29412         @UnsupportedAppUsage
29413         final ViewTreeObserver mTreeObserver;
29414 
29415         /**
29416          * A Canvas used by the view hierarchy to perform bitmap caching.
29417          */
29418         Canvas mCanvas;
29419 
29420         /**
29421          * The view root impl.
29422          */
29423         final ViewRootImpl mViewRootImpl;
29424 
29425         /**
29426          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
29427          * handler can be used to pump events in the UI events queue.
29428          */
29429         @UnsupportedAppUsage
29430         final Handler mHandler;
29431 
29432         /**
29433          * Temporary for use in computing invalidate rectangles while
29434          * calling up the hierarchy.
29435          */
29436         final Rect mTmpInvalRect = new Rect();
29437 
29438         /**
29439          * Temporary for use in computing hit areas with transformed views
29440          */
29441         final RectF mTmpTransformRect = new RectF();
29442 
29443         /**
29444          * Temporary for use in computing hit areas with transformed views
29445          */
29446         final RectF mTmpTransformRect1 = new RectF();
29447 
29448         /**
29449          * Temporary list of rectanges.
29450          */
29451         final List<RectF> mTmpRectList = new ArrayList<>();
29452 
29453         /**
29454          * Temporary for use in transforming invalidation rect
29455          */
29456         final Matrix mTmpMatrix = new Matrix();
29457 
29458         /**
29459          * Temporary for use in transforming invalidation rect
29460          */
29461         final Transformation mTmpTransformation = new Transformation();
29462 
29463         /**
29464          * Temporary for use in querying outlines from OutlineProviders
29465          */
29466         final Outline mTmpOutline = new Outline();
29467 
29468         /**
29469          * Temporary list for use in collecting focusable descendents of a view.
29470          */
29471         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
29472 
29473         /**
29474          * The id of the window for accessibility purposes.
29475          */
29476         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
29477 
29478         /**
29479          * Flags related to accessibility processing.
29480          *
29481          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
29482          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
29483          */
29484         int mAccessibilityFetchFlags;
29485 
29486         /**
29487          * The drawable for highlighting accessibility focus.
29488          */
29489         Drawable mAccessibilityFocusDrawable;
29490 
29491         /**
29492          * The drawable for highlighting autofilled views.
29493          *
29494          * @see #isAutofilled()
29495          */
29496         Drawable mAutofilledDrawable;
29497 
29498         /**
29499          * Show where the margins, bounds and layout bounds are for each view.
29500          */
29501         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
29502 
29503         /**
29504          * Point used to compute visible regions.
29505          */
29506         final Point mPoint = new Point();
29507 
29508         /**
29509          * Used to track which View originated a requestLayout() call, used when
29510          * requestLayout() is called during layout.
29511          */
29512         View mViewRequestingLayout;
29513 
29514         /**
29515          * Used to track the identity of the current drag operation.
29516          */
29517         IBinder mDragToken;
29518 
29519         /**
29520          * The drag shadow surface for the current drag operation.
29521          */
29522         public Surface mDragSurface;
29523 
29524 
29525         /**
29526          * The view that currently has a tooltip displayed.
29527          */
29528         View mTooltipHost;
29529 
29530         /**
29531          * The initial structure has been reported so the view is ready to report updates.
29532          */
29533         boolean mReadyForContentCaptureUpdates;
29534 
29535         /**
29536          * Map(keyed by session) of content capture events that need to be notified after the view
29537          * hierarchy is traversed: value is either the view itself for appearead events, or its
29538          * autofill id for disappeared.
29539          */
29540         SparseArray<ArrayList<Object>> mContentCaptureEvents;
29541 
29542         /**
29543          * Cached reference to the {@link ContentCaptureManager}.
29544          */
29545         ContentCaptureManager mContentCaptureManager;
29546 
29547         /**
29548          * Listener used to fit content on window level.
29549          */
29550         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
29551 
29552         /**
29553          * The leash token of this view's parent when it's in an embedded hierarchy that is
29554          * re-parented to another window.
29555          */
29556         IBinder mLeashedParentToken;
29557 
29558         /**
29559          * The accessibility view id of this view's parent when it's in an embedded
29560          * hierarchy that is re-parented to another window.
29561          */
29562         int mLeashedParentAccessibilityViewId;
29563 
29564         /**
29565          *
29566          */
29567         ScrollCaptureInternal mScrollCaptureInternal;
29568 
29569         /**
29570          * Creates a new set of attachment information with the specified
29571          * events handler and thread.
29572          *
29573          * @param handler the events handler the view must use
29574          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)29575         AttachInfo(IWindowSession session, IWindow window, Display display,
29576                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
29577                 Context context) {
29578             mSession = session;
29579             mWindow = window;
29580             mWindowToken = window.asBinder();
29581             mDisplay = display;
29582             mViewRootImpl = viewRootImpl;
29583             mHandler = handler;
29584             mRootCallbacks = effectPlayer;
29585             mTreeObserver = new ViewTreeObserver(context);
29586         }
29587 
29588         @Nullable
getContentCaptureManager(@onNull Context context)29589         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
29590             if (mContentCaptureManager != null) {
29591                 return mContentCaptureManager;
29592             }
29593             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
29594             return mContentCaptureManager;
29595         }
29596 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)29597         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
29598             if (mContentCaptureManager == null) {
29599                 return;
29600             }
29601 
29602             ArrayList<Object> events = ensureEvents(
29603                         mContentCaptureManager.getMainContentCaptureSession());
29604             events.add(insets);
29605         }
29606 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)29607         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
29608                 @NonNull View view, boolean appeared) {
29609             ArrayList<Object> events = ensureEvents(session);
29610             events.add(appeared ? view : view.getAutofillId());
29611         }
29612 
29613         @NonNull
ensureEvents(@onNull ContentCaptureSession session)29614         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
29615             if (mContentCaptureEvents == null) {
29616                 // Most of the time there will be just one session, so intial capacity is 1
29617                 mContentCaptureEvents = new SparseArray<>(1);
29618             }
29619             int sessionId = session.getId();
29620             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
29621             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
29622             if (events == null) {
29623                 events = new ArrayList<>();
29624                 mContentCaptureEvents.put(sessionId, events);
29625             }
29626 
29627             return events;
29628         }
29629 
29630         @Nullable
getScrollCaptureInternal()29631         ScrollCaptureInternal getScrollCaptureInternal() {
29632             if (mScrollCaptureInternal != null) {
29633                 mScrollCaptureInternal = new ScrollCaptureInternal();
29634             }
29635             return mScrollCaptureInternal;
29636         }
29637 
getRootSurfaceControl()29638         AttachedSurfaceControl getRootSurfaceControl() {
29639             return mViewRootImpl;
29640         }
29641 
dump(String prefix, PrintWriter writer)29642         public void dump(String prefix, PrintWriter writer) {
29643             String innerPrefix = prefix + "  ";
29644             writer.println(prefix + "AttachInfo:");
29645             writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
29646             writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
29647             writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
29648             writer.println(innerPrefix + "mUnbufferedDispatchRequested="
29649                     + mUnbufferedDispatchRequested);
29650         }
29651     }
29652 
29653     /**
29654      * <p>ScrollabilityCache holds various fields used by a View when scrolling
29655      * is supported. This avoids keeping too many unused fields in most
29656      * instances of View.</p>
29657      */
29658     private static class ScrollabilityCache implements Runnable {
29659 
29660         /**
29661          * Scrollbars are not visible
29662          */
29663         public static final int OFF = 0;
29664 
29665         /**
29666          * Scrollbars are visible
29667          */
29668         public static final int ON = 1;
29669 
29670         /**
29671          * Scrollbars are fading away
29672          */
29673         public static final int FADING = 2;
29674 
29675         public boolean fadeScrollBars;
29676 
29677         public int fadingEdgeLength;
29678         public int scrollBarDefaultDelayBeforeFade;
29679         public int scrollBarFadeDuration;
29680 
29681         public int scrollBarSize;
29682         public int scrollBarMinTouchTarget;
29683         @UnsupportedAppUsage
29684         public ScrollBarDrawable scrollBar;
29685         public float[] interpolatorValues;
29686         @UnsupportedAppUsage
29687         public View host;
29688 
29689         public final Paint paint;
29690         public final Matrix matrix;
29691         public Shader shader;
29692 
29693         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
29694 
29695         private static final float[] OPAQUE = { 255 };
29696         private static final float[] TRANSPARENT = { 0.0f };
29697 
29698         /**
29699          * When fading should start. This time moves into the future every time
29700          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
29701          */
29702         public long fadeStartTime;
29703 
29704 
29705         /**
29706          * The current state of the scrollbars: ON, OFF, or FADING
29707          */
29708         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
29709         public int state = OFF;
29710 
29711         private int mLastColor;
29712 
29713         public final Rect mScrollBarBounds = new Rect();
29714         public final Rect mScrollBarTouchBounds = new Rect();
29715 
29716         public static final int NOT_DRAGGING = 0;
29717         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
29718         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
29719         public int mScrollBarDraggingState = NOT_DRAGGING;
29720 
29721         public float mScrollBarDraggingPos = 0;
29722 
ScrollabilityCache(ViewConfiguration configuration, View host)29723         public ScrollabilityCache(ViewConfiguration configuration, View host) {
29724             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
29725             scrollBarSize = configuration.getScaledScrollBarSize();
29726             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
29727             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
29728             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
29729 
29730             paint = new Paint();
29731             matrix = new Matrix();
29732             // use use a height of 1, and then wack the matrix each time we
29733             // actually use it.
29734             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
29735             paint.setShader(shader);
29736             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
29737 
29738             this.host = host;
29739         }
29740 
setFadeColor(int color)29741         public void setFadeColor(int color) {
29742             if (color != mLastColor) {
29743                 mLastColor = color;
29744 
29745                 if (color != 0) {
29746                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
29747                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
29748                     paint.setShader(shader);
29749                     // Restore the default transfer mode (src_over)
29750                     paint.setXfermode(null);
29751                 } else {
29752                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
29753                     paint.setShader(shader);
29754                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
29755                 }
29756             }
29757         }
29758 
run()29759         public void run() {
29760             long now = AnimationUtils.currentAnimationTimeMillis();
29761             if (now >= fadeStartTime) {
29762 
29763                 // the animation fades the scrollbars out by changing
29764                 // the opacity (alpha) from fully opaque to fully
29765                 // transparent
29766                 int nextFrame = (int) now;
29767                 int framesCount = 0;
29768 
29769                 Interpolator interpolator = scrollBarInterpolator;
29770 
29771                 // Start opaque
29772                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
29773 
29774                 // End transparent
29775                 nextFrame += scrollBarFadeDuration;
29776                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
29777 
29778                 state = FADING;
29779 
29780                 // Kick off the fade animation
29781                 host.invalidate(true);
29782             }
29783         }
29784     }
29785 
29786     private class SendAccessibilityEventThrottle implements Runnable {
29787         public volatile boolean mIsPending;
29788         private AccessibilityEvent mAccessibilityEvent;
29789 
post(AccessibilityEvent accessibilityEvent)29790         public void post(AccessibilityEvent accessibilityEvent) {
29791             updateWithAccessibilityEvent(accessibilityEvent);
29792             if (!mIsPending) {
29793                 mIsPending = true;
29794                 postDelayed(this,
29795                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
29796             }
29797         }
29798 
29799         @Override
run()29800         public void run() {
29801             if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
29802                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
29803             }
29804             reset();
29805         }
29806 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)29807         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
29808             mAccessibilityEvent = accessibilityEvent;
29809         }
29810 
reset()29811         public void reset() {
29812             mIsPending = false;
29813             mAccessibilityEvent = null;
29814         }
29815 
29816     }
29817 
29818     /**
29819      * Resuable callback for sending
29820      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
29821      */
29822     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
29823         public int mDeltaX;
29824         public int mDeltaY;
29825 
29826         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)29827         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
29828             super.updateWithAccessibilityEvent(accessibilityEvent);
29829             mDeltaX += accessibilityEvent.getScrollDeltaX();
29830             mDeltaY += accessibilityEvent.getScrollDeltaY();
29831             accessibilityEvent.setScrollDeltaX(mDeltaX);
29832             accessibilityEvent.setScrollDeltaY(mDeltaY);
29833         }
29834 
29835         @Override
reset()29836         public void reset() {
29837             super.reset();
29838             mDeltaX = 0;
29839             mDeltaY = 0;
29840         }
29841     }
29842     /**
29843      * Remove the pending callback for sending a throttled accessibility event.
29844      */
29845     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)29846     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
29847         if (callback == null || !callback.mIsPending) return;
29848         removeCallbacks(callback);
29849         callback.reset();
29850     }
29851 
29852     /**
29853      * <p>
29854      * This class represents a delegate that can be registered in a {@link View}
29855      * to enhance accessibility support via composition rather via inheritance.
29856      * It is specifically targeted to widget developers that extend basic View
29857      * classes i.e. classes in package android.view, that would like their
29858      * applications to be backwards compatible.
29859      * </p>
29860      * <div class="special reference">
29861      * <h3>Developer Guides</h3>
29862      * <p>For more information about making applications accessible, read the
29863      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
29864      * developer guide.</p>
29865      * </div>
29866      * <p>
29867      * A scenario in which a developer would like to use an accessibility delegate
29868      * is overriding a method introduced in a later API version than the minimal API
29869      * version supported by the application. For example, the method
29870      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
29871      * in API version 4 when the accessibility APIs were first introduced. If a
29872      * developer would like their application to run on API version 4 devices (assuming
29873      * all other APIs used by the application are version 4 or lower) and take advantage
29874      * of this method, instead of overriding the method which would break the application's
29875      * backwards compatibility, they can override the corresponding method in this
29876      * delegate and register the delegate in the target View if the API version of
29877      * the system is high enough, i.e. the API version is the same as or higher than the API
29878      * version that introduced
29879      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
29880      * </p>
29881      * <p>
29882      * Here is an example implementation:
29883      * </p>
29884      * <code><pre><p>
29885      * if (Build.VERSION.SDK_INT >= 14) {
29886      *     // If the API version is equal of higher than the version in
29887      *     // which onInitializeAccessibilityNodeInfo was introduced we
29888      *     // register a delegate with a customized implementation.
29889      *     View view = findViewById(R.id.view_id);
29890      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
29891      *         public void onInitializeAccessibilityNodeInfo(View host,
29892      *                 AccessibilityNodeInfo info) {
29893      *             // Let the default implementation populate the info.
29894      *             super.onInitializeAccessibilityNodeInfo(host, info);
29895      *             // Set some other information.
29896      *             info.setEnabled(host.isEnabled());
29897      *         }
29898      *     });
29899      * }
29900      * </code></pre></p>
29901      * <p>
29902      * This delegate contains methods that correspond to the accessibility methods
29903      * in View. If a delegate has been specified the implementation in View hands
29904      * off handling to the corresponding method in this delegate. The default
29905      * implementation the delegate methods behaves exactly as the corresponding
29906      * method in View for the case of no accessibility delegate been set. Hence,
29907      * to customize the behavior of a View method, clients can override only the
29908      * corresponding delegate method without altering the behavior of the rest
29909      * accessibility related methods of the host view.
29910      * </p>
29911      * <p>
29912      * <strong>Note:</strong> On platform versions prior to
29913      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
29914      * views in the {@code android.widget.*} package are called <i>before</i>
29915      * host methods. This prevents certain properties such as class name from
29916      * being modified by overriding
29917      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
29918      * as any changes will be overwritten by the host class.
29919      * <p>
29920      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
29921      * methods are called <i>after</i> host methods, which all properties to be
29922      * modified without being overwritten by the host class.
29923      */
29924     public static class AccessibilityDelegate {
29925 
29926         /**
29927          * Sends an accessibility event of the given type. If accessibility is not
29928          * enabled this method has no effect.
29929          * <p>
29930          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
29931          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
29932          * been set.
29933          * </p>
29934          *
29935          * @param host The View hosting the delegate.
29936          * @param eventType The type of the event to send.
29937          *
29938          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
29939          */
sendAccessibilityEvent(View host, int eventType)29940         public void sendAccessibilityEvent(View host, int eventType) {
29941             host.sendAccessibilityEventInternal(eventType);
29942         }
29943 
29944         /**
29945          * Performs the specified accessibility action on the view. For
29946          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
29947          * <p>
29948          * The default implementation behaves as
29949          * {@link View#performAccessibilityAction(int, Bundle)
29950          *  View#performAccessibilityAction(int, Bundle)} for the case of
29951          *  no accessibility delegate been set.
29952          * </p>
29953          *
29954          * @param action The action to perform.
29955          * @return Whether the action was performed.
29956          *
29957          * @see View#performAccessibilityAction(int, Bundle)
29958          *      View#performAccessibilityAction(int, Bundle)
29959          */
performAccessibilityAction(View host, int action, Bundle args)29960         public boolean performAccessibilityAction(View host, int action, Bundle args) {
29961             return host.performAccessibilityActionInternal(action, args);
29962         }
29963 
29964         /**
29965          * Sends an accessibility event. This method behaves exactly as
29966          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
29967          * empty {@link AccessibilityEvent} and does not perform a check whether
29968          * accessibility is enabled.
29969          * <p>
29970          * The default implementation behaves as
29971          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29972          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
29973          * the case of no accessibility delegate been set.
29974          * </p>
29975          *
29976          * @param host The View hosting the delegate.
29977          * @param event The event to send.
29978          *
29979          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29980          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29981          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)29982         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
29983             host.sendAccessibilityEventUncheckedInternal(event);
29984         }
29985 
29986         /**
29987          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
29988          * to its children for adding their text content to the event.
29989          * <p>
29990          * The default implementation behaves as
29991          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29992          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
29993          * the case of no accessibility delegate been set.
29994          * </p>
29995          *
29996          * @param host The View hosting the delegate.
29997          * @param event The event.
29998          * @return True if the event population was completed.
29999          *
30000          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30001          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
30002          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)30003         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
30004             return host.dispatchPopulateAccessibilityEventInternal(event);
30005         }
30006 
30007         /**
30008          * Gives a chance to the host View to populate the accessibility event with its
30009          * text content.
30010          * <p>
30011          * The default implementation behaves as
30012          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
30013          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
30014          * the case of no accessibility delegate been set.
30015          * </p>
30016          *
30017          * @param host The View hosting the delegate.
30018          * @param event The accessibility event which to populate.
30019          *
30020          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
30021          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
30022          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)30023         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
30024             host.onPopulateAccessibilityEventInternal(event);
30025         }
30026 
30027         /**
30028          * Initializes an {@link AccessibilityEvent} with information about the
30029          * the host View which is the event source.
30030          * <p>
30031          * The default implementation behaves as
30032          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
30033          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
30034          * the case of no accessibility delegate been set.
30035          * </p>
30036          *
30037          * @param host The View hosting the delegate.
30038          * @param event The event to initialize.
30039          *
30040          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
30041          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
30042          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)30043         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
30044             host.onInitializeAccessibilityEventInternal(event);
30045         }
30046 
30047         /**
30048          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
30049          * <p>
30050          * The default implementation behaves as
30051          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30052          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
30053          * the case of no accessibility delegate been set.
30054          * </p>
30055          *
30056          * @param host The View hosting the delegate.
30057          * @param info The instance to initialize.
30058          *
30059          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30060          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
30061          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)30062         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
30063             host.onInitializeAccessibilityNodeInfoInternal(info);
30064         }
30065 
30066         /**
30067          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
30068          * additional data.
30069          * <p>
30070          * This method only needs to be implemented if the View offers to provide additional data.
30071          * </p>
30072          * <p>
30073          * The default implementation behaves as
30074          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
30075          * for the case where no accessibility delegate is set.
30076          * </p>
30077          *
30078          * @param host The View hosting the delegate. Never {@code null}.
30079          * @param info The info to which to add the extra data. Never {@code null}.
30080          * @param extraDataKey A key specifying the type of extra data to add to the info. The
30081          *                     extra data should be added to the {@link Bundle} returned by
30082          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
30083          *                     {@code null}.
30084          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
30085          *                  May be {@code null} if the if the service provided no arguments.
30086          *
30087          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
30088          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)30089         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
30090                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
30091                 @Nullable Bundle arguments) {
30092             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
30093         }
30094 
30095         /**
30096          * Called when a child of the host View has requested sending an
30097          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
30098          * to augment the event.
30099          * <p>
30100          * The default implementation behaves as
30101          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30102          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
30103          * the case of no accessibility delegate been set.
30104          * </p>
30105          *
30106          * @param host The View hosting the delegate.
30107          * @param child The child which requests sending the event.
30108          * @param event The event to be sent.
30109          * @return True if the event should be sent
30110          *
30111          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30112          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
30113          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)30114         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
30115                 AccessibilityEvent event) {
30116             return host.onRequestSendAccessibilityEventInternal(child, event);
30117         }
30118 
30119         /**
30120          * Gets the provider for managing a virtual view hierarchy rooted at this View
30121          * and reported to {@link android.accessibilityservice.AccessibilityService}s
30122          * that explore the window content.
30123          * <p>
30124          * The default implementation behaves as
30125          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
30126          * the case of no accessibility delegate been set.
30127          * </p>
30128          *
30129          * @return The provider.
30130          *
30131          * @see AccessibilityNodeProvider
30132          */
getAccessibilityNodeProvider(View host)30133         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
30134             return null;
30135         }
30136 
30137         /**
30138          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
30139          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
30140          * This method is responsible for obtaining an accessibility node info from a
30141          * pool of reusable instances and calling
30142          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
30143          * view to initialize the former.
30144          * <p>
30145          * <strong>Note:</strong> The client is responsible for recycling the obtained
30146          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
30147          * creation.
30148          * </p>
30149          * <p>
30150          * The default implementation behaves as
30151          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
30152          * the case of no accessibility delegate been set.
30153          * </p>
30154          * @return A populated {@link AccessibilityNodeInfo}.
30155          *
30156          * @see AccessibilityNodeInfo
30157          *
30158          * @hide
30159          */
30160         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
createAccessibilityNodeInfo(View host)30161         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
30162             return host.createAccessibilityNodeInfoInternal();
30163         }
30164     }
30165 
30166     private static class MatchIdPredicate implements Predicate<View> {
30167         public int mId;
30168 
30169         @Override
test(View view)30170         public boolean test(View view) {
30171             return (view.mID == mId);
30172         }
30173     }
30174 
30175     private static class MatchLabelForPredicate implements Predicate<View> {
30176         private int mLabeledId;
30177 
30178         @Override
test(View view)30179         public boolean test(View view) {
30180             return (view.mLabelForId == mLabeledId);
30181         }
30182     }
30183 
30184 
30185     /**
30186      * Returns the current scroll capture hint for this view.
30187      *
30188      * @return the current scroll capture hint
30189      */
30190     @ScrollCaptureHint
getScrollCaptureHint()30191     public int getScrollCaptureHint() {
30192         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
30193                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
30194     }
30195 
30196     /**
30197      * Sets the scroll capture hint for this View. These flags affect the search for a potential
30198      * scroll capture targets.
30199      *
30200      * @param hint the scrollCaptureHint flags value to set
30201      */
setScrollCaptureHint(@crollCaptureHint int hint)30202     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
30203         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
30204         // Since include/exclude are mutually exclusive, exclude takes precedence.
30205         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
30206             hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
30207         }
30208         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
30209                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
30210     }
30211 
30212     /**
30213      * Sets the callback to receive scroll capture requests. This component is the adapter between
30214      * the scroll capture API and application UI code. If no callback is set, the system may provide
30215      * an implementation. Any value provided here will take precedence over a system version.
30216      * <p>
30217      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
30218      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
30219      * <p>
30220      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
30221      * setting a custom callback to help ensure it is selected as the target.
30222      *
30223      * @param callback the new callback to assign
30224      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)30225     public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
30226         getListenerInfo().mScrollCaptureCallback = callback;
30227     }
30228 
30229     /** {@hide} */
30230     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)30231     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
30232             @NonNull Point windowOffset) {
30233         if (mAttachInfo == null) {
30234             return null;
30235         }
30236         if (mAttachInfo.mScrollCaptureInternal == null) {
30237             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
30238         }
30239         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
30240                 windowOffset);
30241     }
30242 
30243     /**
30244      * Dispatch a scroll capture search request down the view hierarchy.
30245      *
30246      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
30247      *                         the parent
30248      * @param windowOffset     the offset of this view within the window
30249      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
30250      *                         results.accept} may be called zero or more times on the calling
30251      *                         thread before onScrollCaptureSearch returns
30252      */
dispatchScrollCaptureSearch( @onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)30253     public void dispatchScrollCaptureSearch(
30254             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
30255             @NonNull Consumer<ScrollCaptureTarget> targets) {
30256         onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
30257     }
30258 
30259     /**
30260      * Called when scroll capture is requested, to search for appropriate content to scroll. If
30261      * applicable, this view adds itself to the provided list for consideration, subject to the
30262      * flags set by {@link #setScrollCaptureHint}.
30263      *
30264      * @param localVisibleRect the local visible rect of this view
30265      * @param windowOffset     the offset of localVisibleRect within the window
30266      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
30267      *                         results.accept} may be called zero or more times on the calling
30268      *                         thread before onScrollCaptureSearch returns
30269      * @throws IllegalStateException if this view is not attached to a window
30270      */
onScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)30271     public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
30272             @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
30273         int hint = getScrollCaptureHint();
30274         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
30275             return;
30276         }
30277         boolean rectIsVisible = true;
30278 
30279         // Apply clipBounds if present.
30280         if (mClipBounds != null) {
30281             rectIsVisible = localVisibleRect.intersect(mClipBounds);
30282         }
30283         if (!rectIsVisible) {
30284             return;
30285         }
30286 
30287         // Get a callback provided by the framework, library or application.
30288         ScrollCaptureCallback callback =
30289                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
30290 
30291         // Try framework support for standard scrolling containers.
30292         if (callback == null) {
30293             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
30294         }
30295 
30296         // If found, then add it to the list.
30297         if (callback != null) {
30298             // Add to the list for consideration
30299             Point offset = new Point(windowOffset.x, windowOffset.y);
30300             Rect rect = new Rect(localVisibleRect);
30301             targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
30302         }
30303     }
30304 
30305     /**
30306      * Dump all private flags in readable format, useful for documentation and
30307      * consistency checking.
30308      */
dumpFlags()30309     private static void dumpFlags() {
30310         final HashMap<String, String> found = Maps.newHashMap();
30311         try {
30312             for (Field field : View.class.getDeclaredFields()) {
30313                 final int modifiers = field.getModifiers();
30314                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
30315                     if (field.getType().equals(int.class)) {
30316                         final int value = field.getInt(null);
30317                         dumpFlag(found, field.getName(), value);
30318                     } else if (field.getType().equals(int[].class)) {
30319                         final int[] values = (int[]) field.get(null);
30320                         for (int i = 0; i < values.length; i++) {
30321                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
30322                         }
30323                     }
30324                 }
30325             }
30326         } catch (IllegalAccessException e) {
30327             throw new RuntimeException(e);
30328         }
30329 
30330         final ArrayList<String> keys = Lists.newArrayList();
30331         keys.addAll(found.keySet());
30332         Collections.sort(keys);
30333         for (String key : keys) {
30334             Log.d(VIEW_LOG_TAG, found.get(key));
30335         }
30336     }
30337 
dumpFlag(HashMap<String, String> found, String name, int value)30338     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
30339         // Sort flags by prefix, then by bits, always keeping unique keys
30340         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
30341         final int prefix = name.indexOf('_');
30342         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
30343         final String output = bits + " " + name;
30344         found.put(key, output);
30345     }
30346 
30347     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)30348     public void encode(@NonNull ViewHierarchyEncoder stream) {
30349         stream.beginObject(this);
30350         encodeProperties(stream);
30351         stream.endObject();
30352     }
30353 
30354     /** {@hide} */
30355     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)30356     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
30357         Object resolveId = ViewDebug.resolveId(getContext(), mID);
30358         if (resolveId instanceof String) {
30359             stream.addProperty("id", (String) resolveId);
30360         } else {
30361             stream.addProperty("id", mID);
30362         }
30363 
30364         stream.addProperty("misc:transformation.alpha",
30365                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
30366         stream.addProperty("misc:transitionName", getTransitionName());
30367 
30368         // layout
30369         stream.addProperty("layout:left", mLeft);
30370         stream.addProperty("layout:right", mRight);
30371         stream.addProperty("layout:top", mTop);
30372         stream.addProperty("layout:bottom", mBottom);
30373         stream.addProperty("layout:width", getWidth());
30374         stream.addProperty("layout:height", getHeight());
30375         stream.addProperty("layout:layoutDirection", getLayoutDirection());
30376         stream.addProperty("layout:layoutRtl", isLayoutRtl());
30377         stream.addProperty("layout:hasTransientState", hasTransientState());
30378         stream.addProperty("layout:baseline", getBaseline());
30379 
30380         // layout params
30381         ViewGroup.LayoutParams layoutParams = getLayoutParams();
30382         if (layoutParams != null) {
30383             stream.addPropertyKey("layoutParams");
30384             layoutParams.encode(stream);
30385         }
30386 
30387         // scrolling
30388         stream.addProperty("scrolling:scrollX", mScrollX);
30389         stream.addProperty("scrolling:scrollY", mScrollY);
30390 
30391         // padding
30392         stream.addProperty("padding:paddingLeft", mPaddingLeft);
30393         stream.addProperty("padding:paddingRight", mPaddingRight);
30394         stream.addProperty("padding:paddingTop", mPaddingTop);
30395         stream.addProperty("padding:paddingBottom", mPaddingBottom);
30396         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
30397         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
30398         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
30399         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
30400         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
30401 
30402         // measurement
30403         stream.addProperty("measurement:minHeight", mMinHeight);
30404         stream.addProperty("measurement:minWidth", mMinWidth);
30405         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
30406         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
30407 
30408         // drawing
30409         stream.addProperty("drawing:elevation", getElevation());
30410         stream.addProperty("drawing:translationX", getTranslationX());
30411         stream.addProperty("drawing:translationY", getTranslationY());
30412         stream.addProperty("drawing:translationZ", getTranslationZ());
30413         stream.addProperty("drawing:rotation", getRotation());
30414         stream.addProperty("drawing:rotationX", getRotationX());
30415         stream.addProperty("drawing:rotationY", getRotationY());
30416         stream.addProperty("drawing:scaleX", getScaleX());
30417         stream.addProperty("drawing:scaleY", getScaleY());
30418         stream.addProperty("drawing:pivotX", getPivotX());
30419         stream.addProperty("drawing:pivotY", getPivotY());
30420         stream.addProperty("drawing:clipBounds",
30421                 mClipBounds == null ? null : mClipBounds.toString());
30422         stream.addProperty("drawing:opaque", isOpaque());
30423         stream.addProperty("drawing:alpha", getAlpha());
30424         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
30425         stream.addProperty("drawing:shadow", hasShadow());
30426         stream.addProperty("drawing:solidColor", getSolidColor());
30427         stream.addProperty("drawing:layerType", mLayerType);
30428         stream.addProperty("drawing:willNotDraw", willNotDraw());
30429         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
30430         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
30431         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
30432         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
30433         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
30434         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
30435 
30436         // focus
30437         stream.addProperty("focus:hasFocus", hasFocus());
30438         stream.addProperty("focus:isFocused", isFocused());
30439         stream.addProperty("focus:focusable", getFocusable());
30440         stream.addProperty("focus:isFocusable", isFocusable());
30441         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
30442 
30443         stream.addProperty("misc:clickable", isClickable());
30444         stream.addProperty("misc:pressed", isPressed());
30445         stream.addProperty("misc:selected", isSelected());
30446         stream.addProperty("misc:touchMode", isInTouchMode());
30447         stream.addProperty("misc:hovered", isHovered());
30448         stream.addProperty("misc:activated", isActivated());
30449 
30450         stream.addProperty("misc:visibility", getVisibility());
30451         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
30452         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
30453 
30454         stream.addProperty("misc:enabled", isEnabled());
30455         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
30456         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
30457 
30458         // theme attributes
30459         Resources.Theme theme = getContext().getTheme();
30460         if (theme != null) {
30461             stream.addPropertyKey("theme");
30462             theme.encode(stream);
30463         }
30464 
30465         // view attribute information
30466         int n = mAttributes != null ? mAttributes.length : 0;
30467         stream.addProperty("meta:__attrCount__", n/2);
30468         for (int i = 0; i < n; i += 2) {
30469             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
30470         }
30471 
30472         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
30473 
30474         // text
30475         stream.addProperty("text:textDirection", getTextDirection());
30476         stream.addProperty("text:textAlignment", getTextAlignment());
30477 
30478         // accessibility
30479         CharSequence contentDescription = getContentDescription();
30480         stream.addUserProperty("accessibility:contentDescription",
30481                 contentDescription == null ? "" : contentDescription.toString());
30482         stream.addProperty("accessibility:labelFor", getLabelFor());
30483         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
30484     }
30485 
30486     /**
30487      * Determine if this view is rendered on a round wearable device and is the main view
30488      * on the screen.
30489      */
shouldDrawRoundScrollbar()30490     boolean shouldDrawRoundScrollbar() {
30491         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
30492             return false;
30493         }
30494 
30495         final View rootView = getRootView();
30496         final WindowInsets insets = getRootWindowInsets();
30497 
30498         int height = getHeight();
30499         int width = getWidth();
30500         int displayHeight = rootView.getHeight();
30501         int displayWidth = rootView.getWidth();
30502 
30503         if (height != displayHeight || width != displayWidth) {
30504             return false;
30505         }
30506 
30507         getLocationInWindow(mAttachInfo.mTmpLocation);
30508         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
30509                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
30510     }
30511 
30512     /**
30513      * Sets the tooltip text which will be displayed in a small popup next to the view.
30514      * <p>
30515      * The tooltip will be displayed:
30516      * <ul>
30517      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
30518      * menu). </li>
30519      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
30520      * </ul>
30521      * <p>
30522      * <strong>Note:</strong> Do not override this method, as it will have no
30523      * effect on the text displayed in the tooltip.
30524      *
30525      * @param tooltipText the tooltip text, or null if no tooltip is required
30526      * @see #getTooltipText()
30527      * @attr ref android.R.styleable#View_tooltipText
30528      */
setTooltipText(@ullable CharSequence tooltipText)30529     public void setTooltipText(@Nullable CharSequence tooltipText) {
30530         if (TextUtils.isEmpty(tooltipText)) {
30531             setFlags(0, TOOLTIP);
30532             hideTooltip();
30533             mTooltipInfo = null;
30534         } else {
30535             setFlags(TOOLTIP, TOOLTIP);
30536             if (mTooltipInfo == null) {
30537                 mTooltipInfo = new TooltipInfo();
30538                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
30539                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
30540                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
30541                 mTooltipInfo.clearAnchorPos();
30542             }
30543             mTooltipInfo.mTooltipText = tooltipText;
30544         }
30545     }
30546 
30547     /**
30548      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
30549      */
30550     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)30551     public void setTooltip(@Nullable CharSequence tooltipText) {
30552         setTooltipText(tooltipText);
30553     }
30554 
30555     /**
30556      * Returns the view's tooltip text.
30557      *
30558      * <strong>Note:</strong> Do not override this method, as it will have no
30559      * effect on the text displayed in the tooltip. You must call
30560      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
30561      *
30562      * @return the tooltip text
30563      * @see #setTooltipText(CharSequence)
30564      * @attr ref android.R.styleable#View_tooltipText
30565      */
30566     @InspectableProperty
30567     @Nullable
getTooltipText()30568     public CharSequence getTooltipText() {
30569         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
30570     }
30571 
30572     /**
30573      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
30574      */
30575     @Nullable
getTooltip()30576     public CharSequence getTooltip() {
30577         return getTooltipText();
30578     }
30579 
showTooltip(int x, int y, boolean fromLongClick)30580     private boolean showTooltip(int x, int y, boolean fromLongClick) {
30581         if (mAttachInfo == null || mTooltipInfo == null) {
30582             return false;
30583         }
30584         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
30585             return false;
30586         }
30587         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
30588             return false;
30589         }
30590         hideTooltip();
30591         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
30592         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
30593         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
30594         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
30595         mAttachInfo.mTooltipHost = this;
30596         // The available accessibility actions have changed
30597         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
30598         return true;
30599     }
30600 
30601     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hideTooltip()30602     void hideTooltip() {
30603         if (mTooltipInfo == null) {
30604             return;
30605         }
30606         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30607         if (mTooltipInfo.mTooltipPopup == null) {
30608             return;
30609         }
30610         mTooltipInfo.mTooltipPopup.hide();
30611         mTooltipInfo.mTooltipPopup = null;
30612         mTooltipInfo.mTooltipFromLongClick = false;
30613         mTooltipInfo.clearAnchorPos();
30614         if (mAttachInfo != null) {
30615             mAttachInfo.mTooltipHost = null;
30616         }
30617         // The available accessibility actions have changed
30618         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
30619     }
30620 
showLongClickTooltip(int x, int y)30621     private boolean showLongClickTooltip(int x, int y) {
30622         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30623         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30624         return showTooltip(x, y, true);
30625     }
30626 
showHoverTooltip()30627     private boolean showHoverTooltip() {
30628         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
30629     }
30630 
dispatchTooltipHoverEvent(MotionEvent event)30631     boolean dispatchTooltipHoverEvent(MotionEvent event) {
30632         if (mTooltipInfo == null) {
30633             return false;
30634         }
30635         switch(event.getAction()) {
30636             case MotionEvent.ACTION_HOVER_MOVE:
30637                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
30638                     break;
30639                 }
30640                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
30641                     if (mTooltipInfo.mTooltipPopup == null) {
30642                         // Schedule showing the tooltip after a timeout.
30643                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30644                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
30645                                 ViewConfiguration.getHoverTooltipShowTimeout());
30646                     }
30647 
30648                     // Hide hover-triggered tooltip after a period of inactivity.
30649                     // Match the timeout used by NativeInputManager to hide the mouse pointer
30650                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
30651                     final int timeout;
30652                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
30653                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
30654                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
30655                     } else {
30656                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
30657                     }
30658                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30659                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
30660                 }
30661                 return true;
30662 
30663             case MotionEvent.ACTION_HOVER_EXIT:
30664                 mTooltipInfo.clearAnchorPos();
30665                 if (!mTooltipInfo.mTooltipFromLongClick) {
30666                     hideTooltip();
30667                 }
30668                 break;
30669         }
30670         return false;
30671     }
30672 
handleTooltipKey(KeyEvent event)30673     void handleTooltipKey(KeyEvent event) {
30674         switch (event.getAction()) {
30675             case KeyEvent.ACTION_DOWN:
30676                 if (event.getRepeatCount() == 0) {
30677                     hideTooltip();
30678                 }
30679                 break;
30680 
30681             case KeyEvent.ACTION_UP:
30682                 handleTooltipUp();
30683                 break;
30684         }
30685     }
30686 
handleTooltipUp()30687     private void handleTooltipUp() {
30688         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
30689             return;
30690         }
30691         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30692         postDelayed(mTooltipInfo.mHideTooltipRunnable,
30693                 ViewConfiguration.getLongPressTooltipHideTimeout());
30694     }
30695 
getFocusableAttribute(TypedArray attributes)30696     private int getFocusableAttribute(TypedArray attributes) {
30697         TypedValue val = new TypedValue();
30698         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
30699             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
30700                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
30701             } else {
30702                 return val.data;
30703             }
30704         } else {
30705             return FOCUSABLE_AUTO;
30706         }
30707     }
30708 
30709     /**
30710      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
30711      * is not showing.
30712      * @hide
30713      */
30714     @TestApi
getTooltipView()30715     public View getTooltipView() {
30716         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
30717             return null;
30718         }
30719         return mTooltipInfo.mTooltipPopup.getContentView();
30720     }
30721 
30722     /**
30723      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
30724      * @hide
30725      */
30726     @TestApi
isDefaultFocusHighlightEnabled()30727     public static boolean isDefaultFocusHighlightEnabled() {
30728         return sUseDefaultFocusHighlight;
30729     }
30730 
30731     /**
30732      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
30733      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
30734      * (visually on-top views first).
30735      *
30736      * @param evt the previously unhandled {@link KeyEvent}.
30737      * @return the {@link View} which consumed the event or {@code null} if not consumed.
30738      */
dispatchUnhandledKeyEvent(KeyEvent evt)30739     View dispatchUnhandledKeyEvent(KeyEvent evt) {
30740         if (onUnhandledKeyEvent(evt)) {
30741             return this;
30742         }
30743         return null;
30744     }
30745 
30746     /**
30747      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
30748      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
30749      * this will dispatch into all the listeners registered via
30750      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
30751      * order (most recently added will receive events first).
30752      *
30753      * @param event An unhandled event.
30754      * @return {@code true} if the event was handled, {@code false} otherwise.
30755      * @see #addOnUnhandledKeyEventListener
30756      */
onUnhandledKeyEvent(@onNull KeyEvent event)30757     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
30758         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
30759             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
30760                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
30761                     return true;
30762                 }
30763             }
30764         }
30765         return false;
30766     }
30767 
hasUnhandledKeyListener()30768     boolean hasUnhandledKeyListener() {
30769         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
30770                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
30771     }
30772 
30773     /**
30774      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
30775      * UI thread.
30776      *
30777      * @param listener a receiver of unhandled {@link KeyEvent}s.
30778      * @see #removeOnUnhandledKeyEventListener
30779      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)30780     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
30781         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
30782         if (listeners == null) {
30783             listeners = new ArrayList<>();
30784             getListenerInfo().mUnhandledKeyListeners = listeners;
30785         }
30786         listeners.add(listener);
30787         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
30788             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
30789         }
30790     }
30791 
30792     /**
30793      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
30794      * UI thread.
30795      *
30796      * @param listener a receiver of unhandled {@link KeyEvent}s.
30797      * @see #addOnUnhandledKeyEventListener
30798      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)30799     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
30800         if (mListenerInfo != null) {
30801             if (mListenerInfo.mUnhandledKeyListeners != null
30802                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
30803                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
30804                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
30805                     mListenerInfo.mUnhandledKeyListeners = null;
30806                     if (mParent instanceof ViewGroup) {
30807                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
30808                     }
30809                 }
30810             }
30811         }
30812     }
30813 
30814     /**
30815      * Set the view to be detached or not detached.
30816      *
30817      * @param detached Whether the view is detached.
30818      *
30819      * @hide
30820      */
setDetached(boolean detached)30821     protected void setDetached(boolean detached) {
30822         if (detached) {
30823             mPrivateFlags4 |= PFLAG4_DETACHED;
30824         } else {
30825             mPrivateFlags4 &= ~PFLAG4_DETACHED;
30826         }
30827     }
30828 
30829     /**
30830      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
30831      * the view.
30832      *
30833      * <p>The default implementation does nothing.</p>
30834      *
30835      * @param supportedFormats the supported translation formats. For now, the only possible value
30836      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
30837      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to
30838      * collect the information to be translated in the view. The {@code requestsCollector} only
30839      * accepts one request; an IllegalStateException is thrown if more than one
30840      * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the
30841      * {@link ViewTranslationRequest}.
30842      */
onCreateViewTranslationRequest(@onNull @ataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)30843     public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
30844             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
30845     }
30846 
30847     /**
30848      * Collects {@link ViewTranslationRequest}s which represents the content to be translated
30849      * for the virtual views in the host view. This is called if this view returned a virtual
30850      * view structure from {@link #onProvideContentCaptureStructure} and the system determined that
30851      * those virtual views were relevant for translation.
30852      *
30853      * <p>The default implementation does nothing.</p>
30854      *
30855      * @param virtualIds the virtual view ids which represents the virtual views in the host
30856      * view.
30857      * @param supportedFormats the supported translation formats. For now, the only possible value
30858      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
30859      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
30860      * multiple times to collect the information to be translated in the host view. One
30861      * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
30862      * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
30863      * Consumer after the method returns.
30864      */
30865     @SuppressLint("NullableCollection")
onCreateVirtualViewTranslationRequests(@onNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)30866     public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
30867             @NonNull @DataFormat int[] supportedFormats,
30868             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
30869         // no-op
30870     }
30871 
30872     /**
30873      * Returns a {@link ViewTranslationCallback} that is used to display the translated information
30874      * or {@code null} if this View doesn't support translation.
30875      *
30876      * @hide
30877      */
30878     @Nullable
getViewTranslationCallback()30879     public ViewTranslationCallback getViewTranslationCallback() {
30880         return mViewTranslationCallback;
30881     }
30882 
30883     /**
30884      * Sets a {@link ViewTranslationCallback} that is used to display/hide the translated
30885      * information. Developers can provide the customized implementation for show/hide translated
30886      * information.
30887      *
30888      * @param callback a {@link ViewTranslationCallback} that is used to control how to display the
30889      * translated information
30890      */
setViewTranslationCallback(@onNull ViewTranslationCallback callback)30891     public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
30892         mViewTranslationCallback = callback;
30893     }
30894 
30895     /**
30896      * Clear the {@link ViewTranslationCallback} from this view.
30897      */
clearViewTranslationCallback()30898     public void clearViewTranslationCallback() {
30899         mViewTranslationCallback = null;
30900     }
30901 
30902     /**
30903      * Returns the {@link ViewTranslationResponse} associated with this view. The response will be
30904      * set when the translation is done then {@link #onViewTranslationResponse} is called. The
30905      * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the
30906      * translated information.
30907      *
30908      * @return a {@link ViewTranslationResponse} that contains the translated information associated
30909      * with this view or {@code null} if this View doesn't have the translation.
30910      */
30911     @Nullable
getViewTranslationResponse()30912     public ViewTranslationResponse getViewTranslationResponse() {
30913         return mViewTranslationResponse;
30914     }
30915 
30916     /**
30917      * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated
30918      * by the TranslationService. The {@link ViewTranslationResponse} should be saved here so that
30919      * the {@link ViewTranslationResponse} can be used to display the translation when the system
30920      * calls {@link ViewTranslationCallback#onShowTranslation}.
30921      *
30922      * <p> The default implementation will set the ViewTranslationResponse that can be get from
30923      * {@link View#getViewTranslationResponse}. </p>
30924      *
30925      * @param response a {@link ViewTranslationResponse} that contains the translated information
30926      * which can be shown in the view.
30927      */
onViewTranslationResponse(@onNull ViewTranslationResponse response)30928     public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
30929         mViewTranslationResponse = response;
30930     }
30931 
30932     /**
30933      * Clears the ViewTranslationResponse stored by the default implementation of {@link
30934      * #onViewTranslationResponse}.
30935      *
30936      * @hide
30937      */
clearViewTranslationResponse()30938     public void clearViewTranslationResponse() {
30939         mViewTranslationResponse = null;
30940     }
30941 
30942     /**
30943      * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
30944      * translated by the TranslationService.
30945      *
30946      * <p> The default implementation does nothing.</p>
30947      *
30948      * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
30949      * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information
30950      * which can be shown in the view. The key of SparseArray is the virtual child ids.
30951      */
onVirtualViewTranslationResponses( @onNull LongSparseArray<ViewTranslationResponse> response)30952     public void onVirtualViewTranslationResponses(
30953             @NonNull LongSparseArray<ViewTranslationResponse> response) {
30954         // no-op
30955     }
30956 
30957     /**
30958      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
30959      * the hierarchy when the app requests ui translation. Typically, this method should only be
30960      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
30961      * classes should override {@link View#onCreateViewTranslationRequest} for normal view or
30962      * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children.
30963      * When requested to start the ui translation, the system will call this method to traverse the
30964      * view hierarchy to collect {@link ViewTranslationRequest}s and create a
30965      * {@link android.view.translation.Translator} to translate the requests. All the
30966      * {@link ViewTranslationRequest}s must be added when the traversal is done.
30967      *
30968      * <p> The default implementation calls {@link View#onCreateViewTranslationRequest} for normal
30969      * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
30970      * children to build {@link ViewTranslationRequest} if the view should be translated.
30971      * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
30972      * recycling of views doesn't prevent the system from attaching the response to it. Therefore,
30973      * if overriding this method, you should set or reset the transient state. </p>
30974      *
30975      * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
30976      * {@code null} if the view doesn't have virtual child that should be translated. The virtual
30977      * child ids are the same virtual ids provided by ContentCapture.
30978      * @param supportedFormats the supported translation formats. For now, the only possible value
30979      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
30980      * @param capability a {@link TranslationCapability} that holds translation capability.
30981      * information, e.g. source spec, target spec.
30982      * @param requests fill in with {@link ViewTranslationRequest}s for translation purpose.
30983      */
dispatchCreateViewTranslationRequest(@onNull Map<AutofillId, long[]> viewIds, @NonNull @DataFormat int[] supportedFormats, @NonNull TranslationCapability capability, @NonNull List<ViewTranslationRequest> requests)30984     public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
30985             @NonNull @DataFormat int[] supportedFormats,
30986             @NonNull TranslationCapability capability,
30987             @NonNull List<ViewTranslationRequest> requests) {
30988         AutofillId autofillId = getAutofillId();
30989         if (viewIds.containsKey(autofillId)) {
30990             if (viewIds.get(autofillId) == null) {
30991                 // TODO: avoiding the allocation per view
30992                 onCreateViewTranslationRequest(supportedFormats,
30993                         new ViewTranslationRequestConsumer(requests));
30994             } else {
30995                 onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
30996                         request -> {
30997                             requests.add(request);
30998                         });
30999             }
31000         }
31001     }
31002 
31003     private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
31004         private final List<ViewTranslationRequest> mRequests;
31005         private boolean mCalled;
31006 
ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests)31007         ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
31008             mRequests = requests;
31009         }
31010 
31011         @Override
accept(ViewTranslationRequest request)31012         public void accept(ViewTranslationRequest request) {
31013             if (mCalled) {
31014                 throw new IllegalStateException("The translation Consumer is not reusable.");
31015             }
31016             mCalled = true;
31017             if (request != null && request.getKeys().size() > 0) {
31018                 mRequests.add(request);
31019                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
31020                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
31021                             + getAutofillId());
31022                 }
31023                 setHasTransientState(true);
31024                 setHasTranslationTransientState(true);
31025             }
31026         }
31027     }
31028 
31029     /**
31030      * Called to generate a {@link DisplayHash} for this view.
31031      *
31032      * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
31033      *                      the values returned from
31034      *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
31035      * @param bounds The bounds for the content within the View to generate the hash for. If
31036      *               bounds are null, the entire View's bounds will be used. If empty, it will
31037      *               invoke the callback
31038      *               {@link DisplayHashResultCallback#onDisplayHashError} with error
31039      *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
31040      * @param executor The executor that the callback should be invoked on.
31041      * @param callback The callback to handle the results of generating the display hash
31042      */
generateDisplayHash(@onNull String hashAlgorithm, @Nullable Rect bounds, @NonNull Executor executor, @NonNull DisplayHashResultCallback callback)31043     public void generateDisplayHash(@NonNull String hashAlgorithm,
31044             @Nullable Rect bounds, @NonNull Executor executor,
31045             @NonNull DisplayHashResultCallback callback) {
31046         IWindowSession session = getWindowSession();
31047         if (session == null) {
31048             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
31049             return;
31050         }
31051         IWindow window = getWindow();
31052         if (window == null) {
31053             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
31054             return;
31055         }
31056 
31057         Rect visibleBounds = new Rect();
31058         getGlobalVisibleRect(visibleBounds);
31059 
31060         if (bounds != null && bounds.isEmpty()) {
31061             callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
31062             return;
31063         }
31064 
31065         if (bounds != null) {
31066             bounds.offset(visibleBounds.left, visibleBounds.top);
31067             visibleBounds.intersectUnchecked(bounds);
31068         }
31069 
31070         if (visibleBounds.isEmpty()) {
31071             callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
31072             return;
31073         }
31074 
31075         RemoteCallback remoteCallback = new RemoteCallback(result ->
31076                 executor.execute(() -> {
31077                     DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH);
31078                     int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
31079                             DISPLAY_HASH_ERROR_UNKNOWN);
31080                     if (displayHash != null) {
31081                         callback.onDisplayHashResult(displayHash);
31082                     } else {
31083                         callback.onDisplayHashError(errorCode);
31084                     }
31085                 }));
31086 
31087         try {
31088             session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
31089         } catch (RemoteException e) {
31090             Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
31091             callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
31092         }
31093     }
31094 
31095     /**
31096      * The AttachedSurfaceControl itself is not a View, it is just the interface to the
31097      * windowing-system object that contains the entire view hierarchy.
31098      * For the root View of a given hierarchy see {@link #getRootView}.
31099 
31100      * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
31101      * This will only return a non-null value when called between {@link #onAttachedToWindow}
31102      * and {@link #onDetachedFromWindow}.
31103      */
getRootSurfaceControl()31104     public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
31105         if (mAttachInfo != null) {
31106           return mAttachInfo.getRootSurfaceControl();
31107         }
31108         return null;
31109     }
31110 }
31111