• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static android.content.res.Resources.ID_NULL;
20 import static android.os.Trace.TRACE_TAG_APP;
21 import static android.os.Trace.TRACE_TAG_VIEW;
22 import static android.service.autofill.Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION;
23 import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
24 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
25 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
26 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
27 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
28 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
29 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
30 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
31 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
32 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
33 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
34 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
35 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
36 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH;
37 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
38 import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API;
39 import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
40 import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
41 import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout;
42 import static android.view.flags.Flags.sensitiveContentAppProtection;
43 import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
44 import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
45 import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
46 import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
47 import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
48 import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
49 import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
50 import static android.view.flags.Flags.viewVelocityApi;
51 import static android.view.inputmethod.Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR;
52 import static android.view.inputmethod.Flags.initiationWithoutInputConnection;
53 
54 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
55 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
56 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
57 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
58 import static com.android.window.flags.Flags.FLAG_DELEGATE_UNHANDLED_DRAGS;
59 
60 import static java.lang.Math.max;
61 
62 import android.animation.AnimatorInflater;
63 import android.animation.StateListAnimator;
64 import android.annotation.AttrRes;
65 import android.annotation.CallSuper;
66 import android.annotation.ColorInt;
67 import android.annotation.DrawableRes;
68 import android.annotation.FlaggedApi;
69 import android.annotation.FloatRange;
70 import android.annotation.IdRes;
71 import android.annotation.IntDef;
72 import android.annotation.IntRange;
73 import android.annotation.LayoutRes;
74 import android.annotation.NonNull;
75 import android.annotation.Nullable;
76 import android.annotation.RequiresPermission;
77 import android.annotation.Size;
78 import android.annotation.StyleRes;
79 import android.annotation.SuppressLint;
80 import android.annotation.SystemApi;
81 import android.annotation.TestApi;
82 import android.annotation.UiContext;
83 import android.annotation.UiThread;
84 import android.app.PendingIntent;
85 import android.compat.annotation.UnsupportedAppUsage;
86 import android.content.AutofillOptions;
87 import android.content.ClipData;
88 import android.content.ClipDescription;
89 import android.content.Context;
90 import android.content.ContextWrapper;
91 import android.content.Intent;
92 import android.content.IntentSender;
93 import android.content.res.ColorStateList;
94 import android.content.res.CompatibilityInfo;
95 import android.content.res.Configuration;
96 import android.content.res.Resources;
97 import android.content.res.TypedArray;
98 import android.credentials.CredentialManager;
99 import android.credentials.CredentialOption;
100 import android.credentials.GetCredentialException;
101 import android.credentials.GetCredentialRequest;
102 import android.credentials.GetCredentialResponse;
103 import android.graphics.Bitmap;
104 import android.graphics.BlendMode;
105 import android.graphics.Canvas;
106 import android.graphics.Color;
107 import android.graphics.Insets;
108 import android.graphics.Interpolator;
109 import android.graphics.LinearGradient;
110 import android.graphics.Matrix;
111 import android.graphics.Outline;
112 import android.graphics.Paint;
113 import android.graphics.PixelFormat;
114 import android.graphics.Point;
115 import android.graphics.PorterDuff;
116 import android.graphics.PorterDuffXfermode;
117 import android.graphics.RecordingCanvas;
118 import android.graphics.Rect;
119 import android.graphics.RectF;
120 import android.graphics.Region;
121 import android.graphics.RenderEffect;
122 import android.graphics.RenderNode;
123 import android.graphics.Shader;
124 import android.graphics.drawable.ColorDrawable;
125 import android.graphics.drawable.Drawable;
126 import android.graphics.drawable.GradientDrawable;
127 import android.hardware.display.DisplayManagerGlobal;
128 import android.hardware.input.InputManager;
129 import android.net.Uri;
130 import android.os.Build;
131 import android.os.Bundle;
132 import android.os.Handler;
133 import android.os.IBinder;
134 import android.os.Message;
135 import android.os.OutcomeReceiver;
136 import android.os.Parcel;
137 import android.os.Parcelable;
138 import android.os.RemoteCallback;
139 import android.os.RemoteException;
140 import android.os.SystemClock;
141 import android.os.Trace;
142 import android.os.Vibrator;
143 import android.os.vibrator.Flags;
144 import android.service.credentials.CredentialProviderService;
145 import android.sysprop.DisplayProperties;
146 import android.text.InputType;
147 import android.text.TextUtils;
148 import android.util.ArraySet;
149 import android.util.AttributeSet;
150 import android.util.DisplayMetrics;
151 import android.util.FloatProperty;
152 import android.util.LayoutDirection;
153 import android.util.Log;
154 import android.util.LongSparseArray;
155 import android.util.LongSparseLongArray;
156 import android.util.Pair;
157 import android.util.Pools.SynchronizedPool;
158 import android.util.Property;
159 import android.util.SparseArray;
160 import android.util.SparseIntArray;
161 import android.util.StateSet;
162 import android.util.SuperNotCalledException;
163 import android.util.TimeUtils;
164 import android.util.TypedValue;
165 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
166 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
167 import android.view.AccessibilityIterators.TextSegmentIterator;
168 import android.view.AccessibilityIterators.WordTextSegmentIterator;
169 import android.view.ContextMenu.ContextMenuInfo;
170 import android.view.InputDevice.InputSourceClass;
171 import android.view.Window.OnContentApplyWindowInsetsListener;
172 import android.view.WindowInsets.Type;
173 import android.view.WindowInsetsAnimation.Bounds;
174 import android.view.WindowManager.LayoutParams;
175 import android.view.accessibility.AccessibilityEvent;
176 import android.view.accessibility.AccessibilityEventSource;
177 import android.view.accessibility.AccessibilityManager;
178 import android.view.accessibility.AccessibilityNodeIdManager;
179 import android.view.accessibility.AccessibilityNodeInfo;
180 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
181 import android.view.accessibility.AccessibilityNodeProvider;
182 import android.view.accessibility.AccessibilityWindowInfo;
183 import android.view.animation.Animation;
184 import android.view.animation.AnimationUtils;
185 import android.view.animation.Transformation;
186 import android.view.autofill.AutofillId;
187 import android.view.autofill.AutofillManager;
188 import android.view.autofill.AutofillValue;
189 import android.view.contentcapture.ContentCaptureContext;
190 import android.view.contentcapture.ContentCaptureManager;
191 import android.view.contentcapture.ContentCaptureSession;
192 import android.view.displayhash.DisplayHash;
193 import android.view.displayhash.DisplayHashManager;
194 import android.view.displayhash.DisplayHashResultCallback;
195 import android.view.inputmethod.EditorInfo;
196 import android.view.inputmethod.InputConnection;
197 import android.view.inputmethod.InputMethodManager;
198 import android.view.inspector.InspectableProperty;
199 import android.view.inspector.InspectableProperty.EnumEntry;
200 import android.view.inspector.InspectableProperty.FlagEntry;
201 import android.view.translation.TranslationCapability;
202 import android.view.translation.TranslationSpec.DataFormat;
203 import android.view.translation.ViewTranslationCallback;
204 import android.view.translation.ViewTranslationRequest;
205 import android.view.translation.ViewTranslationResponse;
206 import android.widget.Checkable;
207 import android.widget.ScrollBarDrawable;
208 import android.window.OnBackInvokedDispatcher;
209 
210 import com.android.internal.R;
211 import com.android.internal.util.ArrayUtils;
212 import com.android.internal.util.FrameworkStatsLog;
213 import com.android.internal.util.Preconditions;
214 import com.android.internal.view.ScrollCaptureInternal;
215 import com.android.internal.view.TooltipPopup;
216 import com.android.internal.view.menu.MenuBuilder;
217 import com.android.internal.widget.ScrollBarUtils;
218 
219 import com.google.android.collect.Lists;
220 import com.google.android.collect.Maps;
221 
222 import java.io.PrintWriter;
223 import java.lang.annotation.Retention;
224 import java.lang.annotation.RetentionPolicy;
225 import java.lang.ref.WeakReference;
226 import java.lang.reflect.Field;
227 import java.lang.reflect.InvocationTargetException;
228 import java.lang.reflect.Method;
229 import java.lang.reflect.Modifier;
230 import java.time.Duration;
231 import java.util.ArrayList;
232 import java.util.Arrays;
233 import java.util.Calendar;
234 import java.util.Collection;
235 import java.util.Collections;
236 import java.util.HashMap;
237 import java.util.List;
238 import java.util.Locale;
239 import java.util.Map;
240 import java.util.concurrent.CopyOnWriteArrayList;
241 import java.util.concurrent.Executor;
242 import java.util.concurrent.atomic.AtomicInteger;
243 import java.util.function.Consumer;
244 import java.util.function.Predicate;
245 
246 /**
247  * <p>
248  * This class represents the basic building block for user interface components. A View
249  * occupies a rectangular area on the screen and is responsible for drawing and
250  * event handling. View is the base class for <em>widgets</em>, which are
251  * used to create interactive UI components (buttons, text fields, etc.). The
252  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
253  * are invisible containers that hold other Views (or other ViewGroups) and define
254  * their layout properties.
255  * </p>
256  *
257  * <div class="special reference">
258  * <h3>Developer Guides</h3>
259  * <p>For information about using this class to develop your application's user interface,
260  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
261  * </div>
262  *
263  * <a name="Using"></a>
264  * <h3>Using Views</h3>
265  * <p>
266  * All of the views in a window are arranged in a single tree. You can add views
267  * either from code or by specifying a tree of views in one or more XML layout
268  * files. There are many specialized subclasses of views that act as controls or
269  * are capable of displaying text, images, or other content.
270  * </p>
271  * <p>
272  * Once you have created a tree of views, there are typically a few types of
273  * common operations you may wish to perform:
274  * <ul>
275  * <li><strong>Set properties:</strong> for example setting the text of a
276  * {@link android.widget.TextView}. The available properties and the methods
277  * that set them will vary among the different subclasses of views. Note that
278  * properties that are known at build time can be set in the XML layout
279  * files.</li>
280  * <li><strong>Set focus:</strong> The framework will handle moving focus in
281  * response to user input. To force focus to a specific view, call
282  * {@link #requestFocus}.</li>
283  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
284  * that will be notified when something interesting happens to the view. For
285  * example, all views will let you set a listener to be notified when the view
286  * gains or loses focus. You can register such a listener using
287  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
288  * Other view subclasses offer more specialized listeners. For example, a Button
289  * exposes a listener to notify clients when the button is clicked.</li>
290  * <li><strong>Set visibility:</strong> You can hide or show views using
291  * {@link #setVisibility(int)}.</li>
292  * </ul>
293  * </p>
294  * <p><em>
295  * Note: The Android framework is responsible for measuring, laying out and
296  * drawing views. You should not call methods that perform these actions on
297  * views yourself unless you are actually implementing a
298  * {@link android.view.ViewGroup}.
299  * </em></p>
300  *
301  * <a name="Lifecycle"></a>
302  * <h3>Implementing a Custom View</h3>
303  *
304  * <p>
305  * To implement a custom view, you will usually begin by providing overrides for
306  * some of the standard methods that the framework calls on all views. You do
307  * not need to override all of these methods. In fact, you can start by just
308  * overriding {@link #onDraw(android.graphics.Canvas)}.
309  * <table border="2" width="85%" align="center" cellpadding="5">
310  *     <thead>
311  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
312  *     </thead>
313  *
314  *     <tbody>
315  *     <tr>
316  *         <td rowspan="2">Creation</td>
317  *         <td>Constructors</td>
318  *         <td>There is a form of the constructor that are called when the view
319  *         is created from code and a form that is called when the view is
320  *         inflated from a layout file. The second form should parse and apply
321  *         any attributes defined in the layout file.
322  *         </td>
323  *     </tr>
324  *     <tr>
325  *         <td><code>{@link #onFinishInflate()}</code></td>
326  *         <td>Called after a view and all of its children has been inflated
327  *         from XML.</td>
328  *     </tr>
329  *
330  *     <tr>
331  *         <td rowspan="3">Layout</td>
332  *         <td><code>{@link #onMeasure(int, int)}</code></td>
333  *         <td>Called to determine the size requirements for this view and all
334  *         of its children.
335  *         </td>
336  *     </tr>
337  *     <tr>
338  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
339  *         <td>Called when this view should assign a size and position to all
340  *         of its children.
341  *         </td>
342  *     </tr>
343  *     <tr>
344  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
345  *         <td>Called when the size of this view has changed.
346  *         </td>
347  *     </tr>
348  *
349  *     <tr>
350  *         <td>Drawing</td>
351  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
352  *         <td>Called when the view should render its content.
353  *         </td>
354  *     </tr>
355  *
356  *     <tr>
357  *         <td rowspan="6">Event processing</td>
358  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
359  *         <td>Called when a new hardware key event occurs.
360  *         </td>
361  *     </tr>
362  *     <tr>
363  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
364  *         <td>Called when a hardware key up event occurs.
365  *         </td>
366  *     </tr>
367  *     <tr>
368  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
369  *         <td>Called when a trackball motion event occurs.
370  *         </td>
371  *     </tr>
372  *     <tr>
373  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
374  *         <td>Called when a touch screen motion event occurs.
375  *         </td>
376  *     </tr>
377  *     <tr>
378  *         <td><code>{@link #onGenericMotionEvent(MotionEvent)}</code></td>
379  *         <td>Called when a generic motion event occurs.
380  *         </td>
381  *     </tr>
382  *     <tr>
383  *         <td><code>{@link #onHoverEvent(MotionEvent)}</code></td>
384  *         <td>Called when a hover motion event occurs.
385  *         </td>
386  *     </tr>
387  *
388  *     <tr>
389  *         <td rowspan="2">Focus</td>
390  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
391  *         <td>Called when the view gains or loses focus.
392  *         </td>
393  *     </tr>
394  *
395  *     <tr>
396  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
397  *         <td>Called when the window containing the view gains or loses focus.
398  *         </td>
399  *     </tr>
400  *
401  *     <tr>
402  *         <td rowspan="3">Attaching</td>
403  *         <td><code>{@link #onAttachedToWindow()}</code></td>
404  *         <td>Called when the view is attached to a window.
405  *         </td>
406  *     </tr>
407  *
408  *     <tr>
409  *         <td><code>{@link #onDetachedFromWindow}</code></td>
410  *         <td>Called when the view is detached from its window.
411  *         </td>
412  *     </tr>
413  *
414  *     <tr>
415  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
416  *         <td>Called when the visibility of the window containing the view
417  *         has changed.
418  *         </td>
419  *     </tr>
420  *     </tbody>
421  *
422  * </table>
423  * </p>
424  *
425  * <a name="IDs"></a>
426  * <h3>IDs</h3>
427  * Views may have an integer id associated with them. These ids are typically
428  * assigned in the layout XML files, and are used to find specific views within
429  * the view tree. A common pattern is to:
430  * <ul>
431  * <li>Define a Button in the layout file and assign it a unique ID.
432  * <pre>
433  * &lt;Button
434  *     android:id="@+id/my_button"
435  *     android:layout_width="wrap_content"
436  *     android:layout_height="wrap_content"
437  *     android:text="@string/my_button_text"/&gt;
438  * </pre></li>
439  * <li>From the onCreate method of an Activity, find the Button
440  * <pre class="prettyprint">
441  *      Button myButton = findViewById(R.id.my_button);
442  * </pre></li>
443  * </ul>
444  * <p>
445  * View IDs need not be unique throughout the tree, but it is good practice to
446  * ensure that they are at least unique within the part of the tree you are
447  * searching.
448  * </p>
449  *
450  * <a name="Position"></a>
451  * <h3>Position</h3>
452  * <p>
453  * The geometry of a view is that of a rectangle. A view has a location,
454  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
455  * two dimensions, expressed as a width and a height. The unit for location
456  * and dimensions is the pixel.
457  * </p>
458  *
459  * <p>
460  * It is possible to retrieve the location of a view by invoking the methods
461  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
462  * coordinate of the rectangle representing the view. The latter returns the
463  * top, or Y, coordinate of the rectangle representing the view. These methods
464  * both return the location of the view relative to its parent. For instance,
465  * when getLeft() returns 20, that means the view is located 20 pixels to the
466  * right of the left edge of its direct parent.
467  * </p>
468  *
469  * <p>
470  * In addition, several convenience methods are offered to avoid unnecessary
471  * computations, namely {@link #getRight()} and {@link #getBottom()}.
472  * These methods return the coordinates of the right and bottom edges of the
473  * rectangle representing the view. For instance, calling {@link #getRight()}
474  * is similar to the following computation: <code>getLeft() + getWidth()</code>
475  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
476  * </p>
477  *
478  * <a name="SizePaddingMargins"></a>
479  * <h3>Size, padding and margins</h3>
480  * <p>
481  * The size of a view is expressed with a width and a height. A view actually
482  * possess two pairs of width and height values.
483  * </p>
484  *
485  * <p>
486  * The first pair is known as <em>measured width</em> and
487  * <em>measured height</em>. These dimensions define how big a view wants to be
488  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
489  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
490  * and {@link #getMeasuredHeight()}.
491  * </p>
492  *
493  * <p>
494  * The second pair is simply known as <em>width</em> and <em>height</em>, or
495  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
496  * dimensions define the actual size of the view on screen, at drawing time and
497  * after layout. These values may, but do not have to, be different from the
498  * measured width and height. The width and height can be obtained by calling
499  * {@link #getWidth()} and {@link #getHeight()}.
500  * </p>
501  *
502  * <p>
503  * To measure its dimensions, a view takes into account its padding. The padding
504  * is expressed in pixels for the left, top, right and bottom parts of the view.
505  * Padding can be used to offset the content of the view by a specific amount of
506  * pixels. For instance, a left padding of 2 will push the view's content by
507  * 2 pixels to the right of the left edge. Padding can be set using the
508  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
509  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
510  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
511  * {@link #getPaddingEnd()}.
512  * </p>
513  *
514  * <p>
515  * Even though a view can define a padding, it does not provide any support for
516  * margins. However, view groups provide such a support. Refer to
517  * {@link android.view.ViewGroup} and
518  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
519  * </p>
520  *
521  * <a name="Layout"></a>
522  * <h3>Layout</h3>
523  * <p>
524  * Layout is a two pass process: a measure pass and a layout pass. The measuring
525  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
526  * of the view tree. Each view pushes dimension specifications down the tree
527  * during the recursion. At the end of the measure pass, every view has stored
528  * its measurements. The second pass happens in
529  * {@link #layout(int,int,int,int)} and is also top-down. During
530  * this pass each parent is responsible for positioning all of its children
531  * using the sizes computed in the measure pass.
532  * </p>
533  *
534  * <p>
535  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
536  * {@link #getMeasuredHeight()} values must be set, along with those for all of
537  * that view's descendants. A view's measured width and measured height values
538  * must respect the constraints imposed by the view's parents. This guarantees
539  * that at the end of the measure pass, all parents accept all of their
540  * children's measurements. A parent view may call measure() more than once on
541  * its children. For example, the parent may measure each child once with
542  * unspecified dimensions to find out how big they want to be, then call
543  * measure() on them again with actual numbers if the sum of all the children's
544  * unconstrained sizes is too big or too small.
545  * </p>
546  *
547  * <p>
548  * The measure pass uses two classes to communicate dimensions. The
549  * {@link MeasureSpec} class is used by views to tell their parents how they
550  * want to be measured and positioned. The base LayoutParams class just
551  * describes how big the view wants to be for both width and height. For each
552  * dimension, it can specify one of:
553  * <ul>
554  * <li> an exact number
555  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
556  * (minus padding)
557  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
558  * enclose its content (plus padding).
559  * </ul>
560  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
561  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
562  * an X and Y value.
563  * </p>
564  *
565  * <p>
566  * MeasureSpecs are used to push requirements down the tree from parent to
567  * child. A MeasureSpec can be in one of three modes:
568  * <ul>
569  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
570  * of a child view. For example, a LinearLayout may call measure() on its child
571  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
572  * tall the child view wants to be given a width of 240 pixels.
573  * <li>EXACTLY: This is used by the parent to impose an exact size on the
574  * child. The child must use this size, and guarantee that all of its
575  * descendants will fit within this size.
576  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
577  * child. The child must guarantee that it and all of its descendants will fit
578  * within this size.
579  * </ul>
580  * </p>
581  *
582  * <p>
583  * To initiate a layout, call {@link #requestLayout}. This method is typically
584  * called by a view on itself when it believes that it can no longer fit within
585  * its current bounds.
586  * </p>
587  *
588  * <a name="Drawing"></a>
589  * <h3>Drawing</h3>
590  * <p>
591  * Drawing is handled by walking the tree and recording the drawing commands of
592  * any View that needs to update. After this, the drawing commands of the
593  * entire tree are issued to screen, clipped to the newly damaged area.
594  * </p>
595  *
596  * <p>
597  * The tree is largely recorded and drawn in order, with parents drawn before
598  * (i.e., behind) their children, with siblings drawn in the order they appear
599  * in the tree. If you set a background drawable for a View, then the View will
600  * draw it before calling back to its <code>onDraw()</code> method. The child
601  * drawing order can be overridden with
602  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
603  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
604  * </p>
605  *
606  * <p>
607  * To force a view to draw, call {@link #invalidate()}.
608  * </p>
609  *
610  * <a name="EventHandlingThreading"></a>
611  * <h3>Event Handling and Threading</h3>
612  * <p>
613  * The basic cycle of a view is as follows:
614  * <ol>
615  * <li>An event comes in and is dispatched to the appropriate view. The view
616  * handles the event and notifies any listeners.</li>
617  * <li>If in the course of processing the event, the view's bounds may need
618  * to be changed, the view will call {@link #requestLayout()}.</li>
619  * <li>Similarly, if in the course of processing the event the view's appearance
620  * may need to be changed, the view will call {@link #invalidate()}.</li>
621  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
622  * the framework will take care of measuring, laying out, and drawing the tree
623  * as appropriate.</li>
624  * </ol>
625  * </p>
626  *
627  * <p><em>Note: The entire view tree is single threaded. You must always be on
628  * the UI thread when calling any method on any view.</em>
629  * If you are doing work on other threads and want to update the state of a view
630  * from that thread, you should use a {@link Handler}.
631  * </p>
632  *
633  * <a name="FocusHandling"></a>
634  * <h3>Focus Handling</h3>
635  * <p>
636  * The framework will handle routine focus movement in response to user input.
637  * This includes changing the focus as views are removed or hidden, or as new
638  * views become available. Views indicate their willingness to take focus
639  * through the {@link #isFocusable} method. To change whether a view can take
640  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
641  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
642  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
643  * </p>
644  * <p>
645  * Focus movement is based on an algorithm which finds the nearest neighbor in a
646  * given direction. In rare cases, the default algorithm may not match the
647  * intended behavior of the developer. In these situations, you can provide
648  * explicit overrides by using these XML attributes in the layout file:
649  * <pre>
650  * nextFocusDown
651  * nextFocusLeft
652  * nextFocusRight
653  * nextFocusUp
654  * </pre>
655  * </p>
656  *
657  *
658  * <p>
659  * To get a particular view to take focus, call {@link #requestFocus()}.
660  * </p>
661  *
662  * <a name="TouchMode"></a>
663  * <h3>Touch Mode</h3>
664  * <p>
665  * When a user is navigating a user interface via directional keys such as a D-pad, it is
666  * necessary to give focus to actionable items such as buttons so the user can see
667  * what will take input.  If the device has touch capabilities, however, and the user
668  * begins interacting with the interface by touching it, it is no longer necessary to
669  * always highlight, or give focus to, a particular view.  This motivates a mode
670  * for interaction named 'touch mode'.
671  * </p>
672  * <p>
673  * For a touch capable device, once the user touches the screen, the device
674  * will enter touch mode.  From this point onward, only views for which
675  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
676  * Other views that are touchable, like buttons, will not take focus when touched; they will
677  * only fire the on click listeners.
678  * </p>
679  * <p>
680  * Any time a user hits a directional key, such as a D-pad direction, the view device will
681  * exit touch mode, and find a view to take focus, so that the user may resume interacting
682  * with the user interface without touching the screen again.
683  * </p>
684  * <p>
685  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
686  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
687  * </p>
688  *
689  * <a name="Scrolling"></a>
690  * <h3>Scrolling</h3>
691  * <p>
692  * The framework provides basic support for views that wish to internally
693  * scroll their content. This includes keeping track of the X and Y scroll
694  * offset as well as mechanisms for drawing scrollbars. See
695  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
696  * {@link #awakenScrollBars()} for more details.
697  * </p>
698  *
699  * <a name="Tags"></a>
700  * <h3>Tags</h3>
701  * <p>
702  * Unlike IDs, tags are not used to identify views. Tags are essentially an
703  * extra piece of information that can be associated with a view. They are most
704  * often used as a convenience to store data related to views in the views
705  * themselves rather than by putting them in a separate structure.
706  * </p>
707  * <p>
708  * Tags may be specified with character sequence values in layout XML as either
709  * a single tag using the {@link android.R.styleable#View_tag android:tag}
710  * attribute or multiple tags using the {@code <tag>} child element:
711  * <pre>
712  *     &lt;View ...
713  *           android:tag="@string/mytag_value" /&gt;
714  *     &lt;View ...&gt;
715  *         &lt;tag android:id="@+id/mytag"
716  *              android:value="@string/mytag_value" /&gt;
717  *     &lt;/View>
718  * </pre>
719  * </p>
720  * <p>
721  * Tags may also be specified with arbitrary objects from code using
722  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
723  * </p>
724  *
725  * <a name="Themes"></a>
726  * <h3>Themes</h3>
727  * <p>
728  * By default, Views are created using the theme of the Context object supplied
729  * to their constructor; however, a different theme may be specified by using
730  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
731  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
732  * code.
733  * </p>
734  * <p>
735  * When the {@link android.R.styleable#View_theme android:theme} attribute is
736  * used in XML, the specified theme is applied on top of the inflation
737  * context's theme (see {@link LayoutInflater}) and used for the view itself as
738  * well as any child elements.
739  * </p>
740  * <p>
741  * In the following example, both views will be created using the Material dark
742  * color scheme; however, because an overlay theme is used which only defines a
743  * subset of attributes, the value of
744  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
745  * the inflation context's theme (e.g. the Activity theme) will be preserved.
746  * <pre>
747  *     &lt;LinearLayout
748  *             ...
749  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
750  *         &lt;View ...&gt;
751  *     &lt;/LinearLayout&gt;
752  * </pre>
753  * </p>
754  *
755  * <a name="Properties"></a>
756  * <h3>Properties</h3>
757  * <p>
758  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
759  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
760  * available both in the {@link Property} form as well as in similarly-named setter/getter
761  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
762  * be used to set persistent state associated with these rendering-related properties on the view.
763  * The properties and methods can also be used in conjunction with
764  * {@link android.animation.Animator Animator}-based animations, described more in the
765  * <a href="#Animation">Animation</a> section.
766  * </p>
767  *
768  * <a name="Animation"></a>
769  * <h3>Animation</h3>
770  * <p>
771  * Starting with Android 3.0, the preferred way of animating views is to use the
772  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
773  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
774  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
775  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
776  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
777  * makes animating these View properties particularly easy and efficient.
778  * </p>
779  * <p>
780  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
781  * You can attach an {@link Animation} object to a view using
782  * {@link #setAnimation(Animation)} or
783  * {@link #startAnimation(Animation)}. The animation can alter the scale,
784  * rotation, translation and alpha of a view over time. If the animation is
785  * attached to a view that has children, the animation will affect the entire
786  * subtree rooted by that node. When an animation is started, the framework will
787  * take care of redrawing the appropriate views until the animation completes.
788  * </p>
789  *
790  * <a name="Security"></a>
791  * <h3>Security</h3>
792  * <p>
793  * Sometimes it is essential that an application be able to verify that an action
794  * is being performed with the full knowledge and consent of the user, such as
795  * granting a permission request, making a purchase or clicking on an advertisement.
796  * Unfortunately, a malicious application could try to spoof the user into
797  * performing these actions, unaware, by concealing the intended purpose of the view.
798  * As a remedy, the framework offers a touch filtering mechanism that can be used to
799  * improve the security of views that provide access to sensitive functionality.
800  * </p><p>
801  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
802  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
803  * will discard touches that are received whenever the view's window is obscured by
804  * another visible window at the touched location.  As a result, the view will not receive touches
805  * whenever the touch passed through a toast, dialog or other window that appears above the view's
806  * window.
807  * </p><p>
808  * For more fine-grained control over security, consider overriding the
809  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
810  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
811  * </p>
812  *
813  * @attr ref android.R.styleable#View_accessibilityHeading
814  * @attr ref android.R.styleable#View_allowClickWhenDisabled
815  * @attr ref android.R.styleable#View_alpha
816  * @attr ref android.R.styleable#View_background
817  * @attr ref android.R.styleable#View_clickable
818  * @attr ref android.R.styleable#View_clipToOutline
819  * @attr ref android.R.styleable#View_contentDescription
820  * @attr ref android.R.styleable#View_drawingCacheQuality
821  * @attr ref android.R.styleable#View_duplicateParentState
822  * @attr ref android.R.styleable#View_id
823  * @attr ref android.R.styleable#View_requiresFadingEdge
824  * @attr ref android.R.styleable#View_fadeScrollbars
825  * @attr ref android.R.styleable#View_fadingEdgeLength
826  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
827  * @attr ref android.R.styleable#View_fitsSystemWindows
828  * @attr ref android.R.styleable#View_isScrollContainer
829  * @attr ref android.R.styleable#View_focusable
830  * @attr ref android.R.styleable#View_focusableInTouchMode
831  * @attr ref android.R.styleable#View_focusedByDefault
832  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
833  * @attr ref android.R.styleable#View_keepScreenOn
834  * @attr ref android.R.styleable#View_keyboardNavigationCluster
835  * @attr ref android.R.styleable#View_layerType
836  * @attr ref android.R.styleable#View_layoutDirection
837  * @attr ref android.R.styleable#View_longClickable
838  * @attr ref android.R.styleable#View_minHeight
839  * @attr ref android.R.styleable#View_minWidth
840  * @attr ref android.R.styleable#View_nextClusterForward
841  * @attr ref android.R.styleable#View_nextFocusDown
842  * @attr ref android.R.styleable#View_nextFocusLeft
843  * @attr ref android.R.styleable#View_nextFocusRight
844  * @attr ref android.R.styleable#View_nextFocusUp
845  * @attr ref android.R.styleable#View_onClick
846  * @attr ref android.R.styleable#View_outlineSpotShadowColor
847  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
848  * @attr ref android.R.styleable#View_padding
849  * @attr ref android.R.styleable#View_paddingHorizontal
850  * @attr ref android.R.styleable#View_paddingVertical
851  * @attr ref android.R.styleable#View_paddingBottom
852  * @attr ref android.R.styleable#View_paddingLeft
853  * @attr ref android.R.styleable#View_paddingRight
854  * @attr ref android.R.styleable#View_paddingTop
855  * @attr ref android.R.styleable#View_paddingStart
856  * @attr ref android.R.styleable#View_paddingEnd
857  * @attr ref android.R.styleable#View_saveEnabled
858  * @attr ref android.R.styleable#View_rotation
859  * @attr ref android.R.styleable#View_rotationX
860  * @attr ref android.R.styleable#View_rotationY
861  * @attr ref android.R.styleable#View_scaleX
862  * @attr ref android.R.styleable#View_scaleY
863  * @attr ref android.R.styleable#View_scrollX
864  * @attr ref android.R.styleable#View_scrollY
865  * @attr ref android.R.styleable#View_scrollbarSize
866  * @attr ref android.R.styleable#View_scrollbarStyle
867  * @attr ref android.R.styleable#View_scrollbars
868  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
869  * @attr ref android.R.styleable#View_scrollbarFadeDuration
870  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
871  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
872  * @attr ref android.R.styleable#View_scrollbarThumbVertical
873  * @attr ref android.R.styleable#View_scrollbarTrackVertical
874  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
875  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
876  * @attr ref android.R.styleable#View_stateListAnimator
877  * @attr ref android.R.styleable#View_transitionName
878  * @attr ref android.R.styleable#View_soundEffectsEnabled
879  * @attr ref android.R.styleable#View_tag
880  * @attr ref android.R.styleable#View_textAlignment
881  * @attr ref android.R.styleable#View_textDirection
882  * @attr ref android.R.styleable#View_transformPivotX
883  * @attr ref android.R.styleable#View_transformPivotY
884  * @attr ref android.R.styleable#View_translationX
885  * @attr ref android.R.styleable#View_translationY
886  * @attr ref android.R.styleable#View_translationZ
887  * @attr ref android.R.styleable#View_visibility
888  * @attr ref android.R.styleable#View_theme
889  *
890  * @see android.view.ViewGroup
891  */
892 @UiThread
893 public class View implements Drawable.Callback, KeyEvent.Callback,
894         AccessibilityEventSource {
895     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
896     private static final boolean DBG = false;
897 
898     /** @hide */
899     public static boolean DEBUG_DRAW = false;
900 
901     /**
902      * The logging tag used by this class with android.util.Log.
903      */
904     protected static final String VIEW_LOG_TAG = "View";
905 
906     /**
907      * The logging tag used by this class when logging verbose, autofill-related messages.
908      */
909     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
910     // set if a session is not started.
911     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
912 
913     /**
914      * The logging tag used by this class when logging content capture-related messages.
915      */
916     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
917 
918     private static final boolean DEBUG_CONTENT_CAPTURE = false;
919 
920     /**
921      * When set to true, this view will save its attribute data.
922      *
923      * @hide
924      */
925     public static boolean sDebugViewAttributes = false;
926 
927     /**
928      * When set to this application package view will save its attribute data.
929      *
930      * @hide
931      */
932     public static String sDebugViewAttributesApplicationPackage;
933 
934     /**
935      * Used to mark a View that has no ID.
936      */
937     public static final int NO_ID = -1;
938 
939     /**
940      * Last ID that is given to Views that are no part of activities.
941      *
942      * {@hide}
943      */
944     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
945 
946     /**
947      * Attribute to find the autofilled highlight
948      *
949      * @see #getAutofilledDrawable()
950      */
951     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
952             new int[]{android.R.attr.autofilledHighlight};
953 
954     /**
955      * Signals that compatibility booleans have been initialized according to
956      * target SDK versions.
957      */
958     private static boolean sCompatibilityDone = false;
959 
960     /** @hide */
961     public HapticScrollFeedbackProvider mScrollFeedbackProvider = null;
962 
963     /**
964      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
965      */
966     private static boolean sAlwaysRemeasureExactly = false;
967 
968     /**
969      * When true makes it possible to use onMeasure caches also when the force layout flag is
970      * enabled. This helps avoiding multiple measures in the same frame with the same dimensions.
971      */
972     private static boolean sUseMeasureCacheDuringForceLayoutFlagValue;
973 
974     /**
975      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
976      * without throwing
977      */
978     static boolean sTextureViewIgnoresDrawableSetters = false;
979 
980     /**
981      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
982      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
983      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
984      * check is implemented for backwards compatibility.
985      *
986      * {@hide}
987      */
988     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
989 
990     /**
991      * Prior to N, when drag enters into child of a view that has already received an
992      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
993      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
994      * false from its event handler for these events.
995      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
996      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
997      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
998      */
999     static boolean sCascadedDragDrop;
1000 
1001     /**
1002      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
1003      * to determine things like whether or not to permit item click events. We can't break
1004      * apps that do this just because more things (clickable things) are now auto-focusable
1005      * and they would get different results, so give old behavior to old apps.
1006      */
1007     static boolean sHasFocusableExcludeAutoFocusable;
1008 
1009     /**
1010      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
1011      * made focusable by default. As a result, apps could (incorrectly) change the clickable
1012      * setting of views off the UI thread. Now that clickable can effect the focusable state,
1013      * changing the clickable attribute off the UI thread will cause an exception (since changing
1014      * the focusable state checks). In order to prevent apps from crashing, we will handle this
1015      * specific case and just not notify parents on new focusables resulting from marking views
1016      * clickable from outside the UI thread.
1017      */
1018     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
1019 
1020     /**
1021      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
1022      * Float.NaN. If the app is targetting P or later then passing these values will result in an
1023      * exception being thrown. If the app is targetting an earlier SDK version, then we will
1024      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
1025      * these bogus values.
1026      */
1027     private static boolean sThrowOnInvalidFloatProperties;
1028 
1029     /**
1030      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
1031      * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead.
1032      */
1033     private static boolean sAcceptZeroSizeDragShadow;
1034 
1035     /**
1036      * When true, measure and layout passes of all the newly attached views will be logged with
1037      * {@link Trace}, so we can better debug jank due to complex view hierarchies.
1038      */
1039     private static boolean sTraceLayoutSteps;
1040 
1041     /**
1042      * When not null, emits a {@link Trace} instant event and the stacktrace every time a relayout
1043      * of a class having this name happens.
1044      */
1045     private static String sTraceRequestLayoutClass;
1046 
1047     @Nullable
1048     private ViewCredentialHandler mViewCredentialHandler;
1049 
1050     /** Used to avoid computing the full strings each time when layout tracing is enabled. */
1051     @Nullable
1052     private ViewTraversalTracingStrings mTracingStrings;
1053 
1054     /**
1055      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
1056      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
1057      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
1058      * further down the hierarchy. This violates the basic concepts of the view hierarchy, and
1059      * thus, the hierarchical dispatching mechanism was hard to use for apps.
1060      * <p>
1061      * In order to make window inset dispatching work properly, we dispatch window insets
1062      * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}.
1063      */
1064     static boolean sBrokenInsetsDispatch;
1065 
1066     /**
1067      * Prior to Q, calling
1068      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
1069      * did not call update the window format so the opacity of the background was not correctly
1070      * applied to the window. Some applications rely on this misbehavior to work properly.
1071      * <p>
1072      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
1073      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
1074      * which updates the window format.
1075      * @hide
1076      */
1077     protected static boolean sBrokenWindowBackground;
1078 
1079     /**
1080      * Prior to R, we were always forcing a layout of the entire hierarchy when insets changed from
1081      * the server. This is inefficient and not all apps use it. Instead, we want to rely on apps
1082      * calling {@link #requestLayout} when they need to relayout based on an insets change.
1083      */
1084     static boolean sForceLayoutWhenInsetsChanged;
1085 
1086     /** @hide */
1087     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
1088     @Retention(RetentionPolicy.SOURCE)
1089     public @interface Focusable {}
1090 
1091     /**
1092      * This view does not want keystrokes.
1093      * <p>
1094      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1095      * android:focusable}.
1096      */
1097     public static final int NOT_FOCUSABLE = 0x00000000;
1098 
1099     /**
1100      * This view wants keystrokes.
1101      * <p>
1102      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1103      * android:focusable}.
1104      */
1105     public static final int FOCUSABLE = 0x00000001;
1106 
1107     /**
1108      * This view determines focusability automatically. This is the default.
1109      * <p>
1110      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1111      * android:focusable}.
1112      */
1113     public static final int FOCUSABLE_AUTO = 0x00000010;
1114 
1115     /**
1116      * Mask for use with setFlags indicating bits used for focus.
1117      */
1118     private static final int FOCUSABLE_MASK = 0x00000011;
1119 
1120     /**
1121      * This view will adjust its padding to fit system windows (e.g. status bar)
1122      */
1123     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1124 
1125     /** @hide */
1126     @IntDef({VISIBLE, INVISIBLE, GONE})
1127     @Retention(RetentionPolicy.SOURCE)
1128     public @interface Visibility {}
1129 
1130     /**
1131      * This view is visible.
1132      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1133      * android:visibility}.
1134      */
1135     public static final int VISIBLE = 0x00000000;
1136 
1137     /**
1138      * This view is invisible, but it still takes up space for layout purposes.
1139      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1140      * android:visibility}.
1141      */
1142     public static final int INVISIBLE = 0x00000004;
1143 
1144     /**
1145      * This view is invisible, and it doesn't take any space for layout
1146      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1147      * android:visibility}.
1148      */
1149     public static final int GONE = 0x00000008;
1150 
1151     /**
1152      * Mask for use with setFlags indicating bits used for visibility.
1153      * {@hide}
1154      */
1155     static final int VISIBILITY_MASK = 0x0000000C;
1156 
1157     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1158 
1159     /**
1160      * Hint indicating that this view can be autofilled with an email address.
1161      *
1162      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1163      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1164      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1165      *
1166      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1167      */
1168     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1169 
1170     /**
1171      * Hint indicating that this view can be autofilled with a user's real name.
1172      *
1173      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1174      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1175      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1176      *
1177      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1178      */
1179     public static final String AUTOFILL_HINT_NAME = "name";
1180 
1181     /**
1182      * Hint indicating that this view can be autofilled with a username.
1183      *
1184      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1185      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1186      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1187      *
1188      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1189      */
1190     public static final String AUTOFILL_HINT_USERNAME = "username";
1191 
1192     /**
1193      * Hint indicating that this view can be autofilled with a password.
1194      *
1195      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1196      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1197      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1198      *
1199      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1200      */
1201     public static final String AUTOFILL_HINT_PASSWORD = "password";
1202 
1203     /**
1204      * Hint indicating that this view can be autofilled with a phone number.
1205      *
1206      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1207      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1208      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1209      *
1210      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1211      */
1212     public static final String AUTOFILL_HINT_PHONE = "phone";
1213 
1214     /**
1215      * Hint indicating that this view can be autofilled with a postal address.
1216      *
1217      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1218      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1219      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1220      *
1221      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1222      */
1223     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1224 
1225     /**
1226      * Hint indicating that this view can be autofilled with a postal code.
1227      *
1228      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1229      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1230      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1231      *
1232      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1233      */
1234     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1235 
1236     /**
1237      * Hint indicating that this view can be autofilled with a credit card number.
1238      *
1239      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1240      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1241      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1242      *
1243      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1244      */
1245     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1246 
1247     /**
1248      * Hint indicating that this view can be autofilled with a credit card security code.
1249      *
1250      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1251      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1252      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1253      *
1254      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1255      */
1256     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1257 
1258     /**
1259      * Hint indicating that this view can be autofilled with a credit card expiration date.
1260      *
1261      * <p>It should be used when the credit card expiration date is represented by just one view;
1262      * if it is represented by more than one (for example, one view for the month and another view
1263      * for the year), then each of these views should use the hint specific for the unit
1264      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1265      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1266      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1267      *
1268      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1269      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1270      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1271      *
1272      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1273      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1274      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1275      * the following options:
1276      *
1277      * <ul>
1278      *   <li>{@code "04/2020"}
1279      *   <li>{@code "4/2020"}
1280      *   <li>{@code "2020/04"}
1281      *   <li>{@code "2020/4"}
1282      *   <li>{@code "April/2020"}
1283      *   <li>{@code "Apr/2020"}
1284      * </ul>
1285      *
1286      * <p>You define a date autofill value for the view by overriding the following methods:
1287      *
1288      * <ol>
1289      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1290      *   <li>{@link #getAutofillValue()} to return a
1291      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1292      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1293      * </ol>
1294      *
1295      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1296      */
1297     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1298             "creditCardExpirationDate";
1299 
1300     /**
1301      * Hint indicating that this view can be autofilled with a credit card expiration month.
1302      *
1303      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1304      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1305      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1306      *
1307      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1308      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1309      * ambiguity when the autofill service provides a value for it. To understand why a
1310      * value can be ambiguous, consider "January", which could be represented as either of
1311      *
1312      * <ul>
1313      *   <li>{@code "1"}: recommended way.
1314      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1315      *   <li>{@code "January"}: full name, in English.
1316      *   <li>{@code "jan"}: abbreviated name, in English.
1317      *   <li>{@code "Janeiro"}: full name, in another language.
1318      * </ul>
1319      *
1320      * <p>Another recommended approach is to use a date autofill value - see
1321      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1322      *
1323      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1324      */
1325     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1326             "creditCardExpirationMonth";
1327 
1328     /**
1329      * Hint indicating that this view can be autofilled with a credit card expiration year.
1330      *
1331      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1332      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1333      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1334      *
1335      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1336      */
1337     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1338             "creditCardExpirationYear";
1339 
1340     /**
1341      * Hint indicating that this view can be autofilled with a credit card expiration day.
1342      *
1343      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1344      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1345      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1346      *
1347      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1348      */
1349     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1350 
1351     /**
1352      * A hint indicating that this view can be autofilled with a password.
1353      *
1354      * This is a heuristic-based hint that is meant to be used by UI Toolkit developers when a
1355      * view is a password field but doesn't specify a
1356      * <code>{@value View#AUTOFILL_HINT_PASSWORD}</code>.
1357      * @hide
1358      */
1359     // TODO(229765029): unhide this for UI toolkit
1360     public static final String AUTOFILL_HINT_PASSWORD_AUTO = "passwordAuto";
1361 
1362     /**
1363      * Hint indicating that the developer intends to fill this view with output from
1364      * CredentialManager.
1365      *
1366      * @hide
1367      */
1368     public static final String AUTOFILL_HINT_CREDENTIAL_MANAGER = "credential";
1369 
1370     /**
1371      * Hints for the autofill services that describes the content of the view.
1372      */
1373     private @Nullable String[] mAutofillHints;
1374 
1375     /**
1376      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1377      */
1378     private AutofillId mAutofillId;
1379 
1380     /** @hide */
1381     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1382             AUTOFILL_TYPE_NONE,
1383             AUTOFILL_TYPE_TEXT,
1384             AUTOFILL_TYPE_TOGGLE,
1385             AUTOFILL_TYPE_LIST,
1386             AUTOFILL_TYPE_DATE,
1387     })
1388     @Retention(RetentionPolicy.SOURCE)
1389     public @interface AutofillType {}
1390 
1391     /**
1392      * Autofill type for views that cannot be autofilled.
1393      *
1394      * <p>Typically used when the view is read-only; for example, a text label.
1395      *
1396      * @see #getAutofillType()
1397      */
1398     public static final int AUTOFILL_TYPE_NONE = 0;
1399 
1400     /**
1401      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1402      *
1403      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1404      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1405      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1406      *
1407      * @see #getAutofillType()
1408      */
1409     public static final int AUTOFILL_TYPE_TEXT = 1;
1410 
1411     /**
1412      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1413      *
1414      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1415      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1416      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1417      *
1418      * @see #getAutofillType()
1419      */
1420     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1421 
1422     /**
1423      * Autofill type for a selection list field, which is filled by an {@code int}
1424      * representing the element index inside the list (starting at {@code 0}).
1425      *
1426      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1427      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1428      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1429      *
1430      * <p>The available options in the selection list are typically provided by
1431      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1432      *
1433      * @see #getAutofillType()
1434      */
1435     public static final int AUTOFILL_TYPE_LIST = 3;
1436 
1437     /**
1438      * Autofill type for a field that contains a date, which is represented by a long representing
1439      * the number of milliseconds since the standard base time known as "the epoch", namely
1440      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1441      *
1442      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1443      * {@link AutofillValue#forDate(long)}, and the values passed to
1444      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1445      *
1446      * @see #getAutofillType()
1447      */
1448     public static final int AUTOFILL_TYPE_DATE = 4;
1449 
1450 
1451     /** @hide */
1452     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1453             IMPORTANT_FOR_AUTOFILL_AUTO,
1454             IMPORTANT_FOR_AUTOFILL_YES,
1455             IMPORTANT_FOR_AUTOFILL_NO,
1456             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1457             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1458     })
1459     @Retention(RetentionPolicy.SOURCE)
1460     public @interface AutofillImportance {}
1461 
1462     /**
1463      * Automatically determine whether a view is important for autofill.
1464      *
1465      * @see #isImportantForAutofill()
1466      * @see #setImportantForAutofill(int)
1467      */
1468     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1469 
1470     /**
1471      * The view is important for autofill, and its children (if any) will be traversed.
1472      *
1473      * @see #isImportantForAutofill()
1474      * @see #setImportantForAutofill(int)
1475      */
1476     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1477 
1478     /**
1479      * The view is not important for autofill, but its children (if any) will be traversed.
1480      *
1481      * @see #isImportantForAutofill()
1482      * @see #setImportantForAutofill(int)
1483      */
1484     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1485 
1486     /**
1487      * The view is important for autofill, but its children (if any) will not be traversed.
1488      *
1489      * @see #isImportantForAutofill()
1490      * @see #setImportantForAutofill(int)
1491      */
1492     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1493 
1494     /**
1495      * The view is not important for autofill, and its children (if any) will not be traversed.
1496      *
1497      * @see #isImportantForAutofill()
1498      * @see #setImportantForAutofill(int)
1499      */
1500     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1501 
1502     /** @hide */
1503     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1504             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1505     })
1506     @Retention(RetentionPolicy.SOURCE)
1507     public @interface AutofillFlags {}
1508 
1509     /**
1510      * Flag requesting you to add views that are marked as not important for autofill
1511      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1512      */
1513     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1514 
1515     /** @hide */
1516     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1517             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1518             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1519             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1520             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1521             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1522     })
1523     @Retention(RetentionPolicy.SOURCE)
1524     public @interface ContentCaptureImportance {}
1525 
1526     /**
1527      * Automatically determine whether a view is important for content capture.
1528      *
1529      * @see #isImportantForContentCapture()
1530      * @see #setImportantForContentCapture(int)
1531      */
1532     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1533 
1534     /**
1535      * The view is important for content capture, and its children (if any) will be traversed.
1536      *
1537      * @see #isImportantForContentCapture()
1538      * @see #setImportantForContentCapture(int)
1539      */
1540     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1541 
1542     /**
1543      * The view is not important for content capture, but its children (if any) will be traversed.
1544      *
1545      * @see #isImportantForContentCapture()
1546      * @see #setImportantForContentCapture(int)
1547      */
1548     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1549 
1550     /**
1551      * The view is important for content capture, but its children (if any) will not be traversed.
1552      *
1553      * @see #isImportantForContentCapture()
1554      * @see #setImportantForContentCapture(int)
1555      */
1556     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1557 
1558     /**
1559      * The view is not important for content capture, and its children (if any) will not be
1560      * traversed.
1561      *
1562      * @see #isImportantForContentCapture()
1563      * @see #setImportantForContentCapture(int)
1564      */
1565     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1566 
1567     /** {@hide} */
1568     @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
1569             value = {
1570                     SCROLL_CAPTURE_HINT_AUTO,
1571                     SCROLL_CAPTURE_HINT_EXCLUDE,
1572                     SCROLL_CAPTURE_HINT_INCLUDE,
1573                     SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
1574     })
1575     @Retention(RetentionPolicy.SOURCE)
1576     public @interface ScrollCaptureHint {}
1577 
1578     /**
1579      * The content of this view will be considered for scroll capture if scrolling is possible.
1580      *
1581      * @see #getScrollCaptureHint()
1582      * @see #setScrollCaptureHint(int)
1583      */
1584     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
1585 
1586     /**
1587      * Explicitly exclude this view as a potential scroll capture target. The system will not
1588      * consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
1589      * takes precedence over.
1590      *
1591      * @see #getScrollCaptureHint()
1592      * @see #setScrollCaptureHint(int)
1593      */
1594     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
1595 
1596     /**
1597      * Explicitly include this view as a potential scroll capture target. When locating a scroll
1598      * capture target, this view will be prioritized before others without this flag. Mutually
1599      * exclusive with {@link #SCROLL_CAPTURE_HINT_EXCLUDE}, which takes precedence.
1600      *
1601      * @see #getScrollCaptureHint()
1602      * @see #setScrollCaptureHint(int)
1603      */
1604     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
1605 
1606     /**
1607      * Explicitly exclude all children of this view as potential scroll capture targets. This view
1608      * is unaffected. Note: Excluded children are not considered, regardless of {@link
1609      * #SCROLL_CAPTURE_HINT_INCLUDE}.
1610      *
1611      * @see #getScrollCaptureHint()
1612      * @see #setScrollCaptureHint(int)
1613      */
1614     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
1615 
1616     /**
1617      * This view is enabled. Interpretation varies by subclass.
1618      * Use with ENABLED_MASK when calling setFlags.
1619      * {@hide}
1620      */
1621     static final int ENABLED = 0x00000000;
1622 
1623     /**
1624      * This view is disabled. Interpretation varies by subclass.
1625      * Use with ENABLED_MASK when calling setFlags.
1626      * {@hide}
1627      */
1628     static final int DISABLED = 0x00000020;
1629 
1630     /**
1631      * Mask for use with setFlags indicating bits used for indicating whether
1632      * this view is enabled
1633      * {@hide}
1634      */
1635     static final int ENABLED_MASK = 0x00000020;
1636 
1637     /**
1638      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1639      * called and further optimizations will be performed. It is okay to have
1640      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1641      * {@hide}
1642      */
1643     static final int WILL_NOT_DRAW = 0x00000080;
1644 
1645     /**
1646      * Mask for use with setFlags indicating bits used for indicating whether
1647      * this view is will draw
1648      * {@hide}
1649      */
1650     static final int DRAW_MASK = 0x00000080;
1651 
1652     /**
1653      * <p>This view doesn't show scrollbars.</p>
1654      * {@hide}
1655      */
1656     static final int SCROLLBARS_NONE = 0x00000000;
1657 
1658     /**
1659      * <p>This view shows horizontal scrollbars.</p>
1660      * {@hide}
1661      */
1662     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1663 
1664     /**
1665      * <p>This view shows vertical scrollbars.</p>
1666      * {@hide}
1667      */
1668     static final int SCROLLBARS_VERTICAL = 0x00000200;
1669 
1670     /**
1671      * <p>Mask for use with setFlags indicating bits used for indicating which
1672      * scrollbars are enabled.</p>
1673      * {@hide}
1674      */
1675     static final int SCROLLBARS_MASK = 0x00000300;
1676 
1677     /**
1678      * Indicates that the view should filter touches when its window is obscured.
1679      * Refer to the class comments for more information about this security feature.
1680      * {@hide}
1681      */
1682     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1683 
1684     /**
1685      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1686      * that they are optional and should be skipped if the window has
1687      * requested system UI flags that ignore those insets for layout.
1688      * <p>
1689      * This is only used for support library as of Android R. The framework now uses
1690      * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
1691      * insets path that loses insets information.
1692      */
1693     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1694 
1695     /**
1696      * <p>This view doesn't show fading edges.</p>
1697      * {@hide}
1698      */
1699     static final int FADING_EDGE_NONE = 0x00000000;
1700 
1701     /**
1702      * <p>This view shows horizontal fading edges.</p>
1703      * {@hide}
1704      */
1705     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1706 
1707     /**
1708      * <p>This view shows vertical fading edges.</p>
1709      * {@hide}
1710      */
1711     static final int FADING_EDGE_VERTICAL = 0x00002000;
1712 
1713     /**
1714      * <p>Mask for use with setFlags indicating bits used for indicating which
1715      * fading edges are enabled.</p>
1716      * {@hide}
1717      */
1718     static final int FADING_EDGE_MASK = 0x00003000;
1719 
1720     /**
1721      * <p>Indicates this view can be clicked. When clickable, a View reacts
1722      * to clicks by notifying the OnClickListener.<p>
1723      * {@hide}
1724      */
1725     static final int CLICKABLE = 0x00004000;
1726 
1727     /**
1728      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1729      * {@hide}
1730      */
1731     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1732 
1733     /**
1734      * <p>Indicates that no icicle should be saved for this view.<p>
1735      * {@hide}
1736      */
1737     static final int SAVE_DISABLED = 0x000010000;
1738 
1739     /**
1740      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1741      * property.</p>
1742      * {@hide}
1743      */
1744     static final int SAVE_DISABLED_MASK = 0x000010000;
1745 
1746     /**
1747      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1748      * {@hide}
1749      */
1750     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1751 
1752     /**
1753      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1754      * {@hide}
1755      */
1756     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1757 
1758     /** @hide */
1759     @Retention(RetentionPolicy.SOURCE)
1760     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1761             DRAWING_CACHE_QUALITY_LOW,
1762             DRAWING_CACHE_QUALITY_HIGH,
1763             DRAWING_CACHE_QUALITY_AUTO
1764     })
1765     public @interface DrawingCacheQuality {}
1766 
1767     /**
1768      * <p>Enables low quality mode for the drawing cache.</p>
1769      *
1770      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1771      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1772      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1773      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1774      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1775      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1776      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1777      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1778      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1779      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1780      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1781      * reports or unit testing the {@link PixelCopy} API is recommended.
1782      */
1783     @Deprecated
1784     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1785 
1786     /**
1787      * <p>Enables high quality mode for the drawing cache.</p>
1788      *
1789      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1790      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1791      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1792      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1793      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1794      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1795      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1796      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1797      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1798      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1799      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1800      * reports or unit testing the {@link PixelCopy} API is recommended.
1801      */
1802     @Deprecated
1803     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1804 
1805     /**
1806      * <p>Enables automatic quality mode for the drawing cache.</p>
1807      *
1808      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1809      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1810      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1811      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1812      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1813      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1814      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1815      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1816      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1817      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1818      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1819      * reports or unit testing the {@link PixelCopy} API is recommended.
1820      */
1821     @Deprecated
1822     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1823 
1824     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1825             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1826     };
1827 
1828     /**
1829      * <p>Mask for use with setFlags indicating bits used for the cache
1830      * quality property.</p>
1831      * {@hide}
1832      */
1833     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1834 
1835     /**
1836      * <p>
1837      * Indicates this view can be long clicked. When long clickable, a View
1838      * reacts to long clicks by notifying the OnLongClickListener or showing a
1839      * context menu.
1840      * </p>
1841      * {@hide}
1842      */
1843     static final int LONG_CLICKABLE = 0x00200000;
1844 
1845     /**
1846      * <p>Indicates that this view gets its drawable states from its direct parent
1847      * and ignores its original internal states.</p>
1848      *
1849      * @hide
1850      */
1851     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1852 
1853     /**
1854      * <p>
1855      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1856      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1857      * OnContextClickListener.
1858      * </p>
1859      * {@hide}
1860      */
1861     static final int CONTEXT_CLICKABLE = 0x00800000;
1862 
1863     /** @hide */
1864     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1865             SCROLLBARS_INSIDE_OVERLAY,
1866             SCROLLBARS_INSIDE_INSET,
1867             SCROLLBARS_OUTSIDE_OVERLAY,
1868             SCROLLBARS_OUTSIDE_INSET
1869     })
1870     @Retention(RetentionPolicy.SOURCE)
1871     public @interface ScrollBarStyle {}
1872 
1873     /**
1874      * The scrollbar style to display the scrollbars inside the content area,
1875      * without increasing the padding. The scrollbars will be overlaid with
1876      * translucency on the view's content.
1877      */
1878     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1879 
1880     /**
1881      * The scrollbar style to display the scrollbars inside the padded area,
1882      * increasing the padding of the view. The scrollbars will not overlap the
1883      * content area of the view.
1884      */
1885     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1886 
1887     /**
1888      * The scrollbar style to display the scrollbars at the edge of the view,
1889      * without increasing the padding. The scrollbars will be overlaid with
1890      * translucency.
1891      */
1892     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1893 
1894     /**
1895      * The scrollbar style to display the scrollbars at the edge of the view,
1896      * increasing the padding of the view. The scrollbars will only overlap the
1897      * background, if any.
1898      */
1899     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1900 
1901     /**
1902      * Mask to check if the scrollbar style is overlay or inset.
1903      * {@hide}
1904      */
1905     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1906 
1907     /**
1908      * Mask to check if the scrollbar style is inside or outside.
1909      * {@hide}
1910      */
1911     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1912 
1913     /**
1914      * Mask for scrollbar style.
1915      * {@hide}
1916      */
1917     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1918 
1919     /**
1920      * View flag indicating that the screen should remain on while the
1921      * window containing this view is visible to the user.  This effectively
1922      * takes care of automatically setting the WindowManager's
1923      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1924      */
1925     public static final int KEEP_SCREEN_ON = 0x04000000;
1926 
1927     /**
1928      * View flag indicating whether this view should have sound effects enabled
1929      * for events such as clicking and touching.
1930      */
1931     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1932 
1933     /**
1934      * View flag indicating whether this view should have haptic feedback
1935      * enabled for events such as long presses.
1936      */
1937     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1938 
1939     /**
1940      * <p>Indicates that the view hierarchy should stop saving state when
1941      * it reaches this view.  If state saving is initiated immediately at
1942      * the view, it will be allowed.
1943      * {@hide}
1944      */
1945     static final int PARENT_SAVE_DISABLED = 0x20000000;
1946 
1947     /**
1948      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1949      * {@hide}
1950      */
1951     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1952 
1953     private static Paint sDebugPaint;
1954 
1955     /**
1956      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1957      * {@hide}
1958      */
1959     static final int TOOLTIP = 0x40000000;
1960 
1961     /** @hide */
1962     @IntDef(prefix = { "CONTENT_SENSITIVITY_" }, value = {
1963             CONTENT_SENSITIVITY_AUTO,
1964             CONTENT_SENSITIVITY_SENSITIVE,
1965             CONTENT_SENSITIVITY_NOT_SENSITIVE
1966     })
1967     @Retention(RetentionPolicy.SOURCE)
1968     public @interface ContentSensitivity {}
1969 
1970     /**
1971      * Content sensitivity is determined by the framework. The framework uses a heuristic to
1972      * determine if this view displays sensitive content.
1973      * Autofill hints i.e. {@link #getAutofillHints()}  are used in the heuristic
1974      * to determine if this view should be considered as a sensitive view.
1975      * <p>
1976      * {@link #AUTOFILL_HINT_USERNAME},
1977      * {@link #AUTOFILL_HINT_PASSWORD},
1978      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER},
1979      * {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
1980      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
1981      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1982      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1983      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}
1984      * are considered sensitive hints by the framework, and the list may include more hints
1985      * in the future.
1986      *
1987      * <p> The window hosting a sensitive view will be marked as secure during an active media
1988      * projection session. This would be equivalent to applying
1989      * {@link android.view.WindowManager.LayoutParams#FLAG_SECURE} to the window.
1990      *
1991      * @see #getContentSensitivity()
1992      */
1993     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
1994     public static final int CONTENT_SENSITIVITY_AUTO = 0x0;
1995 
1996     /**
1997      * The view displays sensitive content.
1998      *
1999      * <p> The window hosting a sensitive view will be marked as secure during an active media
2000      * projection session. This would be equivalent to applying
2001      * {@link android.view.WindowManager.LayoutParams#FLAG_SECURE} to the window.
2002      *
2003      * @see #getContentSensitivity()
2004      */
2005     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
2006     public static final int CONTENT_SENSITIVITY_SENSITIVE = 0x1;
2007 
2008     /**
2009      * The view doesn't display sensitive content.
2010      *
2011      * @see #getContentSensitivity()
2012      */
2013     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
2014     public static final int CONTENT_SENSITIVITY_NOT_SENSITIVE = 0x2;
2015 
2016     /** @hide */
2017     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
2018             FOCUSABLES_ALL,
2019             FOCUSABLES_TOUCH_MODE
2020     })
2021     @Retention(RetentionPolicy.SOURCE)
2022     public @interface FocusableMode {}
2023 
2024     /**
2025      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
2026      * should add all focusable Views regardless if they are focusable in touch mode.
2027      */
2028     public static final int FOCUSABLES_ALL = 0x00000000;
2029 
2030     /**
2031      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
2032      * should add only Views focusable in touch mode.
2033      */
2034     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
2035 
2036     /** @hide */
2037     @IntDef(prefix = { "FOCUS_" }, value = {
2038             FOCUS_BACKWARD,
2039             FOCUS_FORWARD,
2040             FOCUS_LEFT,
2041             FOCUS_UP,
2042             FOCUS_RIGHT,
2043             FOCUS_DOWN
2044     })
2045     @Retention(RetentionPolicy.SOURCE)
2046     public @interface FocusDirection {}
2047 
2048     /** @hide */
2049     @IntDef(prefix = { "FOCUS_" }, value = {
2050             FOCUS_LEFT,
2051             FOCUS_UP,
2052             FOCUS_RIGHT,
2053             FOCUS_DOWN
2054     })
2055     @Retention(RetentionPolicy.SOURCE)
2056     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
2057 
2058     /**
2059      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
2060      * item.
2061      */
2062     public static final int FOCUS_BACKWARD = 0x00000001;
2063 
2064     /**
2065      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
2066      * item.
2067      */
2068     public static final int FOCUS_FORWARD = 0x00000002;
2069 
2070     /**
2071      * Use with {@link #focusSearch(int)}. Move focus to the left.
2072      */
2073     public static final int FOCUS_LEFT = 0x00000011;
2074 
2075     /**
2076      * Use with {@link #focusSearch(int)}. Move focus up.
2077      */
2078     public static final int FOCUS_UP = 0x00000021;
2079 
2080     /**
2081      * Use with {@link #focusSearch(int)}. Move focus to the right.
2082      */
2083     public static final int FOCUS_RIGHT = 0x00000042;
2084 
2085     /**
2086      * Use with {@link #focusSearch(int)}. Move focus down.
2087      */
2088     public static final int FOCUS_DOWN = 0x00000082;
2089 
2090     /**
2091      * Bits of {@link #getMeasuredWidthAndState()} and
2092      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
2093      */
2094     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
2095 
2096     /**
2097      * Bits of {@link #getMeasuredWidthAndState()} and
2098      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
2099      */
2100     public static final int MEASURED_STATE_MASK = 0xff000000;
2101 
2102     /**
2103      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
2104      * for functions that combine both width and height into a single int,
2105      * such as {@link #getMeasuredState()} and the childState argument of
2106      * {@link #resolveSizeAndState(int, int, int)}.
2107      */
2108     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
2109 
2110     /**
2111      * Bit of {@link #getMeasuredWidthAndState()} and
2112      * {@link #getMeasuredWidthAndState()} that indicates the measured size
2113      * is smaller that the space the view would like to have.
2114      */
2115     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
2116 
2117     /**
2118      * Base View state sets
2119      */
2120     // Singles
2121     /**
2122      * Indicates the view has no states set. States are used with
2123      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2124      * view depending on its state.
2125      *
2126      * @see android.graphics.drawable.Drawable
2127      * @see #getDrawableState()
2128      */
2129     protected static final int[] EMPTY_STATE_SET;
2130     /**
2131      * Indicates the view is enabled. States are used with
2132      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2133      * view depending on its state.
2134      *
2135      * @see android.graphics.drawable.Drawable
2136      * @see #getDrawableState()
2137      */
2138     protected static final int[] ENABLED_STATE_SET;
2139     /**
2140      * Indicates the view is focused. States are used with
2141      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2142      * view depending on its state.
2143      *
2144      * @see android.graphics.drawable.Drawable
2145      * @see #getDrawableState()
2146      */
2147     protected static final int[] FOCUSED_STATE_SET;
2148     /**
2149      * Indicates the view is selected. States are used with
2150      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2151      * view depending on its state.
2152      *
2153      * @see android.graphics.drawable.Drawable
2154      * @see #getDrawableState()
2155      */
2156     protected static final int[] SELECTED_STATE_SET;
2157     /**
2158      * Indicates the view is pressed. States are used with
2159      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2160      * view depending on its state.
2161      *
2162      * @see android.graphics.drawable.Drawable
2163      * @see #getDrawableState()
2164      */
2165     protected static final int[] PRESSED_STATE_SET;
2166     /**
2167      * Indicates the view's window has focus. States are used with
2168      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2169      * view depending on its state.
2170      *
2171      * @see android.graphics.drawable.Drawable
2172      * @see #getDrawableState()
2173      */
2174     protected static final int[] WINDOW_FOCUSED_STATE_SET;
2175     // Doubles
2176     /**
2177      * Indicates the view is enabled and has the focus.
2178      *
2179      * @see #ENABLED_STATE_SET
2180      * @see #FOCUSED_STATE_SET
2181      */
2182     protected static final int[] ENABLED_FOCUSED_STATE_SET;
2183     /**
2184      * Indicates the view is enabled and selected.
2185      *
2186      * @see #ENABLED_STATE_SET
2187      * @see #SELECTED_STATE_SET
2188      */
2189     protected static final int[] ENABLED_SELECTED_STATE_SET;
2190     /**
2191      * Indicates the view is enabled and that its window has focus.
2192      *
2193      * @see #ENABLED_STATE_SET
2194      * @see #WINDOW_FOCUSED_STATE_SET
2195      */
2196     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
2197     /**
2198      * Indicates the view is focused and selected.
2199      *
2200      * @see #FOCUSED_STATE_SET
2201      * @see #SELECTED_STATE_SET
2202      */
2203     protected static final int[] FOCUSED_SELECTED_STATE_SET;
2204     /**
2205      * Indicates the view has the focus and that its window has the focus.
2206      *
2207      * @see #FOCUSED_STATE_SET
2208      * @see #WINDOW_FOCUSED_STATE_SET
2209      */
2210     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
2211     /**
2212      * Indicates the view is selected and that its window has the focus.
2213      *
2214      * @see #SELECTED_STATE_SET
2215      * @see #WINDOW_FOCUSED_STATE_SET
2216      */
2217     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2218     // Triples
2219     /**
2220      * Indicates the view is enabled, focused and selected.
2221      *
2222      * @see #ENABLED_STATE_SET
2223      * @see #FOCUSED_STATE_SET
2224      * @see #SELECTED_STATE_SET
2225      */
2226     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2227     /**
2228      * Indicates the view is enabled, focused and its window has the focus.
2229      *
2230      * @see #ENABLED_STATE_SET
2231      * @see #FOCUSED_STATE_SET
2232      * @see #WINDOW_FOCUSED_STATE_SET
2233      */
2234     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2235     /**
2236      * Indicates the view is enabled, selected and its window has the focus.
2237      *
2238      * @see #ENABLED_STATE_SET
2239      * @see #SELECTED_STATE_SET
2240      * @see #WINDOW_FOCUSED_STATE_SET
2241      */
2242     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2243     /**
2244      * Indicates the view is focused, selected and its window has the focus.
2245      *
2246      * @see #FOCUSED_STATE_SET
2247      * @see #SELECTED_STATE_SET
2248      * @see #WINDOW_FOCUSED_STATE_SET
2249      */
2250     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2251     /**
2252      * Indicates the view is enabled, focused, selected and its window
2253      * has the focus.
2254      *
2255      * @see #ENABLED_STATE_SET
2256      * @see #FOCUSED_STATE_SET
2257      * @see #SELECTED_STATE_SET
2258      * @see #WINDOW_FOCUSED_STATE_SET
2259      */
2260     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2261     /**
2262      * Indicates the view is pressed and its window has the focus.
2263      *
2264      * @see #PRESSED_STATE_SET
2265      * @see #WINDOW_FOCUSED_STATE_SET
2266      */
2267     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2268     /**
2269      * Indicates the view is pressed and selected.
2270      *
2271      * @see #PRESSED_STATE_SET
2272      * @see #SELECTED_STATE_SET
2273      */
2274     protected static final int[] PRESSED_SELECTED_STATE_SET;
2275     /**
2276      * Indicates the view is pressed, selected and its window has the focus.
2277      *
2278      * @see #PRESSED_STATE_SET
2279      * @see #SELECTED_STATE_SET
2280      * @see #WINDOW_FOCUSED_STATE_SET
2281      */
2282     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2283     /**
2284      * Indicates the view is pressed and focused.
2285      *
2286      * @see #PRESSED_STATE_SET
2287      * @see #FOCUSED_STATE_SET
2288      */
2289     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2290     /**
2291      * Indicates the view is pressed, focused and its window has the focus.
2292      *
2293      * @see #PRESSED_STATE_SET
2294      * @see #FOCUSED_STATE_SET
2295      * @see #WINDOW_FOCUSED_STATE_SET
2296      */
2297     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2298     /**
2299      * Indicates the view is pressed, focused and selected.
2300      *
2301      * @see #PRESSED_STATE_SET
2302      * @see #SELECTED_STATE_SET
2303      * @see #FOCUSED_STATE_SET
2304      */
2305     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2306     /**
2307      * Indicates the view is pressed, focused, selected and its window has the focus.
2308      *
2309      * @see #PRESSED_STATE_SET
2310      * @see #FOCUSED_STATE_SET
2311      * @see #SELECTED_STATE_SET
2312      * @see #WINDOW_FOCUSED_STATE_SET
2313      */
2314     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2315     /**
2316      * Indicates the view is pressed and enabled.
2317      *
2318      * @see #PRESSED_STATE_SET
2319      * @see #ENABLED_STATE_SET
2320      */
2321     protected static final int[] PRESSED_ENABLED_STATE_SET;
2322     /**
2323      * Indicates the view is pressed, enabled and its window has the focus.
2324      *
2325      * @see #PRESSED_STATE_SET
2326      * @see #ENABLED_STATE_SET
2327      * @see #WINDOW_FOCUSED_STATE_SET
2328      */
2329     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2330     /**
2331      * Indicates the view is pressed, enabled and selected.
2332      *
2333      * @see #PRESSED_STATE_SET
2334      * @see #ENABLED_STATE_SET
2335      * @see #SELECTED_STATE_SET
2336      */
2337     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2338     /**
2339      * Indicates the view is pressed, enabled, selected and its window has the
2340      * focus.
2341      *
2342      * @see #PRESSED_STATE_SET
2343      * @see #ENABLED_STATE_SET
2344      * @see #SELECTED_STATE_SET
2345      * @see #WINDOW_FOCUSED_STATE_SET
2346      */
2347     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2348     /**
2349      * Indicates the view is pressed, enabled and focused.
2350      *
2351      * @see #PRESSED_STATE_SET
2352      * @see #ENABLED_STATE_SET
2353      * @see #FOCUSED_STATE_SET
2354      */
2355     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2356     /**
2357      * Indicates the view is pressed, enabled, focused and its window has the
2358      * focus.
2359      *
2360      * @see #PRESSED_STATE_SET
2361      * @see #ENABLED_STATE_SET
2362      * @see #FOCUSED_STATE_SET
2363      * @see #WINDOW_FOCUSED_STATE_SET
2364      */
2365     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2366     /**
2367      * Indicates the view is pressed, enabled, focused and selected.
2368      *
2369      * @see #PRESSED_STATE_SET
2370      * @see #ENABLED_STATE_SET
2371      * @see #SELECTED_STATE_SET
2372      * @see #FOCUSED_STATE_SET
2373      */
2374     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2375     /**
2376      * Indicates the view is pressed, enabled, focused, selected and its window
2377      * has the focus.
2378      *
2379      * @see #PRESSED_STATE_SET
2380      * @see #ENABLED_STATE_SET
2381      * @see #SELECTED_STATE_SET
2382      * @see #FOCUSED_STATE_SET
2383      * @see #WINDOW_FOCUSED_STATE_SET
2384      */
2385     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2386 
2387     /**
2388      * This indicates that the frame rate category was chosen for an unknown reason.
2389      * @hide
2390      */
2391     public static final int FRAME_RATE_CATEGORY_REASON_UNKNOWN = 0x0000_0000;
2392 
2393     /**
2394      * This indicates that the frame rate category was chosen because it was a small area update.
2395      * @hide
2396      */
2397     public static final int FRAME_RATE_CATEGORY_REASON_SMALL = 0x0100_0000;
2398 
2399     /**
2400      * This indicates that the frame rate category was chosen because it was an intermittent update.
2401      * @hide
2402      */
2403     public static final int FRAME_RATE_CATEGORY_REASON_INTERMITTENT = 0x0200_0000;
2404 
2405     /**
2406      * This indicates that the frame rate category was chosen because it was a large View.
2407      * @hide
2408      */
2409     public static final int FRAME_RATE_CATEGORY_REASON_LARGE = 0x03000000;
2410 
2411     /**
2412      * This indicates that the frame rate category was chosen because it was requested.
2413      * @hide
2414      */
2415     public static final int FRAME_RATE_CATEGORY_REASON_REQUESTED = 0x0400_0000;
2416 
2417     /**
2418      * This indicates that the frame rate category was chosen because an invalid frame rate was
2419      * requested.
2420      * @hide
2421      */
2422     public static final int FRAME_RATE_CATEGORY_REASON_INVALID = 0x0500_0000;
2423 
2424     /**
2425      * This indicates that the frame rate category was chosen because the view has a velocity
2426      * @hide
2427      */
2428     public static final int FRAME_RATE_CATEGORY_REASON_VELOCITY = 0x0600_0000;
2429 
2430     /**
2431      * This indicates that the frame rate category was chosen because it is currently boosting.
2432      * @hide
2433      */
2434     public static final int FRAME_RATE_CATEGORY_REASON_BOOST = 0x0800_0000;
2435 
2436     /**
2437      * This indicates that the frame rate category was chosen because it is currently having
2438      * touch boost.
2439      * @hide
2440      */
2441     public static final int FRAME_RATE_CATEGORY_REASON_TOUCH = 0x0900_0000;
2442 
2443     /**
2444      * This indicates that the frame rate category was chosen because it is currently having
2445      * touch boost.
2446      * @hide
2447      */
2448     public static final int FRAME_RATE_CATEGORY_REASON_CONFLICTED = 0x0A00_0000;
2449 
2450     private static final int FRAME_RATE_CATEGORY_REASON_MASK = 0xFFFF_0000;
2451 
2452     /**
2453      * @hide
2454      */
2455     protected static boolean sToolkitSetFrameRateReadOnlyFlagValue;
2456     private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
2457     private static final boolean sToolkitFrameRateDefaultNormalReadOnlyFlagValue =
2458             toolkitFrameRateDefaultNormalReadOnly();
2459     private static final boolean sToolkitFrameRateBySizeReadOnlyFlagValue =
2460             toolkitFrameRateBySizeReadOnly();
2461 
2462     private static final boolean sToolkitFrameRateSmallUsesPercentReadOnlyFlagValue =
2463             toolkitFrameRateSmallUsesPercentReadOnly();
2464     private static final boolean sToolkitFrameRateViewEnablingReadOnlyFlagValue =
2465             toolkitFrameRateViewEnablingReadOnly();
2466     private static boolean sToolkitFrameRateVelocityMappingReadOnlyFlagValue =
2467             toolkitFrameRateVelocityMappingReadOnly();
2468 
2469     // Used to set frame rate compatibility.
2470     @Surface.FrameRateCompatibility int mFrameRateCompatibility =
2471             FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
2472 
2473     static {
2474         EMPTY_STATE_SET = StateSet.get(0);
2475 
2476         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2477 
2478         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2479         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2480                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2481 
2482         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2483         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2484                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2485         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2486                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2487         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2488                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2489                         | StateSet.VIEW_STATE_FOCUSED);
2490 
2491         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2492         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2493                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2494         ENABLED_SELECTED_STATE_SET = StateSet.get(
2495                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2496         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2497                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2498                         | StateSet.VIEW_STATE_ENABLED);
2499         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2500                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2501         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2502                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2503                         | StateSet.VIEW_STATE_ENABLED);
2504         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2505                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2506                         | StateSet.VIEW_STATE_ENABLED);
2507         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2508                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2509                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2510 
2511         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2512         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2513                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2514         PRESSED_SELECTED_STATE_SET = StateSet.get(
2515                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2516         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2517                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2518                         | StateSet.VIEW_STATE_PRESSED);
2519         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2520                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2521         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2522                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2523                         | StateSet.VIEW_STATE_PRESSED);
2524         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2525                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2526                         | StateSet.VIEW_STATE_PRESSED);
2527         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2528                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2529                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2530         PRESSED_ENABLED_STATE_SET = StateSet.get(
2531                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2532         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2533                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2534                         | StateSet.VIEW_STATE_PRESSED);
2535         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2536                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2537                         | StateSet.VIEW_STATE_PRESSED);
2538         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2539                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2540                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2541         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2542                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2543                         | StateSet.VIEW_STATE_PRESSED);
2544         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2545                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2546                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2547         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2548                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2549                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2550         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2551                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2552                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2553                         | StateSet.VIEW_STATE_PRESSED);
2554 
2555         sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
2556         sToolkitMetricsForFrameRateDecisionFlagValue = toolkitMetricsForFrameRateDecision();
2557         sUseMeasureCacheDuringForceLayoutFlagValue = enableUseMeasureCacheDuringForceLayout();
2558     }
2559 
2560     /**
2561      * Accessibility event types that are dispatched for text population.
2562      */
2563     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2564             AccessibilityEvent.TYPE_VIEW_CLICKED
2565             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2566             | AccessibilityEvent.TYPE_VIEW_SELECTED
2567             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2568             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2569             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2570             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2571             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2572             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2573             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2574             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2575 
2576     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2577 
2578     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2579 
2580     /**
2581      * Temporary Rect currently for use in setBackground().  This will probably
2582      * be extended in the future to hold our own class with more than just
2583      * a Rect. :)
2584      */
2585     static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
2586 
2587     /**
2588      * Map used to store views' tags.
2589      */
2590     @UnsupportedAppUsage
2591     private SparseArray<Object> mKeyedTags;
2592 
2593     /**
2594      * The next available accessibility id.
2595      */
2596     private static int sNextAccessibilityViewId;
2597 
2598     /**
2599      * The animation currently associated with this view.
2600      * @hide
2601      */
2602     protected Animation mCurrentAnimation = null;
2603 
2604     /**
2605      * Width as measured during measure pass.
2606      * {@hide}
2607      */
2608     @ViewDebug.ExportedProperty(category = "measurement")
2609     @UnsupportedAppUsage
2610     int mMeasuredWidth;
2611 
2612     /**
2613      * Height as measured during measure pass.
2614      * {@hide}
2615      */
2616     @ViewDebug.ExportedProperty(category = "measurement")
2617     @UnsupportedAppUsage
2618     int mMeasuredHeight;
2619 
2620     /**
2621      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2622      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2623      * its display list. This flag, used only when hw accelerated, allows us to clear the
2624      * flag while retaining this information until it's needed (at getDisplayList() time and
2625      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2626      *
2627      * {@hide}
2628      */
2629     @UnsupportedAppUsage
2630     boolean mRecreateDisplayList = false;
2631 
2632     /**
2633      * The view's identifier.
2634      * {@hide}
2635      *
2636      * @see #setId(int)
2637      * @see #getId()
2638      */
2639     @IdRes
2640     @ViewDebug.ExportedProperty(resolveId = true)
2641     int mID = NO_ID;
2642 
2643     /** The ID of this view for autofill purposes.
2644      * <ul>
2645      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2646      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2647      *                                                  unique in the process. This might change
2648      *                                                  over activity lifecycle events.
2649      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2650      *                                                  unique in the activity. This stays the same
2651      *                                                  over activity lifecycle events.
2652      */
2653     private int mAutofillViewId = NO_ID;
2654 
2655     // ID for accessibility purposes. This ID must be unique for every window
2656     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2657     private int mAccessibilityViewId = NO_ID;
2658 
2659     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2660 
2661     /**
2662      * The view's tag.
2663      * {@hide}
2664      *
2665      * @see #setTag(Object)
2666      * @see #getTag()
2667      */
2668     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2669     protected Object mTag = null;
2670 
2671     /*
2672      * Masks for mPrivateFlags, as generated by dumpFlags():
2673      *
2674      * |-------|-------|-------|-------|
2675      *                                 1 PFLAG_WANTS_FOCUS
2676      *                                1  PFLAG_FOCUSED
2677      *                               1   PFLAG_SELECTED
2678      *                              1    PFLAG_IS_ROOT_NAMESPACE
2679      *                             1     PFLAG_HAS_BOUNDS
2680      *                            1      PFLAG_DRAWN
2681      *                           1       PFLAG_DRAW_ANIMATION
2682      *                          1        PFLAG_SKIP_DRAW
2683      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2684      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2685      *                      1            PFLAG_MEASURED_DIMENSION_SET
2686      *                     1             PFLAG_FORCE_LAYOUT
2687      *                    1              PFLAG_LAYOUT_REQUIRED
2688      *                   1               PFLAG_PRESSED
2689      *                  1                PFLAG_DRAWING_CACHE_VALID
2690      *                 1                 PFLAG_ANIMATION_STARTED
2691      *                1                  PFLAG_SAVE_STATE_CALLED
2692      *               1                   PFLAG_ALPHA_SET
2693      *              1                    PFLAG_SCROLL_CONTAINER
2694      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2695      *            1                      PFLAG_DIRTY
2696      *            1                      PFLAG_DIRTY_MASK
2697      *          1                        PFLAG_OPAQUE_BACKGROUND
2698      *         1                         PFLAG_OPAQUE_SCROLLBARS
2699      *         11                        PFLAG_OPAQUE_MASK
2700      *        1                          PFLAG_PREPRESSED
2701      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2702      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2703      *     1                             PFLAG_HOVERED
2704      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2705      *   1                               PFLAG_ACTIVATED
2706      *  1                                PFLAG_INVALIDATED
2707      * |-------|-------|-------|-------|
2708      */
2709     /** {@hide} */
2710     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2711     /** {@hide} */
2712     static final int PFLAG_FOCUSED                     = 0x00000002;
2713     /** {@hide} */
2714     static final int PFLAG_SELECTED                    = 0x00000004;
2715     /** {@hide} */
2716     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2717     /** {@hide} */
2718     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2719     /** {@hide} */
2720     static final int PFLAG_DRAWN                       = 0x00000020;
2721     /**
2722      * When this flag is set, this view is running an animation on behalf of its
2723      * children and should therefore not cancel invalidate requests, even if they
2724      * lie outside of this view's bounds.
2725      *
2726      * {@hide}
2727      */
2728     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2729     /** {@hide} */
2730     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2731     /** {@hide} */
2732     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2733     /** {@hide} */
2734     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2735     /** {@hide} */
2736     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2737     /** {@hide} */
2738     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2739     /** {@hide} */
2740     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2741 
2742     private static final int PFLAG_PRESSED             = 0x00004000;
2743 
2744     /** {@hide} */
2745     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2746     /**
2747      * Flag used to indicate that this view should be drawn once more (and only once
2748      * more) after its animation has completed.
2749      * {@hide}
2750      */
2751     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2752 
2753     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2754 
2755     /**
2756      * Indicates that the View returned true when onSetAlpha() was called and that
2757      * the alpha must be restored.
2758      * {@hide}
2759      */
2760     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2761 
2762     /**
2763      * Set by {@link #setScrollContainer(boolean)}.
2764      */
2765     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2766 
2767     /**
2768      * Set by {@link #setScrollContainer(boolean)}.
2769      */
2770     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2771 
2772     /**
2773      * View flag indicating whether this view was invalidated (fully or partially.)
2774      *
2775      * @hide
2776      */
2777     static final int PFLAG_DIRTY                       = 0x00200000;
2778 
2779     /**
2780      * Mask for {@link #PFLAG_DIRTY}.
2781      *
2782      * @hide
2783      */
2784     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2785 
2786     /**
2787      * Indicates whether the background is opaque.
2788      *
2789      * @hide
2790      */
2791     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2792 
2793     /**
2794      * Indicates whether the scrollbars are opaque.
2795      *
2796      * @hide
2797      */
2798     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2799 
2800     /**
2801      * Indicates whether the view is opaque.
2802      *
2803      * @hide
2804      */
2805     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2806 
2807     /**
2808      * Indicates a prepressed state;
2809      * the short time between ACTION_DOWN and recognizing
2810      * a 'real' press. Prepressed is used to recognize quick taps
2811      * even when they are shorter than ViewConfiguration.getTapTimeout().
2812      *
2813      * @hide
2814      */
2815     private static final int PFLAG_PREPRESSED          = 0x02000000;
2816 
2817     /**
2818      * Indicates whether the view is temporarily detached.
2819      *
2820      * @hide
2821      */
2822     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2823 
2824     /**
2825      * Indicates that we should awaken scroll bars once attached
2826      *
2827      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2828      * during window attachment and it is no longer needed. Feel free to repurpose it.
2829      *
2830      * @hide
2831      */
2832     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2833 
2834     /**
2835      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2836      * @hide
2837      */
2838     private static final int PFLAG_HOVERED             = 0x10000000;
2839 
2840     /**
2841      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2842      */
2843     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2844 
2845     /** {@hide} */
2846     static final int PFLAG_ACTIVATED                   = 0x40000000;
2847 
2848     /**
2849      * Indicates that this view was specifically invalidated, not just dirtied because some
2850      * child view was invalidated. The flag is used to determine when we need to recreate
2851      * a view's display list (as opposed to just returning a reference to its existing
2852      * display list).
2853      *
2854      * @hide
2855      */
2856     static final int PFLAG_INVALIDATED                 = 0x80000000;
2857 
2858     /* End of masks for mPrivateFlags */
2859 
2860     /*
2861      * Masks for mPrivateFlags2, as generated by dumpFlags():
2862      *
2863      * |-------|-------|-------|-------|
2864      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2865      *                                1  PFLAG2_DRAG_HOVERED
2866      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2867      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2868      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2869      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2870      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2871      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2872      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2873      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2874      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2875      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2876      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2877      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2878      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2879      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2880      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2881      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2882      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2883      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2884      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2885      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2886      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2887      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2888      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2889      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2890      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2891      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2892      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2893      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2894      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2895      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2896      *    1                              PFLAG2_PADDING_RESOLVED
2897      *   1                               PFLAG2_DRAWABLE_RESOLVED
2898      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2899      * |-------|-------|-------|-------|
2900      */
2901 
2902     /**
2903      * Indicates that this view has reported that it can accept the current drag's content.
2904      * Cleared when the drag operation concludes.
2905      * @hide
2906      */
2907     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2908 
2909     /**
2910      * Indicates that this view is currently directly under the drag location in a
2911      * drag-and-drop operation involving content that it can accept.  Cleared when
2912      * the drag exits the view, or when the drag operation concludes.
2913      * @hide
2914      */
2915     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2916 
2917     /** @hide */
2918     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2919             LAYOUT_DIRECTION_LTR,
2920             LAYOUT_DIRECTION_RTL,
2921             LAYOUT_DIRECTION_INHERIT,
2922             LAYOUT_DIRECTION_LOCALE
2923     })
2924     @Retention(RetentionPolicy.SOURCE)
2925     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2926     public @interface LayoutDir {}
2927 
2928     /** @hide */
2929     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2930             LAYOUT_DIRECTION_LTR,
2931             LAYOUT_DIRECTION_RTL
2932     })
2933     @Retention(RetentionPolicy.SOURCE)
2934     public @interface ResolvedLayoutDir {}
2935 
2936     /**
2937      * A flag to indicate that the layout direction of this view has not been defined yet.
2938      * @hide
2939      */
2940     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2941 
2942     /**
2943      * Horizontal layout direction of this view is from Left to Right.
2944      * Use with {@link #setLayoutDirection}.
2945      */
2946     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2947 
2948     /**
2949      * Horizontal layout direction of this view is from Right to Left.
2950      * Use with {@link #setLayoutDirection}.
2951      */
2952     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2953 
2954     /**
2955      * Horizontal layout direction of this view is inherited from its parent.
2956      * Use with {@link #setLayoutDirection}.
2957      */
2958     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2959 
2960     /**
2961      * Horizontal layout direction of this view is from deduced from the default language
2962      * script for the locale. Use with {@link #setLayoutDirection}.
2963      */
2964     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2965 
2966     /**
2967      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2968      * @hide
2969      */
2970     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2971 
2972     /**
2973      * Mask for use with private flags indicating bits used for horizontal layout direction.
2974      * @hide
2975      */
2976     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2977 
2978     /**
2979      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2980      * right-to-left direction.
2981      * @hide
2982      */
2983     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2984 
2985     /**
2986      * Indicates whether the view horizontal layout direction has been resolved.
2987      * @hide
2988      */
2989     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2990 
2991     /**
2992      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2993      * @hide
2994      */
2995     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2996             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2997 
2998     /*
2999      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
3000      * flag value.
3001      * @hide
3002      */
3003     private static final int[] LAYOUT_DIRECTION_FLAGS = {
3004             LAYOUT_DIRECTION_LTR,
3005             LAYOUT_DIRECTION_RTL,
3006             LAYOUT_DIRECTION_INHERIT,
3007             LAYOUT_DIRECTION_LOCALE
3008     };
3009 
3010     /**
3011      * Default horizontal layout direction.
3012      */
3013     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
3014 
3015     /**
3016      * Default horizontal layout direction.
3017      * @hide
3018      */
3019     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
3020 
3021     /**
3022      * Text direction is inherited through {@link ViewGroup}
3023      */
3024     public static final int TEXT_DIRECTION_INHERIT = 0;
3025 
3026     /**
3027      * Text direction is using "first strong algorithm". The first strong directional character
3028      * determines the paragraph direction. If there is no strong directional character, the
3029      * paragraph direction is the view's resolved layout direction.
3030      */
3031     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
3032 
3033     /**
3034      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
3035      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
3036      * If there are neither, the paragraph direction is the view's resolved layout direction.
3037      */
3038     public static final int TEXT_DIRECTION_ANY_RTL = 2;
3039 
3040     /**
3041      * Text direction is forced to LTR.
3042      */
3043     public static final int TEXT_DIRECTION_LTR = 3;
3044 
3045     /**
3046      * Text direction is forced to RTL.
3047      */
3048     public static final int TEXT_DIRECTION_RTL = 4;
3049 
3050     /**
3051      * Text direction is coming from the system Locale.
3052      */
3053     public static final int TEXT_DIRECTION_LOCALE = 5;
3054 
3055     /**
3056      * Text direction is using "first strong algorithm". The first strong directional character
3057      * determines the paragraph direction. If there is no strong directional character, the
3058      * paragraph direction is LTR.
3059      */
3060     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
3061 
3062     /**
3063      * Text direction is using "first strong algorithm". The first strong directional character
3064      * determines the paragraph direction. If there is no strong directional character, the
3065      * paragraph direction is RTL.
3066      */
3067     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
3068 
3069     /**
3070      * Default text direction is inherited
3071      */
3072     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
3073 
3074     /**
3075      * Default resolved text direction
3076      * @hide
3077      */
3078     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
3079 
3080     /**
3081      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
3082      * @hide
3083      */
3084     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
3085 
3086     /**
3087      * Mask for use with private flags indicating bits used for text direction.
3088      * @hide
3089      */
3090     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
3091             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
3092 
3093     /**
3094      * Array of text direction flags for mapping attribute "textDirection" to correct
3095      * flag value.
3096      * @hide
3097      */
3098     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
3099             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3100             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3101             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3102             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3103             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3104             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3105             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3106             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
3107     };
3108 
3109     /**
3110      * Indicates whether the view text direction has been resolved.
3111      * @hide
3112      */
3113     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
3114             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
3115 
3116     /**
3117      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
3118      * @hide
3119      */
3120     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
3121 
3122     /**
3123      * Mask for use with private flags indicating bits used for resolved text direction.
3124      * @hide
3125      */
3126     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
3127             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
3128 
3129     /**
3130      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
3131      * @hide
3132      */
3133     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
3134             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
3135 
3136     /** @hide */
3137     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
3138             TEXT_ALIGNMENT_INHERIT,
3139             TEXT_ALIGNMENT_GRAVITY,
3140             TEXT_ALIGNMENT_CENTER,
3141             TEXT_ALIGNMENT_TEXT_START,
3142             TEXT_ALIGNMENT_TEXT_END,
3143             TEXT_ALIGNMENT_VIEW_START,
3144             TEXT_ALIGNMENT_VIEW_END
3145     })
3146     @Retention(RetentionPolicy.SOURCE)
3147     public @interface TextAlignment {}
3148 
3149     /**
3150      * Default text alignment. The text alignment of this View is inherited from its parent.
3151      * Use with {@link #setTextAlignment(int)}
3152      */
3153     public static final int TEXT_ALIGNMENT_INHERIT = 0;
3154 
3155     /**
3156      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
3157      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
3158      *
3159      * Use with {@link #setTextAlignment(int)}
3160      */
3161     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
3162 
3163     /**
3164      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
3165      *
3166      * Use with {@link #setTextAlignment(int)}
3167      */
3168     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
3169 
3170     /**
3171      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
3172      *
3173      * Use with {@link #setTextAlignment(int)}
3174      */
3175     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
3176 
3177     /**
3178      * Center the paragraph, e.g. ALIGN_CENTER.
3179      *
3180      * Use with {@link #setTextAlignment(int)}
3181      */
3182     public static final int TEXT_ALIGNMENT_CENTER = 4;
3183 
3184     /**
3185      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
3186      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
3187      *
3188      * Use with {@link #setTextAlignment(int)}
3189      */
3190     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
3191 
3192     /**
3193      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
3194      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
3195      *
3196      * Use with {@link #setTextAlignment(int)}
3197      */
3198     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
3199 
3200     /**
3201      * Default text alignment is inherited
3202      */
3203     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3204 
3205     /**
3206      * Default resolved text alignment
3207      * @hide
3208      */
3209     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3210 
3211     /**
3212       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
3213       * @hide
3214       */
3215     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
3216 
3217     /**
3218       * Mask for use with private flags indicating bits used for text alignment.
3219       * @hide
3220       */
3221     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3222 
3223     /**
3224      * Array of text direction flags for mapping attribute "textAlignment" to correct
3225      * flag value.
3226      * @hide
3227      */
3228     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
3229             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3230             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3231             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3232             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3233             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3234             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3235             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
3236     };
3237 
3238     /**
3239      * Indicates whether the view text alignment has been resolved.
3240      * @hide
3241      */
3242     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3243 
3244     /**
3245      * Bit shift to get the resolved text alignment.
3246      * @hide
3247      */
3248     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
3249 
3250     /**
3251      * Mask for use with private flags indicating bits used for text alignment.
3252      * @hide
3253      */
3254     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
3255             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3256 
3257     /**
3258      * Indicates whether if the view text alignment has been resolved to gravity
3259      */
3260     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
3261             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3262 
3263     // Accessiblity constants for mPrivateFlags2
3264 
3265     /**
3266      * Shift for the bits in {@link #mPrivateFlags2} related to the
3267      * "importantForAccessibility" attribute.
3268      */
3269     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
3270 
3271     /**
3272      * Automatically determine whether a view is important for accessibility.
3273      */
3274     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
3275 
3276     /**
3277      * The view is important for accessibility.
3278      */
3279     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
3280 
3281     /**
3282      * The view is not important for accessibility.
3283      */
3284     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
3285 
3286     /**
3287      * The view is not important for accessibility, nor are any of its
3288      * descendant views.
3289      */
3290     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
3291 
3292     /**
3293      * The default whether the view is important for accessibility.
3294      */
3295     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3296 
3297     /**
3298      * Automatically determine whether the view should only allow interactions from
3299      * {@link android.accessibilityservice.AccessibilityService}s with the
3300      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
3301      * set to true.
3302      *
3303      * <p>
3304      * Accessibility interactions from services without {@code isAccessibilityTool} set to true are
3305      * disallowed for any of the following conditions:
3306      * <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
3307      * <li>any parent of this view returns true from {@link #isAccessibilityDataSensitive()}.</li>
3308      * </p>
3309      */
3310     public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
3311 
3312     /**
3313      * Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
3314      * with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
3315      * property set to true.
3316      */
3317     public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
3318 
3319     /**
3320      * Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
3321      * regardless of their
3322      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
3323      */
3324     public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
3325 
3326     /** @hide */
3327     @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
3328             ACCESSIBILITY_DATA_SENSITIVE_AUTO,
3329             ACCESSIBILITY_DATA_SENSITIVE_YES,
3330             ACCESSIBILITY_DATA_SENSITIVE_NO,
3331     })
3332     @Retention(RetentionPolicy.SOURCE)
3333     public @interface AccessibilityDataSensitive {}
3334 
3335     /**
3336      * Mask for obtaining the bits which specify how to determine
3337      * whether a view is important for accessibility.
3338      */
3339     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
3340         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
3341         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
3342         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3343 
3344     /**
3345      * Shift for the bits in {@link #mPrivateFlags2} related to the
3346      * "accessibilityLiveRegion" attribute.
3347      */
3348     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3349 
3350     /**
3351      * Live region mode specifying that accessibility services should not
3352      * automatically announce changes to this view. This is the default live
3353      * region mode for most views.
3354      * <p>
3355      * Use with {@link #setAccessibilityLiveRegion(int)}.
3356      */
3357     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3358 
3359     /**
3360      * Live region mode specifying that accessibility services should notify users of changes to
3361      * this view.
3362      * <p>
3363      * Use with {@link #setAccessibilityLiveRegion(int)}.
3364      */
3365     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3366 
3367     /**
3368      * Live region mode specifying that accessibility services should immediately notify users of
3369      * changes to this view. For example, a screen reader may interrupt ongoing speech to
3370      * immediately announce these changes.
3371      * <p>
3372      * Use with {@link #setAccessibilityLiveRegion(int)}.
3373      */
3374     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3375 
3376     /**
3377      * The default whether the view is important for accessibility.
3378      */
3379     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3380 
3381     /**
3382      * Mask for obtaining the bits which specify a view's accessibility live
3383      * region mode.
3384      */
3385     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3386             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3387             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3388 
3389     /**
3390      * Flag indicating whether a view has accessibility focus.
3391      */
3392     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3393 
3394     /**
3395      * Flag whether the accessibility state of the subtree rooted at this view changed.
3396      */
3397     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3398 
3399     /**
3400      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3401      * is used to check whether later changes to the view's transform should invalidate the
3402      * view to force the quickReject test to run again.
3403      */
3404     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3405 
3406     /**
3407      * Flag indicating that start/end padding has been resolved into left/right padding
3408      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3409      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3410      * during measurement. In some special cases this is required such as when an adapter-based
3411      * view measures prospective children without attaching them to a window.
3412      */
3413     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3414 
3415     /**
3416      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3417      */
3418     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3419 
3420     /**
3421      * Indicates that the view is tracking some sort of transient state
3422      * that the app should not need to be aware of, but that the framework
3423      * should take special care to preserve.
3424      */
3425     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3426 
3427     /**
3428      * Group of bits indicating that RTL properties resolution is done.
3429      */
3430     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3431             PFLAG2_TEXT_DIRECTION_RESOLVED |
3432             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3433             PFLAG2_PADDING_RESOLVED |
3434             PFLAG2_DRAWABLE_RESOLVED;
3435 
3436     // There are a couple of flags left in mPrivateFlags2
3437 
3438     /* End of masks for mPrivateFlags2 */
3439 
3440     /*
3441      * Masks for mPrivateFlags3, as generated by dumpFlags():
3442      *
3443      * |-------|-------|-------|-------|
3444      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3445      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3446      *                               1   PFLAG3_IS_LAID_OUT
3447      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3448      *                             1     PFLAG3_CALLED_SUPER
3449      *                            1      PFLAG3_APPLYING_INSETS
3450      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3451      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3452      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3453      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3454      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3455      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3456      *                     1             PFLAG3_SCROLL_INDICATOR_START
3457      *                    1              PFLAG3_SCROLL_INDICATOR_END
3458      *                   1               PFLAG3_ASSIST_BLOCKED
3459      *                  1                PFLAG3_CLUSTER
3460      *                 1                 PFLAG3_IS_AUTOFILLED
3461      *                1                  PFLAG3_FINGER_DOWN
3462      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3463      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3464      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3465      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3466      *        1                          PFLAG3_TEMPORARY_DETACH
3467      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3468      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3469      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3470      *    1                              PFLAG3_AGGREGATED_VISIBLE
3471      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3472      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3473      * |-------|-------|-------|-------|
3474      */
3475 
3476     /**
3477      * Flag indicating that view has a transform animation set on it. This is used to track whether
3478      * an animation is cleared between successive frames, in order to tell the associated
3479      * DisplayList to clear its animation matrix.
3480      */
3481     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3482 
3483     /**
3484      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3485      * animation is cleared between successive frames, in order to tell the associated
3486      * DisplayList to restore its alpha value.
3487      */
3488     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3489 
3490     /**
3491      * Flag indicating that the view has been through at least one layout since it
3492      * was last attached to a window.
3493      */
3494     static final int PFLAG3_IS_LAID_OUT = 0x4;
3495 
3496     /**
3497      * Flag indicating that a call to measure() was skipped and should be done
3498      * instead when layout() is invoked.
3499      */
3500     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3501 
3502     /**
3503      * Flag indicating that an overridden method correctly called down to
3504      * the superclass implementation as required by the API spec.
3505      */
3506     static final int PFLAG3_CALLED_SUPER = 0x10;
3507 
3508     /**
3509      * Flag indicating that we're in the process of applying window insets.
3510      */
3511     static final int PFLAG3_APPLYING_INSETS = 0x20;
3512 
3513     /**
3514      * Flag indicating that we're in the process of fitting system windows using the old method.
3515      */
3516     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3517 
3518     /**
3519      * Flag indicating that nested scrolling is enabled for this view.
3520      * The view will optionally cooperate with views up its parent chain to allow for
3521      * integrated nested scrolling along the same axis.
3522      */
3523     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3524 
3525     /**
3526      * Flag indicating that the bottom scroll indicator should be displayed
3527      * when this view can scroll up.
3528      */
3529     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3530 
3531     /**
3532      * Flag indicating that the bottom scroll indicator should be displayed
3533      * when this view can scroll down.
3534      */
3535     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3536 
3537     /**
3538      * Flag indicating that the left scroll indicator should be displayed
3539      * when this view can scroll left.
3540      */
3541     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3542 
3543     /**
3544      * Flag indicating that the right scroll indicator should be displayed
3545      * when this view can scroll right.
3546      */
3547     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3548 
3549     /**
3550      * Flag indicating that the start scroll indicator should be displayed
3551      * when this view can scroll in the start direction.
3552      */
3553     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3554 
3555     /**
3556      * Flag indicating that the end scroll indicator should be displayed
3557      * when this view can scroll in the end direction.
3558      */
3559     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3560 
3561     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3562 
3563     static final int SCROLL_INDICATORS_NONE = 0x0000;
3564 
3565     /**
3566      * Mask for use with setFlags indicating bits used for indicating which
3567      * scroll indicators are enabled.
3568      */
3569     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3570             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3571             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3572             | PFLAG3_SCROLL_INDICATOR_END;
3573 
3574     /**
3575      * Left-shift required to translate between public scroll indicator flags
3576      * and internal PFLAGS3 flags. When used as a right-shift, translates
3577      * PFLAGS3 flags to public flags.
3578      */
3579     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3580 
3581     /** @hide */
3582     @Retention(RetentionPolicy.SOURCE)
3583     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3584             SCROLL_INDICATOR_TOP,
3585             SCROLL_INDICATOR_BOTTOM,
3586             SCROLL_INDICATOR_LEFT,
3587             SCROLL_INDICATOR_RIGHT,
3588             SCROLL_INDICATOR_START,
3589             SCROLL_INDICATOR_END,
3590     })
3591     public @interface ScrollIndicators {}
3592 
3593     /**
3594      * Scroll indicator direction for the top edge of the view.
3595      *
3596      * @see #setScrollIndicators(int)
3597      * @see #setScrollIndicators(int, int)
3598      * @see #getScrollIndicators()
3599      */
3600     public static final int SCROLL_INDICATOR_TOP =
3601             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3602 
3603     /**
3604      * Scroll indicator direction for the bottom edge of the view.
3605      *
3606      * @see #setScrollIndicators(int)
3607      * @see #setScrollIndicators(int, int)
3608      * @see #getScrollIndicators()
3609      */
3610     public static final int SCROLL_INDICATOR_BOTTOM =
3611             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3612 
3613     /**
3614      * Scroll indicator direction for the left edge of the view.
3615      *
3616      * @see #setScrollIndicators(int)
3617      * @see #setScrollIndicators(int, int)
3618      * @see #getScrollIndicators()
3619      */
3620     public static final int SCROLL_INDICATOR_LEFT =
3621             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3622 
3623     /**
3624      * Scroll indicator direction for the right edge of the view.
3625      *
3626      * @see #setScrollIndicators(int)
3627      * @see #setScrollIndicators(int, int)
3628      * @see #getScrollIndicators()
3629      */
3630     public static final int SCROLL_INDICATOR_RIGHT =
3631             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3632 
3633     /**
3634      * Scroll indicator direction for the starting edge of the view.
3635      * <p>
3636      * Resolved according to the view's layout direction, see
3637      * {@link #getLayoutDirection()} for more information.
3638      *
3639      * @see #setScrollIndicators(int)
3640      * @see #setScrollIndicators(int, int)
3641      * @see #getScrollIndicators()
3642      */
3643     public static final int SCROLL_INDICATOR_START =
3644             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3645 
3646     /**
3647      * Scroll indicator direction for the ending edge of the view.
3648      * <p>
3649      * Resolved according to the view's layout direction, see
3650      * {@link #getLayoutDirection()} for more information.
3651      *
3652      * @see #setScrollIndicators(int)
3653      * @see #setScrollIndicators(int, int)
3654      * @see #getScrollIndicators()
3655      */
3656     public static final int SCROLL_INDICATOR_END =
3657             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3658 
3659     /**
3660      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3661      * into this view.<p>
3662      */
3663     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3664 
3665     /**
3666      * Flag indicating that the view is a root of a keyboard navigation cluster.
3667      *
3668      * @see #isKeyboardNavigationCluster()
3669      * @see #setKeyboardNavigationCluster(boolean)
3670      */
3671     private static final int PFLAG3_CLUSTER = 0x8000;
3672 
3673     /**
3674      * Flag indicating that the view is autofilled
3675      *
3676      * @see #isAutofilled()
3677      * @see #setAutofilled(boolean, boolean)
3678      */
3679     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3680 
3681     /**
3682      * Indicates that the user is currently touching the screen.
3683      * Currently used for the tooltip positioning only.
3684      */
3685     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3686 
3687     /**
3688      * Flag indicating that this view is the default-focus view.
3689      *
3690      * @see #isFocusedByDefault()
3691      * @see #setFocusedByDefault(boolean)
3692      */
3693     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3694 
3695     /**
3696      * Shift for the bits in {@link #mPrivateFlags3} related to the
3697      * "importantForAutofill" attribute.
3698      */
3699     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3700 
3701     /**
3702      * Mask for obtaining the bits which specify how to determine
3703      * whether a view is important for autofill.
3704      */
3705     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3706             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3707             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3708             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3709             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3710 
3711     /**
3712      * Whether this view has rendered elements that overlap (see {@link
3713      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3714      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3715      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3716      * determined by whatever {@link #hasOverlappingRendering()} returns.
3717      */
3718     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3719 
3720     /**
3721      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3722      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3723      */
3724     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3725 
3726     /**
3727      * Flag indicating that the view is temporarily detached from the parent view.
3728      *
3729      * @see #onStartTemporaryDetach()
3730      * @see #onFinishTemporaryDetach()
3731      */
3732     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3733 
3734     /**
3735      * Flag indicating that the view does not wish to be revealed within its parent
3736      * hierarchy when it gains focus. Expressed in the negative since the historical
3737      * default behavior is to reveal on focus; this flag suppresses that behavior.
3738      *
3739      * @see #setRevealOnFocusHint(boolean)
3740      * @see #getRevealOnFocusHint()
3741      */
3742     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3743 
3744     /**
3745      * Flag indicating that when layout is completed we should notify
3746      * that the view was entered for autofill purposes. To minimize
3747      * showing autofill for views not visible to the user we evaluate
3748      * user visibility which cannot be done until the view is laid out.
3749      */
3750     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3751 
3752     /**
3753      * Works like focusable for screen readers, but without the side effects on input focus.
3754      * @see #setScreenReaderFocusable(boolean)
3755      */
3756     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3757 
3758     /**
3759      * The last aggregated visibility. Used to detect when it truly changes.
3760      */
3761     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3762 
3763     /**
3764      * Used to indicate that {@link #mAutofillId} was explicitly set through
3765      * {@link #setAutofillId(AutofillId)}.
3766      */
3767     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3768 
3769     /**
3770      * Indicates if the View is a heading for accessibility purposes
3771      */
3772     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3773 
3774     /* End of masks for mPrivateFlags3 */
3775 
3776     /*
3777      * Masks for mPrivateFlags4, as generated by dumpFlags():
3778      *
3779      * |-------|-------|-------|-------|
3780      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3781      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3782      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3783      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3784      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3785      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3786      *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
3787      *                       1          PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
3788      *                     11           PFLAG4_SCROLL_CAPTURE_HINT_MASK
3789      *                    1             PFLAG4_ALLOW_CLICK_WHEN_DISABLED
3790      *                   1              PFLAG4_DETACHED
3791      *                  1               PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
3792      *                 1                PFLAG4_DRAG_A11Y_STARTED
3793      *                1                 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
3794      *               1                  PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER
3795      *              1                   PFLAG4_TRAVERSAL_TRACING_ENABLED
3796      *             1                    PFLAG4_RELAYOUT_TRACING_ENABLED
3797      *            1                     PFLAG4_ROTARY_HAPTICS_DETERMINED
3798      *           1                      PFLAG4_ROTARY_HAPTICS_ENABLED
3799      *          1                       PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT
3800      *         1                        PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT
3801      *       11                         PFLAG4_CONTENT_SENSITIVITY_MASK
3802      *      1                           PFLAG4_IS_COUNTED_AS_SENSITIVE
3803      *     1                            PFLAG4_HAS_DRAWN
3804      *    1                             PFLAG4_HAS_MOVED
3805      *   1                              PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION
3806      * |-------|-------|-------|-------|
3807      */
3808 
3809     /**
3810      * Mask for obtaining the bits which specify how to determine
3811      * whether a view is important for autofill.
3812      *
3813      * <p>NOTE: the important for content capture values were the first flags added and are set in
3814      * the rightmost position, so we don't need to shift them
3815      */
3816     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3817             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3818             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3819             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3820             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3821 
3822     /*
3823      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3824      * should be called.
3825      *
3826      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3827      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3828      */
3829     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3830     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3831 
3832     /*
3833      * Flags used to cache the value returned by isImportantForContentCapture while the view
3834      * hierarchy is being traversed.
3835      */
3836     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3837     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3838 
3839     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3840             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3841             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3842 
3843     /**
3844      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3845      */
3846     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3847 
3848     /**
3849      * Flag indicating the field should not have yellow highlight when autofilled.
3850      */
3851     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3852 
3853     /**
3854      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3855      */
3856     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3857 
3858     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3859             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3860             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3861 
3862     /**
3863      * Indicates if the view can receive click events when disabled.
3864      */
3865     private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
3866 
3867     /**
3868      * Indicates if the view is just detached.
3869      */
3870     private static final int PFLAG4_DETACHED = 0x000002000;
3871 
3872     /**
3873      * Indicates that the view has transient state because the system is translating it.
3874      */
3875     private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
3876 
3877     /**
3878      * Indicates that the view has started a drag with {@link AccessibilityAction#ACTION_DRAG_START}
3879      */
3880     private static final int PFLAG4_DRAG_A11Y_STARTED = 0x000008000;
3881 
3882     /**
3883      * Indicates that the view enables auto handwriting initiation.
3884      */
3885     private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
3886 
3887     /**
3888      * Indicates that the view is important for Credential Manager.
3889      */
3890     private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000;
3891 
3892     /**
3893      * When set, measure and layout passes of this view will be logged with {@link Trace}, so we
3894      * can better debug jank due to complex view hierarchies.
3895      */
3896     private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
3897 
3898     /**
3899      * When set, emits a {@link Trace} instant event and stacktrace every time a requestLayout of
3900      * this class happens.
3901      */
3902     private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
3903 
3904     /** Indicates if rotary scroll haptics support for the view has been determined. */
3905     private static final int PFLAG4_ROTARY_HAPTICS_DETERMINED = 0x100000;
3906 
3907     /**
3908      * Indicates if rotary scroll haptics is enabled for this view.
3909      * The source of truth for this info is a ViewConfiguration API; this bit only caches the value.
3910      */
3911     private static final int PFLAG4_ROTARY_HAPTICS_ENABLED = 0x200000;
3912 
3913     /** Indicates if there has been a scroll event since the last rotary input. */
3914     private static final int PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT = 0x400000;
3915 
3916     /**
3917      * Indicates if there has been a rotary input that may generate a scroll event.
3918      * This flag is important so that a scroll event can be properly attributed to a rotary input.
3919      */
3920     private static final int PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT = 0x800000;
3921 
3922     private static final int PFLAG4_CONTENT_SENSITIVITY_SHIFT = 24;
3923 
3924     /**
3925      * Mask for obtaining the bits which specify how to determine whether a view
3926      * displays sensitive content or not.
3927      */
3928     private static final int PFLAG4_CONTENT_SENSITIVITY_MASK =
3929             (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE
3930                     | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT;
3931 
3932     /**
3933      * Whether this view has been counted as a sensitive view or not.
3934      *
3935      * @see AttachInfo#mSensitiveViewsCount
3936      */
3937     private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000;
3938 
3939     /**
3940      * Whether this view has been drawn once with updateDisplayListIfDirty() or not.
3941      * Used by VRR to for quick detection of scrolling.
3942      */
3943     private static final int PFLAG4_HAS_DRAWN = 0x8000000;
3944 
3945     /**
3946      * Whether this view has been moved with either setTranslationX/Y or setLeft/Top.
3947      * Used by VRR to for quick detection of scrolling.
3948      */
3949     private static final int PFLAG4_HAS_MOVED = 0x10000000;
3950 
3951     /**
3952      * Whether the invalidateViewProperty is involked at current frame.
3953      */
3954     private static final int PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION = 0x20000000;
3955 
3956     /* End of masks for mPrivateFlags4 */
3957 
3958     /** @hide */
3959     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3960     /** @hide */
3961     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3962     /** @hide */
3963     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3964 
3965     /** @hide */
3966     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3967             VIEW_STRUCTURE_FOR_ASSIST,
3968             VIEW_STRUCTURE_FOR_AUTOFILL,
3969             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3970     })
3971     @Retention(RetentionPolicy.SOURCE)
3972     public @interface ViewStructureType {}
3973 
3974     /**
3975      * Always allow a user to over-scroll this view, provided it is a
3976      * view that can scroll.
3977      *
3978      * @see #getOverScrollMode()
3979      * @see #setOverScrollMode(int)
3980      */
3981     public static final int OVER_SCROLL_ALWAYS = 0;
3982 
3983     /**
3984      * Allow a user to over-scroll this view only if the content is large
3985      * enough to meaningfully scroll, provided it is a view that can scroll.
3986      *
3987      * @see #getOverScrollMode()
3988      * @see #setOverScrollMode(int)
3989      */
3990     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3991 
3992     /**
3993      * Never allow a user to over-scroll this view.
3994      *
3995      * @see #getOverScrollMode()
3996      * @see #setOverScrollMode(int)
3997      */
3998     public static final int OVER_SCROLL_NEVER = 2;
3999 
4000     /**
4001      * Special constant for {@link #setSystemUiVisibility(int)}: View has
4002      * requested the system UI (status bar) to be visible (the default).
4003      *
4004      * @see #setSystemUiVisibility(int)
4005      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
4006      * instead.
4007      */
4008     @Deprecated
4009     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
4010 
4011     /**
4012      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
4013      * system UI to enter an unobtrusive "low profile" mode.
4014      *
4015      * <p>This is for use in games, book readers, video players, or any other
4016      * "immersive" application where the usual system chrome is deemed too distracting.
4017      *
4018      * <p>In low profile mode, the status bar and/or navigation icons may dim.
4019      *
4020      * @see #setSystemUiVisibility(int)
4021      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
4022      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
4023      * {@link Type#systemBars()}.
4024      */
4025     @Deprecated
4026     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
4027 
4028     /**
4029      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
4030      * system navigation be temporarily hidden.
4031      *
4032      * <p>This is an even less obtrusive state than that called for by
4033      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
4034      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
4035      * those to disappear. This is useful (in conjunction with the
4036      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
4037      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
4038      * window flags) for displaying content using every last pixel on the display.
4039      *
4040      * <p>There is a limitation: because navigation controls are so important, the least user
4041      * interaction will cause them to reappear immediately.  When this happens, both
4042      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
4043      * so that both elements reappear at the same time.
4044      *
4045      * @see #setSystemUiVisibility(int)
4046      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
4047      * instead.
4048      */
4049     @Deprecated
4050     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
4051 
4052     /**
4053      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
4054      * into the normal fullscreen mode so that its content can take over the screen
4055      * while still allowing the user to interact with the application.
4056      *
4057      * <p>This has the same visual effect as
4058      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
4059      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
4060      * meaning that non-critical screen decorations (such as the status bar) will be
4061      * hidden while the user is in the View's window, focusing the experience on
4062      * that content.  Unlike the window flag, if you are using ActionBar in
4063      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
4064      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
4065      * hide the action bar.
4066      *
4067      * <p>This approach to going fullscreen is best used over the window flag when
4068      * it is a transient state -- that is, the application does this at certain
4069      * points in its user interaction where it wants to allow the user to focus
4070      * on content, but not as a continuous state.  For situations where the application
4071      * would like to simply stay full screen the entire time (such as a game that
4072      * wants to take over the screen), the
4073      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
4074      * is usually a better approach.  The state set here will be removed by the system
4075      * in various situations (such as the user moving to another application) like
4076      * the other system UI states.
4077      *
4078      * <p>When using this flag, the application should provide some easy facility
4079      * for the user to go out of it.  A common example would be in an e-book
4080      * reader, where tapping on the screen brings back whatever screen and UI
4081      * decorations that had been hidden while the user was immersed in reading
4082      * the book.
4083      *
4084      * @see #setSystemUiVisibility(int)
4085      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
4086      * instead.
4087      */
4088     @Deprecated
4089     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
4090 
4091     /**
4092      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
4093      * flags, we would like a stable view of the content insets given to
4094      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
4095      * will always represent the worst case that the application can expect
4096      * as a continuous state.  In the stock Android UI this is the space for
4097      * the system bar, nav bar, and status bar, but not more transient elements
4098      * such as an input method.
4099      *
4100      * The stable layout your UI sees is based on the system UI modes you can
4101      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
4102      * then you will get a stable layout for changes of the
4103      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
4104      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
4105      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
4106      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
4107      * with a stable layout.  (Note that you should avoid using
4108      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
4109      *
4110      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
4111      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
4112      * then a hidden status bar will be considered a "stable" state for purposes
4113      * here.  This allows your UI to continually hide the status bar, while still
4114      * using the system UI flags to hide the action bar while still retaining
4115      * a stable layout.  Note that changing the window fullscreen flag will never
4116      * provide a stable layout for a clean transition.
4117      *
4118      * <p>If you are using ActionBar in
4119      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
4120      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
4121      * insets it adds to those given to the application.
4122      *
4123      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
4124      * insets that don't change when system bars change visibility state.
4125      */
4126     @Deprecated
4127     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
4128 
4129     /**
4130      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
4131      * to be laid out as if it has requested
4132      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
4133      * allows it to avoid artifacts when switching in and out of that mode, at
4134      * the expense that some of its user interface may be covered by screen
4135      * decorations when they are shown.  You can perform layout of your inner
4136      * UI elements to account for the navigation system UI through the
4137      * {@link #fitSystemWindows(Rect)} method.
4138      *
4139      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
4140      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
4141      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
4142      */
4143     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
4144 
4145     /**
4146      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
4147      * to be laid out as if it has requested
4148      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
4149      * allows it to avoid artifacts when switching in and out of that mode, at
4150      * the expense that some of its user interface may be covered by screen
4151      * decorations when they are shown.  You can perform layout of your inner
4152      * UI elements to account for non-fullscreen system UI through the
4153      * {@link #fitSystemWindows(Rect)} method.
4154      *
4155      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
4156      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
4157      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
4158      *  layoutInDisplayCutoutMode} is
4159      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
4160      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
4161      *
4162      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
4163      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
4164      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
4165      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
4166      *
4167      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
4168      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
4169      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
4170      */
4171     @Deprecated
4172     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
4173 
4174     /**
4175      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
4176      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
4177      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
4178      * user interaction.
4179      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
4180      * has an effect when used in combination with that flag.</p>
4181      *
4182      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_DEFAULT} instead.
4183      */
4184     @Deprecated
4185     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
4186 
4187     /**
4188      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
4189      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
4190      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
4191      * experience while also hiding the system bars.  If this flag is not set,
4192      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
4193      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
4194      * if the user swipes from the top of the screen.
4195      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
4196      * system gestures, such as swiping from the top of the screen.  These transient system bars
4197      * will overlay app's content, may have some degree of transparency, and will automatically
4198      * hide after a short timeout.
4199      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
4200      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
4201      * with one or both of those flags.</p>
4202      *
4203      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
4204      */
4205     @Deprecated
4206     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
4207 
4208     /**
4209      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
4210      * is compatible with light status bar backgrounds.
4211      *
4212      * <p>For this to take effect, the window must request
4213      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
4214      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
4215      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
4216      *         FLAG_TRANSLUCENT_STATUS}.
4217      *
4218      * @see android.R.attr#windowLightStatusBar
4219      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
4220      */
4221     @Deprecated
4222     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
4223 
4224     /**
4225      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
4226      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
4227      */
4228     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
4229 
4230     /**
4231      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
4232      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
4233      */
4234     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
4235 
4236     /**
4237      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
4238      * that is compatible with light navigation bar backgrounds.
4239      *
4240      * <p>For this to take effect, the window must request
4241      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
4242      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
4243      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
4244      *         FLAG_TRANSLUCENT_NAVIGATION}.
4245      *
4246      * @see android.R.attr#windowLightNavigationBar
4247      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
4248      */
4249     @Deprecated
4250     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
4251 
4252     /**
4253      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
4254      */
4255     @Deprecated
4256     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
4257 
4258     /**
4259      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
4260      */
4261     @Deprecated
4262     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
4263 
4264     /**
4265      * @hide
4266      *
4267      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4268      * out of the public fields to keep the undefined bits out of the developer's way.
4269      *
4270      * Flag to make the status bar not expandable.  Unless you also
4271      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
4272      */
4273     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4274     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
4275 
4276     /**
4277      * @hide
4278      *
4279      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4280      * out of the public fields to keep the undefined bits out of the developer's way.
4281      *
4282      * Flag to hide notification icons and scrolling ticker text.
4283      */
4284     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
4285 
4286     /**
4287      * @hide
4288      *
4289      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4290      * out of the public fields to keep the undefined bits out of the developer's way.
4291      *
4292      * Flag to disable incoming notification alerts.  This will not block
4293      * icons, but it will block sound, vibrating and other visual or aural notifications.
4294      */
4295     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
4296 
4297     /**
4298      * @hide
4299      *
4300      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4301      * out of the public fields to keep the undefined bits out of the developer's way.
4302      *
4303      * Flag to hide only the scrolling ticker.  Note that
4304      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
4305      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
4306      */
4307     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
4308 
4309     /**
4310      * @hide
4311      *
4312      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4313      * out of the public fields to keep the undefined bits out of the developer's way.
4314      *
4315      * Flag to hide the center system info area.
4316      */
4317     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
4318 
4319     /**
4320      * @hide
4321      *
4322      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4323      * out of the public fields to keep the undefined bits out of the developer's way.
4324      *
4325      * Flag to hide only the home button.  Don't use this
4326      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4327      */
4328     @UnsupportedAppUsage
4329     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
4330 
4331     /**
4332      * @hide
4333      *
4334      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4335      * out of the public fields to keep the undefined bits out of the developer's way.
4336      *
4337      * Flag to hide only the back button. Don't use this
4338      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4339      */
4340     @UnsupportedAppUsage
4341     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
4342 
4343     /**
4344      * @hide
4345      *
4346      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4347      * out of the public fields to keep the undefined bits out of the developer's way.
4348      *
4349      * Flag to hide only the clock.  You might use this if your activity has
4350      * its own clock making the status bar's clock redundant.
4351      */
4352     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
4353 
4354     /**
4355      * @hide
4356      *
4357      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4358      * out of the public fields to keep the undefined bits out of the developer's way.
4359      *
4360      * Flag to hide only the recent apps button. Don't use this
4361      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4362      */
4363     @UnsupportedAppUsage
4364     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
4365 
4366     /**
4367      * @hide
4368      *
4369      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4370      * out of the public fields to keep the undefined bits out of the developer's way.
4371      *
4372      * Flag to disable the global search gesture. Don't use this
4373      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4374      */
4375     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
4376 
4377     /**
4378      * @hide
4379      *
4380      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4381      * out of the public fields to keep the undefined bits out of the developer's way.
4382      *
4383      * Flag to disable the ongoing call chip.
4384      */
4385     public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
4386 
4387     /**
4388      * @hide
4389      */
4390     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4391 
4392     /**
4393      * These are the system UI flags that can be cleared by events outside
4394      * of an application.  Currently this is just the ability to tap on the
4395      * screen while hiding the navigation bar to have it return.
4396      * @hide
4397      */
4398     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4399             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4400             | SYSTEM_UI_FLAG_FULLSCREEN;
4401 
4402     /**
4403      * Flags that can impact the layout in relation to system UI.
4404      *
4405      * @deprecated System UI layout flags are deprecated.
4406      */
4407     @Deprecated
4408     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4409             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4410             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4411 
4412     /** @hide */
4413     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4414             FIND_VIEWS_WITH_TEXT,
4415             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4416     })
4417     @Retention(RetentionPolicy.SOURCE)
4418     public @interface FindViewFlags {}
4419 
4420     /**
4421      * Find views that render the specified text.
4422      *
4423      * @see #findViewsWithText(ArrayList, CharSequence, int)
4424      */
4425     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4426 
4427     /**
4428      * Find find views that contain the specified content description.
4429      *
4430      * @see #findViewsWithText(ArrayList, CharSequence, int)
4431      */
4432     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4433 
4434     /**
4435      * Find views that contain {@link AccessibilityNodeProvider}. Such
4436      * a View is a root of virtual view hierarchy and may contain the searched
4437      * text. If this flag is set Views with providers are automatically
4438      * added and it is a responsibility of the client to call the APIs of
4439      * the provider to determine whether the virtual tree rooted at this View
4440      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4441      * representing the virtual views with this text.
4442      *
4443      * @see #findViewsWithText(ArrayList, CharSequence, int)
4444      *
4445      * @hide
4446      */
4447     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4448 
4449     /**
4450      * The undefined cursor position.
4451      *
4452      * @hide
4453      */
4454     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4455 
4456     /**
4457      * Indicates that the screen has changed state and is now off.
4458      *
4459      * @see #onScreenStateChanged(int)
4460      */
4461     public static final int SCREEN_STATE_OFF = 0x0;
4462 
4463     /**
4464      * Indicates that the screen has changed state and is now on.
4465      *
4466      * @see #onScreenStateChanged(int)
4467      */
4468     public static final int SCREEN_STATE_ON = 0x1;
4469 
4470     /**
4471      * Indicates no axis of view scrolling.
4472      */
4473     public static final int SCROLL_AXIS_NONE = 0;
4474 
4475     /**
4476      * Indicates scrolling along the horizontal axis.
4477      */
4478     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4479 
4480     /**
4481      * Indicates scrolling along the vertical axis.
4482      */
4483     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4484 
4485     /**
4486      * Controls the over-scroll mode for this view.
4487      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4488      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4489      * and {@link #OVER_SCROLL_NEVER}.
4490      */
4491     private int mOverScrollMode;
4492 
4493     /**
4494      * The parent this view is attached to.
4495      * {@hide}
4496      *
4497      * @see #getParent()
4498      */
4499     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4500     protected ViewParent mParent;
4501 
4502     /**
4503      * {@hide}
4504      *
4505      * Not available for general use. If you need help, hang up and then dial one of the following
4506      * public APIs:
4507      *
4508      * @see #isAttachedToWindow() for current attach state
4509      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4510      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4511      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4512      * @see #getHandler() for posting messages to this view's UI thread/looper
4513      * @see #getParent() for interacting with the parent chain
4514      * @see #getWindowToken() for the current window token
4515      * @see #getRootView() for the view at the root of the attached hierarchy
4516      * @see #getDisplay() for the Display this view is presented on
4517      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4518      * @see #hasWindowFocus() for whether the attached window is currently focused
4519      * @see #getWindowVisibility() for checking the visibility of the attached window
4520      */
4521     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4522     AttachInfo mAttachInfo;
4523 
4524     /**
4525      * {@hide}
4526      */
4527     @ViewDebug.ExportedProperty(flagMapping = {
4528         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4529                 name = "FORCE_LAYOUT"),
4530         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4531                 name = "LAYOUT_REQUIRED"),
4532         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4533             name = "DRAWING_CACHE_INVALID", outputIf = false),
4534         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4535         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4536         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4537     }, formatToHexString = true)
4538 
4539     /* @hide */
4540     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4541     public int mPrivateFlags;
4542     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4543     int mPrivateFlags2;
4544     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4545     int mPrivateFlags3;
4546 
4547     private int mPrivateFlags4;
4548 
4549     /**
4550      * This view's request for the visibility of the status bar.
4551      * @hide
4552      */
4553     @ViewDebug.ExportedProperty(flagMapping = {
4554             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4555                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4556                     name = "LOW_PROFILE"),
4557             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4558                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4559                     name = "HIDE_NAVIGATION"),
4560             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4561                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4562                     name = "FULLSCREEN"),
4563             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4564                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4565                     name = "LAYOUT_STABLE"),
4566             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4567                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4568                     name = "LAYOUT_HIDE_NAVIGATION"),
4569             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4570                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4571                     name = "LAYOUT_FULLSCREEN"),
4572             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4573                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4574                     name = "IMMERSIVE"),
4575             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4576                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4577                     name = "IMMERSIVE_STICKY"),
4578             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4579                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4580                     name = "LIGHT_STATUS_BAR"),
4581             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4582                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4583                     name = "LIGHT_NAVIGATION_BAR"),
4584             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4585                     equals = STATUS_BAR_DISABLE_EXPAND,
4586                     name = "STATUS_BAR_DISABLE_EXPAND"),
4587             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4588                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4589                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4590             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4591                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4592                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4593             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4594                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4595                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4596             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4597                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4598                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4599             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4600                     equals = STATUS_BAR_DISABLE_HOME,
4601                     name = "STATUS_BAR_DISABLE_HOME"),
4602             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4603                     equals = STATUS_BAR_DISABLE_BACK,
4604                     name = "STATUS_BAR_DISABLE_BACK"),
4605             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4606                     equals = STATUS_BAR_DISABLE_CLOCK,
4607                     name = "STATUS_BAR_DISABLE_CLOCK"),
4608             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4609                     equals = STATUS_BAR_DISABLE_RECENT,
4610                     name = "STATUS_BAR_DISABLE_RECENT"),
4611             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4612                     equals = STATUS_BAR_DISABLE_SEARCH,
4613                     name = "STATUS_BAR_DISABLE_SEARCH"),
4614             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4615                     equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4616                     name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
4617     }, formatToHexString = true)
4618     @SystemUiVisibility
4619     int mSystemUiVisibility;
4620 
4621     /**
4622      * @hide
4623      */
4624     @IntDef(flag = true, prefix = "", value = {
4625             SYSTEM_UI_FLAG_LOW_PROFILE,
4626             SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4627             SYSTEM_UI_FLAG_FULLSCREEN,
4628             SYSTEM_UI_FLAG_LAYOUT_STABLE,
4629             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4630             SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4631             SYSTEM_UI_FLAG_IMMERSIVE,
4632             SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4633             SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4634             SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4635             STATUS_BAR_DISABLE_EXPAND,
4636             STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4637             STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4638             STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4639             STATUS_BAR_DISABLE_SYSTEM_INFO,
4640             STATUS_BAR_DISABLE_HOME,
4641             STATUS_BAR_DISABLE_BACK,
4642             STATUS_BAR_DISABLE_CLOCK,
4643             STATUS_BAR_DISABLE_RECENT,
4644             STATUS_BAR_DISABLE_SEARCH,
4645             STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4646     })
4647     @Retention(RetentionPolicy.SOURCE)
4648     public @interface SystemUiVisibility {}
4649 
4650     /**
4651      * Reference count for transient state.
4652      * @see #setHasTransientState(boolean)
4653      */
4654     int mTransientStateCount = 0;
4655 
4656     /**
4657      * Count of how many windows this view has been attached to.
4658      */
4659     int mWindowAttachCount;
4660 
4661     /**
4662      * The layout parameters associated with this view and used by the parent
4663      * {@link android.view.ViewGroup} to determine how this view should be
4664      * laid out.
4665      *
4666      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4667      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4668      * state correctness of the class.
4669      * {@hide}
4670      */
4671     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4672     protected ViewGroup.LayoutParams mLayoutParams;
4673 
4674     /**
4675      * The view flags hold various views states.
4676      *
4677      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4678      * triggering updates.
4679      * {@hide}
4680      */
4681     @ViewDebug.ExportedProperty(formatToHexString = true)
4682     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4683     int mViewFlags;
4684 
4685     static class TransformationInfo {
4686         /**
4687          * The transform matrix for the View. This transform is calculated internally
4688          * based on the translation, rotation, and scale properties.
4689          *
4690          * Do *not* use this variable directly; instead call getMatrix(), which will
4691          * load the value from the View's RenderNode.
4692          */
4693         private final Matrix mMatrix = new Matrix();
4694 
4695         /**
4696          * The inverse transform matrix for the View. This transform is calculated
4697          * internally based on the translation, rotation, and scale properties.
4698          *
4699          * Do *not* use this variable directly; instead call getInverseMatrix(),
4700          * which will load the value from the View's RenderNode.
4701          */
4702         private Matrix mInverseMatrix;
4703 
4704         /**
4705          * The opacity of the View. This is a value from 0 to 1, where 0 means
4706          * completely transparent and 1 means completely opaque.
4707          */
4708         @ViewDebug.ExportedProperty
4709         private float mAlpha = 1f;
4710 
4711         /**
4712          * The opacity of the view as manipulated by the Fade transition. This is a
4713          * property only used by transitions, which is composited with the other alpha
4714          * values to calculate the final visual alpha value.
4715          */
4716         float mTransitionAlpha = 1f;
4717     }
4718 
4719     /** @hide */
4720     @UnsupportedAppUsage
4721     public TransformationInfo mTransformationInfo;
4722 
4723     /**
4724      * Current clip bounds. to which all drawing of this view are constrained.
4725      */
4726     @ViewDebug.ExportedProperty(category = "drawing")
4727     Rect mClipBounds = null;
4728 
4729     private boolean mLastIsOpaque;
4730 
4731     /**
4732      * The distance in pixels from the left edge of this view's parent
4733      * to the left edge of this view.
4734      * {@hide}
4735      */
4736     @ViewDebug.ExportedProperty(category = "layout")
4737     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4738     protected int mLeft;
4739     /**
4740      * The mLeft from the previous frame. Used for detecting movement for purposes of variable
4741      * refresh rate.
4742      */
4743     private int mLastFrameLeft;
4744     /**
4745      * The distance in pixels from the left edge of this view's parent
4746      * to the right edge of this view.
4747      * {@hide}
4748      */
4749     @ViewDebug.ExportedProperty(category = "layout")
4750     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4751     protected int mRight;
4752     /**
4753      * The distance in pixels from the top edge of this view's parent
4754      * to the top edge of this view.
4755      * {@hide}
4756      */
4757     @ViewDebug.ExportedProperty(category = "layout")
4758     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4759     protected int mTop;
4760     /**
4761      * The mTop from the previous frame. Used for detecting movement for purposes of variable
4762      * refresh rate.
4763      */
4764     private int mLastFrameTop;
4765     /**
4766      * The distance in pixels from the top edge of this view's parent
4767      * to the bottom edge of this view.
4768      * {@hide}
4769      */
4770     @ViewDebug.ExportedProperty(category = "layout")
4771     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4772     protected int mBottom;
4773 
4774     /**
4775      * The offset, in pixels, by which the content of this view is scrolled
4776      * horizontally.
4777      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4778      * accessing these directly.
4779      * {@hide}
4780      */
4781     @ViewDebug.ExportedProperty(category = "scrolling")
4782     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4783     protected int mScrollX;
4784     /**
4785      * The offset, in pixels, by which the content of this view is scrolled
4786      * vertically.
4787      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4788      * accessing these directly.
4789      * {@hide}
4790      */
4791     @ViewDebug.ExportedProperty(category = "scrolling")
4792     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4793     protected int mScrollY;
4794 
4795     /**
4796      * The final computed left padding in pixels that is used for drawing. This is the distance in
4797      * pixels between the left edge of this view and the left edge of its content.
4798      * {@hide}
4799      */
4800     @ViewDebug.ExportedProperty(category = "padding")
4801     @UnsupportedAppUsage
4802     protected int mPaddingLeft = 0;
4803     /**
4804      * The final computed right padding in pixels that is used for drawing. This is the distance in
4805      * pixels between the right edge of this view and the right edge of its content.
4806      * {@hide}
4807      */
4808     @ViewDebug.ExportedProperty(category = "padding")
4809     @UnsupportedAppUsage
4810     protected int mPaddingRight = 0;
4811     /**
4812      * The final computed top padding in pixels that is used for drawing. This is the distance in
4813      * pixels between the top edge of this view and the top edge of its content.
4814      * {@hide}
4815      */
4816     @ViewDebug.ExportedProperty(category = "padding")
4817     @UnsupportedAppUsage
4818     protected int mPaddingTop;
4819     /**
4820      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4821      * pixels between the bottom edge of this view and the bottom edge of its content.
4822      * {@hide}
4823      */
4824     @ViewDebug.ExportedProperty(category = "padding")
4825     @UnsupportedAppUsage
4826     protected int mPaddingBottom;
4827 
4828     /**
4829      * The amount of pixel offset applied to the left edge of this view's handwriting bounds.
4830      */
4831     private float mHandwritingBoundsOffsetLeft;
4832 
4833     /**
4834      * The amount of pixel offset applied to the top edge of this view's handwriting bounds.
4835      */
4836     private float mHandwritingBoundsOffsetTop;
4837 
4838     /**
4839      * The amount of pixel offset applied to the right edge of this view's handwriting bounds.
4840      */
4841     private float mHandwritingBoundsOffsetRight;
4842 
4843     /**
4844      * The amount of pixel offset applied to the bottom edge of this view's handwriting bounds.
4845      */
4846     private float mHandwritingBoundsOffsetBottom;
4847 
4848     /**
4849      * The layout insets in pixels, that is the distance in pixels between the
4850      * visible edges of this view its bounds.
4851      */
4852     private Insets mLayoutInsets;
4853 
4854     /**
4855      * Briefly describes the state of the view and is primarily used for accessibility support.
4856      */
4857     private CharSequence mStateDescription;
4858 
4859     /**
4860      * Briefly describes the view and is primarily used for accessibility support.
4861      */
4862     private CharSequence mContentDescription;
4863 
4864     /**
4865      * If this view represents a distinct part of the window, it can have a title that labels the
4866      * area.
4867      */
4868     private CharSequence mAccessibilityPaneTitle;
4869 
4870     /**
4871      * Describes whether this view should only allow interactions from
4872      * {@link android.accessibilityservice.AccessibilityService}s with the
4873      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
4874      * set to true.
4875      */
4876     private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
4877     /** Used to calculate and cache {@link #isAccessibilityDataSensitive()}. */
4878     private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
4879 
4880     /**
4881      * Specifies the id of a view for which this view serves as a label for
4882      * accessibility purposes.
4883      */
4884     private int mLabelForId = View.NO_ID;
4885 
4886     /**
4887      * Predicate for matching labeled view id with its label for
4888      * accessibility purposes.
4889      */
4890     private MatchLabelForPredicate mMatchLabelForPredicate;
4891 
4892     /**
4893      * Specifies a view before which this one is visited in accessibility traversal.
4894      */
4895     private int mAccessibilityTraversalBeforeId = NO_ID;
4896 
4897     /**
4898      * Specifies a view after which this one is visited in accessibility traversal.
4899      */
4900     private int mAccessibilityTraversalAfterId = NO_ID;
4901 
4902     /**
4903      * Predicate for matching a view by its id.
4904      */
4905     private MatchIdPredicate mMatchIdPredicate;
4906 
4907     /**
4908      * The right padding after RTL resolution, but before taking account of scroll bars.
4909      *
4910      * @hide
4911      */
4912     @ViewDebug.ExportedProperty(category = "padding")
4913     protected int mUserPaddingRight;
4914 
4915     /**
4916      * The resolved bottom padding before taking account of scroll bars.
4917      *
4918      * @hide
4919      */
4920     @ViewDebug.ExportedProperty(category = "padding")
4921     protected int mUserPaddingBottom;
4922 
4923     /**
4924      * The left padding after RTL resolution, but before taking account of scroll bars.
4925      *
4926      * @hide
4927      */
4928     @ViewDebug.ExportedProperty(category = "padding")
4929     protected int mUserPaddingLeft;
4930 
4931     /**
4932      * Cache the paddingStart set by the user to append to the scrollbar's size.
4933      *
4934      */
4935     @ViewDebug.ExportedProperty(category = "padding")
4936     int mUserPaddingStart;
4937 
4938     /**
4939      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4940      *
4941      */
4942     @ViewDebug.ExportedProperty(category = "padding")
4943     int mUserPaddingEnd;
4944 
4945     /**
4946      * The left padding as set by a setter method, a background's padding, or via XML property
4947      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4948      *
4949      * @hide
4950      */
4951     int mUserPaddingLeftInitial;
4952 
4953     /**
4954      * The right padding as set by a setter method, a background's padding, or via XML property
4955      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4956      *
4957      * @hide
4958      */
4959     int mUserPaddingRightInitial;
4960 
4961     /**
4962      * Default undefined padding
4963      */
4964     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4965 
4966     /**
4967      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4968      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4969      */
4970     private boolean mLeftPaddingDefined = false;
4971 
4972     /**
4973      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4974      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4975      */
4976     private boolean mRightPaddingDefined = false;
4977 
4978     /**
4979      * @hide
4980      */
4981     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4982     /**
4983      * @hide
4984      */
4985     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4986 
4987     private LongSparseLongArray mMeasureCache;
4988 
4989     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4990     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4991     private Drawable mBackground;
4992     private TintInfo mBackgroundTint;
4993 
4994     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4995     private ForegroundInfo mForegroundInfo;
4996 
4997     private Drawable mScrollIndicatorDrawable;
4998 
4999     /**
5000      * RenderNode used for backgrounds.
5001      * <p>
5002      * When non-null and valid, this is expected to contain an up-to-date copy
5003      * of the background drawable. It is cleared on temporary detach, and reset
5004      * on cleanup.
5005      * @hide
5006      */
5007     RenderNode mBackgroundRenderNode;
5008 
5009     @UnsupportedAppUsage
5010     private int mBackgroundResource;
5011     private boolean mBackgroundSizeChanged;
5012 
5013     /** The default focus highlight.
5014      * @see #mDefaultFocusHighlightEnabled
5015      * @see Drawable#hasFocusStateSpecified()
5016      */
5017     private Drawable mDefaultFocusHighlight;
5018     private Drawable mDefaultFocusHighlightCache;
5019     private boolean mDefaultFocusHighlightSizeChanged;
5020     /**
5021      * True if the default focus highlight is needed on the target device.
5022      */
5023     private static boolean sUseDefaultFocusHighlight;
5024 
5025     /**
5026      * True if zero-sized views can be focused.
5027      */
5028     private static boolean sCanFocusZeroSized;
5029 
5030     /**
5031      * Always assign focus if a focusable View is available.
5032      */
5033     private static boolean sAlwaysAssignFocus;
5034 
5035     private String mTransitionName;
5036 
5037     static class TintInfo {
5038         ColorStateList mTintList;
5039         BlendMode mBlendMode;
5040         boolean mHasTintMode;
5041         boolean mHasTintList;
5042     }
5043 
5044     private static class ForegroundInfo {
5045         private Drawable mDrawable;
5046         private TintInfo mTintInfo;
5047         private int mGravity = Gravity.FILL;
5048         private boolean mInsidePadding = true;
5049         private boolean mBoundsChanged = true;
5050         private final Rect mSelfBounds = new Rect();
5051         private final Rect mOverlayBounds = new Rect();
5052     }
5053 
5054     static class ListenerInfo {
5055 
5056         @UnsupportedAppUsage
ListenerInfo()5057         ListenerInfo() {
5058         }
5059 
5060         /**
5061          * Listener used to dispatch focus change events.
5062          * This field should be made private, so it is hidden from the SDK.
5063          * {@hide}
5064          */
5065         @UnsupportedAppUsage
5066         protected OnFocusChangeListener mOnFocusChangeListener;
5067 
5068         /**
5069          * Listeners for layout change events.
5070          */
5071         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
5072 
5073         protected OnScrollChangeListener mOnScrollChangeListener;
5074 
5075         /**
5076          * Listeners for attach events.
5077          */
5078         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
5079 
5080         /**
5081          * Listener used to dispatch click events.
5082          * This field should be made private, so it is hidden from the SDK.
5083          * {@hide}
5084          */
5085         @UnsupportedAppUsage
5086         public OnClickListener mOnClickListener;
5087 
5088         /**
5089          * Listener used to dispatch long click events.
5090          * This field should be made private, so it is hidden from the SDK.
5091          * {@hide}
5092          */
5093         @UnsupportedAppUsage
5094         protected OnLongClickListener mOnLongClickListener;
5095 
5096         /**
5097          * Listener used to dispatch context click events. This field should be made private, so it
5098          * is hidden from the SDK.
5099          * {@hide}
5100          */
5101         protected OnContextClickListener mOnContextClickListener;
5102 
5103         /**
5104          * Listener used to build the context menu.
5105          * This field should be made private, so it is hidden from the SDK.
5106          * {@hide}
5107          */
5108         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5109         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
5110 
5111         @UnsupportedAppUsage
5112         private OnKeyListener mOnKeyListener;
5113 
5114         @UnsupportedAppUsage
5115         private OnTouchListener mOnTouchListener;
5116 
5117         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5118         private OnHoverListener mOnHoverListener;
5119 
5120         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5121         private OnGenericMotionListener mOnGenericMotionListener;
5122 
5123         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5124         private OnDragListener mOnDragListener;
5125 
5126         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
5127 
5128         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
5129 
5130         OnCapturedPointerListener mOnCapturedPointerListener;
5131 
5132         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
5133 
5134         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
5135 
5136         /**
5137          * This lives here since it's only valid for interactive views. This list is null
5138          * until its first use.
5139          */
5140         private List<Rect> mSystemGestureExclusionRects = null;
5141         private List<Rect> mKeepClearRects = null;
5142         private List<Rect> mUnrestrictedKeepClearRects = null;
5143         private boolean mPreferKeepClear = false;
5144         private Rect mHandwritingArea = null;
5145 
5146         /**
5147          * Used to track {@link #mSystemGestureExclusionRects}, {@link #mKeepClearRects} and
5148          * {@link #mHandwritingArea}.
5149          */
5150         public RenderNode.PositionUpdateListener mPositionUpdateListener;
5151         private Runnable mPositionChangedUpdate;
5152 
5153         /**
5154          * Allows the application to implement custom scroll capture support.
5155          */
5156         ScrollCaptureCallback mScrollCaptureCallback;
5157 
5158         @Nullable
5159         private OnReceiveContentListener mOnReceiveContentListener;
5160     }
5161 
5162     @UnsupportedAppUsage
5163     ListenerInfo mListenerInfo;
5164 
5165     private static class TooltipInfo {
5166         /**
5167          * Text to be displayed in a tooltip popup.
5168          */
5169         @Nullable
5170         CharSequence mTooltipText;
5171 
5172         /**
5173          * View-relative position of the tooltip anchor point.
5174          */
5175         int mAnchorX;
5176         int mAnchorY;
5177 
5178         /**
5179          * The tooltip popup.
5180          */
5181         @Nullable
5182         TooltipPopup mTooltipPopup;
5183 
5184         /**
5185          * Set to true if the tooltip was shown as a result of a long click.
5186          */
5187         boolean mTooltipFromLongClick;
5188 
5189         /**
5190          * Keep these Runnables so that they can be used to reschedule.
5191          */
5192         Runnable mShowTooltipRunnable;
5193         Runnable mHideTooltipRunnable;
5194 
5195         /**
5196          * Hover move is ignored if it is within this distance in pixels from the previous one.
5197          */
5198         int mHoverSlop;
5199 
5200         /**
5201          * Update the anchor position if it significantly (that is by at least mHoverSlop)
5202          * different from the previously stored position. Ignoring insignificant changes
5203          * filters out the jitter which is typical for such input sources as stylus.
5204          *
5205          * @return True if the position has been updated.
5206          */
updateAnchorPos(MotionEvent event)5207         private boolean updateAnchorPos(MotionEvent event) {
5208             final int newAnchorX = (int) event.getX();
5209             final int newAnchorY = (int) event.getY();
5210             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
5211                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
5212                 return false;
5213             }
5214             mAnchorX = newAnchorX;
5215             mAnchorY = newAnchorY;
5216             return true;
5217         }
5218 
5219         /**
5220          *  Clear the anchor position to ensure that the next change is considered significant.
5221          */
clearAnchorPos()5222         private void clearAnchorPos() {
5223             mAnchorX = Integer.MAX_VALUE;
5224             mAnchorY = Integer.MAX_VALUE;
5225         }
5226     }
5227 
5228     TooltipInfo mTooltipInfo;
5229 
5230     // Temporary values used to hold (x,y) coordinates when delegating from the
5231     // two-arg performLongClick() method to the legacy no-arg version.
5232     private float mLongClickX = Float.NaN;
5233     private float mLongClickY = Float.NaN;
5234 
5235     /**
5236      * The application environment this view lives in.
5237      * This field should be made private, so it is hidden from the SDK.
5238      * {@hide}
5239      */
5240     @ViewDebug.ExportedProperty(deepExport = true)
5241     @UnsupportedAppUsage
5242     @UiContext
5243     protected Context mContext;
5244 
5245     @UnsupportedAppUsage
5246     private final Resources mResources;
5247 
5248     @UnsupportedAppUsage
5249     private ScrollabilityCache mScrollCache;
5250 
5251     private int[] mDrawableState = null;
5252 
5253     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
5254 
5255     /**
5256      * Animator that automatically runs based on state changes.
5257      */
5258     private StateListAnimator mStateListAnimator;
5259 
5260     /**
5261      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
5262      * the user may specify which view to go to next.
5263      */
5264     private int mNextFocusLeftId = View.NO_ID;
5265 
5266     /**
5267      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
5268      * the user may specify which view to go to next.
5269      */
5270     private int mNextFocusRightId = View.NO_ID;
5271 
5272     /**
5273      * When this view has focus and the next focus is {@link #FOCUS_UP},
5274      * the user may specify which view to go to next.
5275      */
5276     private int mNextFocusUpId = View.NO_ID;
5277 
5278     /**
5279      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
5280      * the user may specify which view to go to next.
5281      */
5282     private int mNextFocusDownId = View.NO_ID;
5283 
5284     /**
5285      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
5286      * the user may specify which view to go to next.
5287      */
5288     int mNextFocusForwardId = View.NO_ID;
5289 
5290     /**
5291      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
5292      *
5293      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
5294      */
5295     int mNextClusterForwardId = View.NO_ID;
5296 
5297     /**
5298      * Whether this View should use a default focus highlight when it gets focused but doesn't
5299      * have {@link android.R.attr#state_focused} defined in its background.
5300      */
5301     boolean mDefaultFocusHighlightEnabled = true;
5302 
5303     private CheckForLongPress mPendingCheckForLongPress;
5304     @UnsupportedAppUsage
5305     private CheckForTap mPendingCheckForTap = null;
5306     private PerformClick mPerformClick;
5307     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
5308     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
5309     private UnsetPressedState mUnsetPressedState;
5310 
5311     /**
5312      * Whether the long press's action has been invoked.  The tap's action is invoked on the
5313      * up event while a long press is invoked as soon as the long press duration is reached, so
5314      * a long press could be performed before the tap is checked, in which case the tap's action
5315      * should not be invoked.
5316      */
5317     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5318     private boolean mHasPerformedLongPress;
5319 
5320     /**
5321      * Whether a context click button is currently pressed down. This is true when the stylus is
5322      * touching the screen and the primary button has been pressed, or if a mouse's right button is
5323      * pressed. This is false once the button is released or if the stylus has been lifted.
5324      */
5325     private boolean mInContextButtonPress;
5326 
5327     /**
5328      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
5329      * true after a stylus button press has occured, when the next up event should not be recognized
5330      * as a tap.
5331      */
5332     private boolean mIgnoreNextUpEvent;
5333 
5334     /**
5335      * The minimum height of the view. We'll try our best to have the height
5336      * of this view to at least this amount.
5337      */
5338     @ViewDebug.ExportedProperty(category = "measurement")
5339     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
5340     private int mMinHeight;
5341 
5342     /**
5343      * The minimum width of the view. We'll try our best to have the width
5344      * of this view to at least this amount.
5345      */
5346     @ViewDebug.ExportedProperty(category = "measurement")
5347     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
5348     private int mMinWidth;
5349 
5350     /**
5351      * The delegate to handle touch events that are physically in this view
5352      * but should be handled by another view.
5353      */
5354     private TouchDelegate mTouchDelegate = null;
5355 
5356     /**
5357      * While touch exploration is in use, set to true when hovering across boundaries and
5358      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
5359      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
5360      * {@link MotionEvent#ACTION_HOVER_EXIT}.
5361      * Note that children of view group are excluded in the touch area.
5362      * @see #dispatchTouchExplorationHoverEvent
5363      */
5364     private boolean mHoveringTouchDelegate = false;
5365 
5366     // These two fields are set if the view is a handwriting delegator.
5367     private Runnable mHandwritingDelegatorCallback;
5368     private String mAllowedHandwritingDelegatePackageName;
5369 
5370     // These three fields are set if the view is a handwriting delegate.
5371     private boolean mIsHandwritingDelegate;
5372     private String mAllowedHandwritingDelegatorPackageName;
5373     private @InputMethodManager.HandwritingDelegateFlags int mHandwritingDelegateFlags;
5374 
5375     /**
5376      * Solid color to use as a background when creating the drawing cache. Enables
5377      * the cache to use 16 bit bitmaps instead of 32 bit.
5378      */
5379     private int mDrawingCacheBackgroundColor = 0;
5380 
5381     /**
5382      * Special tree observer used when mAttachInfo is null.
5383      */
5384     private ViewTreeObserver mFloatingTreeObserver;
5385 
5386     /**
5387      * Cache the touch slop from the context that created the view.
5388      */
5389     private int mTouchSlop;
5390 
5391     /**
5392      * Cache the ambiguous gesture multiplier from the context that created the view.
5393      */
5394     private float mAmbiguousGestureMultiplier;
5395 
5396     /**
5397      * Object that handles automatic animation of view properties.
5398      */
5399     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5400     private ViewPropertyAnimator mAnimator = null;
5401 
5402     /**
5403      * List of registered FrameMetricsObservers.
5404      */
5405     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
5406 
5407     /**
5408      * Flag indicating that a drag can cross window boundaries.  When
5409      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5410      * with this flag set, all visible applications with targetSdkVersion >=
5411      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
5412      * in the drag operation and receive the dragged content.
5413      *
5414      * <p>If this is the only flag set, then the drag recipient will only have access to text data
5415      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
5416      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
5417      */
5418     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
5419 
5420     /**
5421      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5422      * request read access to the content URI(s) contained in the {@link ClipData} object.
5423      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5424      */
5425     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5426 
5427     /**
5428      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5429      * request write access to the content URI(s) contained in the {@link ClipData} object.
5430      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5431      */
5432     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5433 
5434     /**
5435      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5436      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5437      * reboots until explicitly revoked with
5438      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5439      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5440      */
5441     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5442             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5443 
5444     /**
5445      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5446      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5447      * match against the original granted URI.
5448      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5449      */
5450     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5451             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5452 
5453     /**
5454      * Flag indicating that the drag shadow will be opaque.  When
5455      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5456      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5457      */
5458     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5459 
5460     /**
5461      * Flag indicating that the drag was initiated with
5462      * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START}. When
5463      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called, this
5464      * is used by the system to perform a drag without animations.
5465      */
5466     public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
5467 
5468     /**
5469      * Flag indicating that the caller desires to take ownership of the drag surface for handling
5470      * the animation associated with an unhandled drag.  It is mainly useful if the view starting
5471      * a global drag changes visibility during the gesture and the default animation of animating
5472      * the surface back to the origin is not sufficient.
5473      *
5474      * The calling app must hold the {@link android.Manifest.permission#START_TASKS_FROM_RECENTS}
5475      * permission and will receive the drag surface as a part of
5476      * {@link action.view.DragEvent#ACTION_DRAG_ENDED} only if the drag event's
5477      * {@link action.view.DragEvent#getDragResult()} is {@code false}.  The caller is responsible
5478      * for removing the surface after its animation.
5479      *
5480      * This flag has no effect if the system decides that a cancel-drag animation does not need to
5481      * occur.
5482      * @hide
5483      */
5484     public static final int DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION = 1 << 11;
5485 
5486     /**
5487      * Flag indicating that a drag can cross window boundaries (within the same application).  When
5488      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5489      * with this flag set, only visible windows belonging to the same application (ie. share the
5490      * same UID) with targetSdkVersion >= {@link android.os.Build.VERSION_CODES#N API 24} will be
5491      * able to participate in the drag operation and receive the dragged content.
5492      *
5493      * If both DRAG_FLAG_GLOBAL_SAME_APPLICATION and DRAG_FLAG_GLOBAL are set, then
5494      * DRAG_FLAG_GLOBAL_SAME_APPLICATION takes precedence and the drag will only go to visible
5495      * windows from the same application.
5496      */
5497     @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS)
5498     public static final int DRAG_FLAG_GLOBAL_SAME_APPLICATION = 1 << 12;
5499 
5500     /**
5501      * Flag indicating that an unhandled drag should be delegated to the system to be started if no
5502      * visible window wishes to handle the drop. When using this flag, the caller must provide
5503      * ClipData with an Item that contains an immutable IntentSender to an activity to be launched
5504      * (not a broadcast, service, etc).  See
5505      * {@link ClipData.Item.Builder#setIntentSender(IntentSender)}.
5506      *
5507      * The system can decide to launch the intent or not based on factors like the current screen
5508      * size or windowing mode. If the system does not launch the intent, it will be canceled via the
5509      * normal drag and drop flow.
5510      */
5511     @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS)
5512     public static final int DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG = 1 << 13;
5513 
5514     /**
5515      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5516      */
5517     private float mVerticalScrollFactor;
5518 
5519     /**
5520      * Position of the vertical scroll bar.
5521      */
5522     @UnsupportedAppUsage
5523     private int mVerticalScrollbarPosition;
5524 
5525     /**
5526      * Position the scroll bar at the default position as determined by the system.
5527      */
5528     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5529 
5530     /**
5531      * Position the scroll bar along the left edge.
5532      */
5533     public static final int SCROLLBAR_POSITION_LEFT = 1;
5534 
5535     /**
5536      * Position the scroll bar along the right edge.
5537      */
5538     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5539 
5540     /**
5541      * Indicates that the view does not have a layer.
5542      *
5543      * @see #getLayerType()
5544      * @see #setLayerType(int, android.graphics.Paint)
5545      * @see #LAYER_TYPE_SOFTWARE
5546      * @see #LAYER_TYPE_HARDWARE
5547      */
5548     public static final int LAYER_TYPE_NONE = 0;
5549 
5550     /**
5551      * <p>Indicates that the view has a software layer. A software layer is backed
5552      * by a bitmap and causes the view to be rendered using Android's software
5553      * rendering pipeline, even if hardware acceleration is enabled.</p>
5554      *
5555      * <p>Software layers have various usages:</p>
5556      * <p>When the application is not using hardware acceleration, a software layer
5557      * is useful to apply a specific color filter and/or blending mode and/or
5558      * translucency to a view and all its children.</p>
5559      * <p>When the application is using hardware acceleration, a software layer
5560      * is useful to render drawing primitives not supported by the hardware
5561      * accelerated pipeline. It can also be used to cache a complex view tree
5562      * into a texture and reduce the complexity of drawing operations. For instance,
5563      * when animating a complex view tree with a translation, a software layer can
5564      * be used to render the view tree only once.</p>
5565      * <p>Software layers should be avoided when the affected view tree updates
5566      * often. Every update will require to re-render the software layer, which can
5567      * potentially be slow (particularly when hardware acceleration is turned on
5568      * since the layer will have to be uploaded into a hardware texture after every
5569      * update.)</p>
5570      *
5571      * @see #getLayerType()
5572      * @see #setLayerType(int, android.graphics.Paint)
5573      * @see #LAYER_TYPE_NONE
5574      * @see #LAYER_TYPE_HARDWARE
5575      */
5576     public static final int LAYER_TYPE_SOFTWARE = 1;
5577 
5578     /**
5579      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5580      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5581      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5582      * rendering pipeline, but only if hardware acceleration is turned on for the
5583      * view hierarchy. When hardware acceleration is turned off, hardware layers
5584      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5585      *
5586      * <p>A hardware layer is useful to apply a specific color filter and/or
5587      * blending mode and/or translucency to a view and all its children.</p>
5588      * <p>A hardware layer can be used to cache a complex view tree into a
5589      * texture and reduce the complexity of drawing operations. For instance,
5590      * when animating a complex view tree with a translation, a hardware layer can
5591      * be used to render the view tree only once.</p>
5592      * <p>A hardware layer can also be used to increase the rendering quality when
5593      * rotation transformations are applied on a view. It can also be used to
5594      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5595      *
5596      * @see #getLayerType()
5597      * @see #setLayerType(int, android.graphics.Paint)
5598      * @see #LAYER_TYPE_NONE
5599      * @see #LAYER_TYPE_SOFTWARE
5600      */
5601     public static final int LAYER_TYPE_HARDWARE = 2;
5602 
5603     /** @hide */
5604     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5605             LAYER_TYPE_NONE,
5606             LAYER_TYPE_SOFTWARE,
5607             LAYER_TYPE_HARDWARE
5608     })
5609     @Retention(RetentionPolicy.SOURCE)
5610     public @interface LayerType {}
5611 
5612     int mLayerType = LAYER_TYPE_NONE;
5613     Paint mLayerPaint;
5614 
5615     /**
5616      * Set to true when drawing cache is enabled and cannot be created.
5617      *
5618      * @hide
5619      */
5620     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5621     public boolean mCachingFailed;
5622     @UnsupportedAppUsage
5623     private Bitmap mDrawingCache;
5624     @UnsupportedAppUsage
5625     private Bitmap mUnscaledDrawingCache;
5626 
5627     /**
5628      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5629      * <p>
5630      * When non-null and valid, this is expected to contain an up-to-date copy
5631      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5632      * cleanup.
5633      */
5634     @UnsupportedAppUsage
5635     final RenderNode mRenderNode;
5636 
5637     /**
5638      * Set to true when the view is sending hover accessibility events because it
5639      * is the innermost hovered view.
5640      */
5641     private boolean mSendingHoverAccessibilityEvents;
5642 
5643     /**
5644      * Delegate for injecting accessibility functionality.
5645      */
5646     @UnsupportedAppUsage
5647     AccessibilityDelegate mAccessibilityDelegate;
5648 
5649     /**
5650      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5651      * and add/remove objects to/from the overlay directly through the Overlay methods.
5652      */
5653     ViewOverlay mOverlay;
5654 
5655     /**
5656      * The currently active parent view for receiving delegated nested scrolling events.
5657      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5658      * by {@link #stopNestedScroll()} at the same point where we clear
5659      * requestDisallowInterceptTouchEvent.
5660      */
5661     private ViewParent mNestedScrollingParent;
5662 
5663     /**
5664      * Consistency verifier for debugging purposes.
5665      * @hide
5666      */
5667     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5668             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5669                     new InputEventConsistencyVerifier(this, 0) : null;
5670 
5671     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5672 
5673     private int[] mTempNestedScrollConsumed;
5674 
5675     /**
5676      * An overlay is going to draw this View instead of being drawn as part of this
5677      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5678      * when this view is invalidated.
5679      */
5680     GhostView mGhostView;
5681 
5682     /**
5683      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5684      * @hide
5685      */
5686     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5687     public String[] mAttributes;
5688 
5689     /**
5690      * Maps a Resource id to its name.
5691      */
5692     private static SparseArray<String> mAttributeMap;
5693 
5694     /**
5695      * Queue of pending runnables. Used to postpone calls to post() until this
5696      * view is attached and has a handler.
5697      */
5698     private HandlerActionQueue mRunQueue;
5699 
5700     /**
5701      * The pointer icon when the mouse hovers on this view. The default is null.
5702      */
5703     private PointerIcon mMousePointerIcon;
5704 
5705     /** Vibrator for haptic feedback. */
5706     private Vibrator mVibrator;
5707 
5708     /**
5709      * @hide
5710      */
5711     @UnsupportedAppUsage
5712     String mStartActivityRequestWho;
5713 
5714     @Nullable
5715     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5716 
5717     /** Used to delay visibility updates sent to the autofill manager */
5718     private Handler mVisibilityChangeForAutofillHandler;
5719 
5720     /**
5721      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5722      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5723      */
5724     @Nullable
5725     private ContentCaptureSession mContentCaptureSession;
5726 
5727     /**
5728      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5729      */
5730     private boolean mContentCaptureSessionCached;
5731 
5732     @LayoutRes
5733     private int mSourceLayoutId = ID_NULL;
5734 
5735     @Nullable
5736     private SparseIntArray mAttributeSourceResId;
5737 
5738     @Nullable
5739     private SparseArray<int[]> mAttributeResolutionStacks;
5740 
5741     @StyleRes
5742     private int mExplicitStyle;
5743 
5744     /**
5745      * Specifies which input source classes should provide unbuffered input events to this view
5746      *
5747      * @see View#requestUnbufferedDispatch(int)
5748      */
5749     @InputSourceClass
5750     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5751 
5752     @Nullable
5753     private String[] mReceiveContentMimeTypes;
5754 
5755     @Nullable
5756     private ViewTranslationCallback mViewTranslationCallback;
5757 
5758     private float mFrameContentVelocity = -1;
5759 
5760     @Nullable
5761 
5762     private ViewTranslationResponse mViewTranslationResponse;
5763 
5764     /**
5765      * The size in DP that is considered small for VRR purposes, if square.
5766      */
5767     private static final float FRAME_RATE_SQUARE_SMALL_SIZE_DP = 40f;
5768 
5769     /**
5770      * The size in DP that is considered small for VRR purposes in the narrow dimension. Used for
5771      * narrow Views like a progress bar.
5772      */
5773     private static final float FRAME_RATE_NARROW_SIZE_DP = 10f;
5774 
5775     /**
5776      * A threshold value to determine the frame rate category of the View based on the size.
5777      */
5778     private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
5779 
5780     static final float MAX_FRAME_RATE = 120;
5781 
5782     // The preferred frame rate of the view that is mainly used for
5783     // touch boosting, view velocity handling, and TextureView.
5784     private float mPreferredFrameRate = REQUESTED_FRAME_RATE_CATEGORY_DEFAULT;
5785 
5786     private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
5787 
5788     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5789     public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
5790     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5791     public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1;
5792     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5793     public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2;
5794     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5795     public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3;
5796     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5797     public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4;
5798 
5799     private int mSizeBasedFrameRateCategoryAndReason;
5800 
5801     /**
5802      * Simple constructor to use when creating a view from code.
5803      *
5804      * @param context The Context the view is running in, through which it can
5805      *        access the current theme, resources, etc.
5806      */
View(Context context)5807     public View(Context context) {
5808         mContext = context;
5809         mResources = context != null ? context.getResources() : null;
5810         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5811         // Set some flags defaults
5812         mPrivateFlags2 =
5813                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5814                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5815                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5816                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5817                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5818                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5819 
5820         final ViewConfiguration configuration = ViewConfiguration.get(context);
5821         mTouchSlop = configuration.getScaledTouchSlop();
5822         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5823 
5824         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5825         mUserPaddingStart = UNDEFINED_PADDING;
5826         mUserPaddingEnd = UNDEFINED_PADDING;
5827         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5828 
5829         if (!sCompatibilityDone && context != null) {
5830             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5831 
5832             // Old versions of the platform would give different results from
5833             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5834             // modes, so we always need to run an additional EXACTLY pass.
5835             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5836 
5837             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5838             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5839             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5840 
5841             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5842             // in apps so we target check it to avoid breaking existing apps.
5843             sPreserveMarginParamsInLayoutParamConversion =
5844                     targetSdkVersion >= Build.VERSION_CODES.N;
5845 
5846             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5847 
5848             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5849 
5850             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5851 
5852             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5853                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5854 
5855             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5856 
5857             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5858 
5859             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5860 
5861             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5862 
5863             sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
5864 
5865             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5866 
5867             GradientDrawable.sWrapNegativeAngleMeasurements =
5868                     targetSdkVersion >= Build.VERSION_CODES.Q;
5869 
5870             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5871 
5872             sCompatibilityDone = true;
5873         }
5874     }
5875 
5876     /**
5877      * Constructor that is called when inflating a view from XML. This is called
5878      * when a view is being constructed from an XML file, supplying attributes
5879      * that were specified in the XML file. This version uses a default style of
5880      * 0, so the only attribute values applied are those in the Context's Theme
5881      * and the given AttributeSet.
5882      *
5883      * <p>
5884      * The method onFinishInflate() will be called after all children have been
5885      * added.
5886      *
5887      * @param context The Context the view is running in, through which it can
5888      *        access the current theme, resources, etc.
5889      * @param attrs The attributes of the XML tag that is inflating the view.
5890      * @see #View(Context, AttributeSet, int)
5891      */
5892     public View(Context context, @Nullable AttributeSet attrs) {
5893         this(context, attrs, 0);
5894     }
5895 
5896     /**
5897      * Perform inflation from XML and apply a class-specific base style from a
5898      * theme attribute. This constructor of View allows subclasses to use their
5899      * own base style when they are inflating. For example, a Button class's
5900      * constructor would call this version of the super class constructor and
5901      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5902      * allows the theme's button style to modify all of the base view attributes
5903      * (in particular its background) as well as the Button class's attributes.
5904      *
5905      * @param context The Context the view is running in, through which it can
5906      *        access the current theme, resources, etc.
5907      * @param attrs The attributes of the XML tag that is inflating the view.
5908      * @param defStyleAttr An attribute in the current theme that contains a
5909      *        reference to a style resource that supplies default values for
5910      *        the view. Can be 0 to not look for defaults.
5911      * @see #View(Context, AttributeSet)
5912      */
5913     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5914         this(context, attrs, defStyleAttr, 0);
5915     }
5916 
5917     /**
5918      * Perform inflation from XML and apply a class-specific base style from a
5919      * theme attribute or style resource. This constructor of View allows
5920      * subclasses to use their own base style when they are inflating.
5921      * <p>
5922      * When determining the final value of a particular attribute, there are
5923      * four inputs that come into play:
5924      * <ol>
5925      * <li>Any attribute values in the given AttributeSet.
5926      * <li>The style resource specified in the AttributeSet (named "style").
5927      * <li>The default style specified by <var>defStyleAttr</var>.
5928      * <li>The default style specified by <var>defStyleRes</var>.
5929      * <li>The base values in this theme.
5930      * </ol>
5931      * <p>
5932      * Each of these inputs is considered in-order, with the first listed taking
5933      * precedence over the following ones. In other words, if in the
5934      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5935      * , then the button's text will <em>always</em> be black, regardless of
5936      * what is specified in any of the styles.
5937      *
5938      * @param context The Context the view is running in, through which it can
5939      *        access the current theme, resources, etc.
5940      * @param attrs The attributes of the XML tag that is inflating the view.
5941      * @param defStyleAttr An attribute in the current theme that contains a
5942      *        reference to a style resource that supplies default values for
5943      *        the view. Can be 0 to not look for defaults.
5944      * @param defStyleRes A resource identifier of a style resource that
5945      *        supplies default values for the view, used only if
5946      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5947      *        to not look for defaults.
5948      * @see #View(Context, AttributeSet, int)
5949      */
5950     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5951         this(context);
5952 
5953         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5954 
5955         final TypedArray a = context.obtainStyledAttributes(
5956                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5957 
5958         retrieveExplicitStyle(context.getTheme(), attrs);
5959         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5960                 defStyleAttr, defStyleRes);
5961 
5962         if (sDebugViewAttributes) {
5963             saveAttributeData(attrs, a);
5964         }
5965 
5966         Drawable background = null;
5967 
5968         int leftPadding = -1;
5969         int topPadding = -1;
5970         int rightPadding = -1;
5971         int bottomPadding = -1;
5972         int startPadding = UNDEFINED_PADDING;
5973         int endPadding = UNDEFINED_PADDING;
5974 
5975         int padding = -1;
5976         int paddingHorizontal = -1;
5977         int paddingVertical = -1;
5978 
5979         int viewFlagValues = 0;
5980         int viewFlagMasks = 0;
5981 
5982         boolean setScrollContainer = false;
5983 
5984         int x = 0;
5985         int y = 0;
5986 
5987         float tx = 0;
5988         float ty = 0;
5989         float tz = 0;
5990         float elevation = 0;
5991         float rotation = 0;
5992         float rotationX = 0;
5993         float rotationY = 0;
5994         float sx = 1f;
5995         float sy = 1f;
5996         boolean transformSet = false;
5997 
5998         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5999         int overScrollMode = mOverScrollMode;
6000         boolean initializeScrollbars = false;
6001         boolean initializeScrollIndicators = false;
6002 
6003         boolean startPaddingDefined = false;
6004         boolean endPaddingDefined = false;
6005         boolean leftPaddingDefined = false;
6006         boolean rightPaddingDefined = false;
6007 
6008         // Set default values.
6009         viewFlagValues |= FOCUSABLE_AUTO;
6010         viewFlagMasks |= FOCUSABLE_AUTO;
6011 
6012         final int N = a.getIndexCount();
6013         for (int i = 0; i < N; i++) {
6014             int attr = a.getIndex(i);
6015             switch (attr) {
6016                 case com.android.internal.R.styleable.View_background:
6017                     background = a.getDrawable(attr);
6018                     break;
6019                 case com.android.internal.R.styleable.View_padding:
6020                     padding = a.getDimensionPixelSize(attr, -1);
6021                     mUserPaddingLeftInitial = padding;
6022                     mUserPaddingRightInitial = padding;
6023                     leftPaddingDefined = true;
6024                     rightPaddingDefined = true;
6025                     break;
6026                 case com.android.internal.R.styleable.View_paddingHorizontal:
6027                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
6028                     mUserPaddingLeftInitial = paddingHorizontal;
6029                     mUserPaddingRightInitial = paddingHorizontal;
6030                     leftPaddingDefined = true;
6031                     rightPaddingDefined = true;
6032                     break;
6033                 case com.android.internal.R.styleable.View_paddingVertical:
6034                     paddingVertical = a.getDimensionPixelSize(attr, -1);
6035                     break;
6036                 case com.android.internal.R.styleable.View_paddingLeft:
6037                     leftPadding = a.getDimensionPixelSize(attr, -1);
6038                     mUserPaddingLeftInitial = leftPadding;
6039                     leftPaddingDefined = true;
6040                     break;
6041                 case com.android.internal.R.styleable.View_paddingTop:
6042                     topPadding = a.getDimensionPixelSize(attr, -1);
6043                     break;
6044                 case com.android.internal.R.styleable.View_paddingRight:
6045                     rightPadding = a.getDimensionPixelSize(attr, -1);
6046                     mUserPaddingRightInitial = rightPadding;
6047                     rightPaddingDefined = true;
6048                     break;
6049                 case com.android.internal.R.styleable.View_paddingBottom:
6050                     bottomPadding = a.getDimensionPixelSize(attr, -1);
6051                     break;
6052                 case com.android.internal.R.styleable.View_paddingStart:
6053                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
6054                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
6055                     break;
6056                 case com.android.internal.R.styleable.View_paddingEnd:
6057                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
6058                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
6059                     break;
6060                 case com.android.internal.R.styleable.View_scrollX:
6061                     x = a.getDimensionPixelOffset(attr, 0);
6062                     break;
6063                 case com.android.internal.R.styleable.View_scrollY:
6064                     y = a.getDimensionPixelOffset(attr, 0);
6065                     break;
6066                 case com.android.internal.R.styleable.View_alpha:
6067                     setAlpha(a.getFloat(attr, 1f));
6068                     break;
6069                 case com.android.internal.R.styleable.View_transformPivotX:
6070                     setPivotX(a.getDimension(attr, 0));
6071                     break;
6072                 case com.android.internal.R.styleable.View_transformPivotY:
6073                     setPivotY(a.getDimension(attr, 0));
6074                     break;
6075                 case com.android.internal.R.styleable.View_translationX:
6076                     tx = a.getDimension(attr, 0);
6077                     transformSet = true;
6078                     break;
6079                 case com.android.internal.R.styleable.View_translationY:
6080                     ty = a.getDimension(attr, 0);
6081                     transformSet = true;
6082                     break;
6083                 case com.android.internal.R.styleable.View_translationZ:
6084                     tz = a.getDimension(attr, 0);
6085                     transformSet = true;
6086                     break;
6087                 case com.android.internal.R.styleable.View_elevation:
6088                     elevation = a.getDimension(attr, 0);
6089                     transformSet = true;
6090                     break;
6091                 case com.android.internal.R.styleable.View_rotation:
6092                     rotation = a.getFloat(attr, 0);
6093                     transformSet = true;
6094                     break;
6095                 case com.android.internal.R.styleable.View_rotationX:
6096                     rotationX = a.getFloat(attr, 0);
6097                     transformSet = true;
6098                     break;
6099                 case com.android.internal.R.styleable.View_rotationY:
6100                     rotationY = a.getFloat(attr, 0);
6101                     transformSet = true;
6102                     break;
6103                 case com.android.internal.R.styleable.View_scaleX:
6104                     sx = a.getFloat(attr, 1f);
6105                     transformSet = true;
6106                     break;
6107                 case com.android.internal.R.styleable.View_scaleY:
6108                     sy = a.getFloat(attr, 1f);
6109                     transformSet = true;
6110                     break;
6111                 case com.android.internal.R.styleable.View_id:
6112                     mID = a.getResourceId(attr, NO_ID);
6113                     break;
6114                 case com.android.internal.R.styleable.View_tag:
6115                     mTag = a.getText(attr);
6116                     break;
6117                 case com.android.internal.R.styleable.View_fitsSystemWindows:
6118                     if (a.getBoolean(attr, false)) {
6119                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
6120                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
6121                     }
6122                     break;
6123                 case com.android.internal.R.styleable.View_focusable:
6124                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
6125                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
6126                         viewFlagMasks |= FOCUSABLE_MASK;
6127                     }
6128                     break;
6129                 case com.android.internal.R.styleable.View_focusableInTouchMode:
6130                     if (a.getBoolean(attr, false)) {
6131                         // unset auto focus since focusableInTouchMode implies explicit focusable
6132                         viewFlagValues &= ~FOCUSABLE_AUTO;
6133                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
6134                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
6135                     }
6136                     break;
6137                 case com.android.internal.R.styleable.View_clickable:
6138                     if (a.getBoolean(attr, false)) {
6139                         viewFlagValues |= CLICKABLE;
6140                         viewFlagMasks |= CLICKABLE;
6141                     }
6142                     break;
6143                 case com.android.internal.R.styleable.View_allowClickWhenDisabled:
6144                     setAllowClickWhenDisabled(a.getBoolean(attr, false));
6145                     break;
6146                 case com.android.internal.R.styleable.View_longClickable:
6147                     if (a.getBoolean(attr, false)) {
6148                         viewFlagValues |= LONG_CLICKABLE;
6149                         viewFlagMasks |= LONG_CLICKABLE;
6150                     }
6151                     break;
6152                 case com.android.internal.R.styleable.View_contextClickable:
6153                     if (a.getBoolean(attr, false)) {
6154                         viewFlagValues |= CONTEXT_CLICKABLE;
6155                         viewFlagMasks |= CONTEXT_CLICKABLE;
6156                     }
6157                     break;
6158                 case com.android.internal.R.styleable.View_saveEnabled:
6159                     if (!a.getBoolean(attr, true)) {
6160                         viewFlagValues |= SAVE_DISABLED;
6161                         viewFlagMasks |= SAVE_DISABLED_MASK;
6162                     }
6163                     break;
6164                 case com.android.internal.R.styleable.View_duplicateParentState:
6165                     if (a.getBoolean(attr, false)) {
6166                         viewFlagValues |= DUPLICATE_PARENT_STATE;
6167                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
6168                     }
6169                     break;
6170                 case com.android.internal.R.styleable.View_visibility:
6171                     final int visibility = a.getInt(attr, 0);
6172                     if (visibility != 0) {
6173                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
6174                         viewFlagMasks |= VISIBILITY_MASK;
6175                     }
6176                     break;
6177                 case com.android.internal.R.styleable.View_layoutDirection:
6178                     // Clear any layout direction flags (included resolved bits) already set
6179                     mPrivateFlags2 &=
6180                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
6181                     // Set the layout direction flags depending on the value of the attribute
6182                     final int layoutDirection = a.getInt(attr, -1);
6183                     final int value = (layoutDirection != -1) ?
6184                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
6185                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
6186                     break;
6187                 case com.android.internal.R.styleable.View_drawingCacheQuality:
6188                     final int cacheQuality = a.getInt(attr, 0);
6189                     if (cacheQuality != 0) {
6190                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
6191                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
6192                     }
6193                     break;
6194                 case com.android.internal.R.styleable.View_contentDescription:
6195                     setContentDescription(a.getString(attr));
6196                     break;
6197                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
6198                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
6199                     break;
6200                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
6201                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
6202                     break;
6203                 case com.android.internal.R.styleable.View_labelFor:
6204                     setLabelFor(a.getResourceId(attr, NO_ID));
6205                     break;
6206                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
6207                     if (!a.getBoolean(attr, true)) {
6208                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
6209                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
6210                     }
6211                     break;
6212                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
6213                     if (!a.getBoolean(attr, true)) {
6214                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
6215                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
6216                     }
6217                     break;
6218                 case R.styleable.View_scrollbars:
6219                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
6220                     if (scrollbars != SCROLLBARS_NONE) {
6221                         viewFlagValues |= scrollbars;
6222                         viewFlagMasks |= SCROLLBARS_MASK;
6223                         initializeScrollbars = true;
6224                     }
6225                     break;
6226                 //noinspection deprecation
6227                 case R.styleable.View_fadingEdge:
6228                     break;
6229                 case R.styleable.View_requiresFadingEdge:
6230                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
6231                     if (fadingEdge != FADING_EDGE_NONE) {
6232                         viewFlagValues |= fadingEdge;
6233                         viewFlagMasks |= FADING_EDGE_MASK;
6234                         initializeFadingEdgeInternal(a);
6235                     }
6236                     break;
6237                 case R.styleable.View_scrollbarStyle:
6238                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
6239                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6240                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
6241                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
6242                     }
6243                     break;
6244                 case R.styleable.View_isScrollContainer:
6245                     setScrollContainer = true;
6246                     if (a.getBoolean(attr, false)) {
6247                         setScrollContainer(true);
6248                     }
6249                     break;
6250                 case com.android.internal.R.styleable.View_keepScreenOn:
6251                     if (a.getBoolean(attr, false)) {
6252                         viewFlagValues |= KEEP_SCREEN_ON;
6253                         viewFlagMasks |= KEEP_SCREEN_ON;
6254                     }
6255                     break;
6256                 case R.styleable.View_filterTouchesWhenObscured:
6257                     if (a.getBoolean(attr, false)) {
6258                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
6259                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
6260                     }
6261                     break;
6262                 case R.styleable.View_nextFocusLeft:
6263                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
6264                     break;
6265                 case R.styleable.View_nextFocusRight:
6266                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
6267                     break;
6268                 case R.styleable.View_nextFocusUp:
6269                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
6270                     break;
6271                 case R.styleable.View_nextFocusDown:
6272                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
6273                     break;
6274                 case R.styleable.View_nextFocusForward:
6275                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
6276                     break;
6277                 case R.styleable.View_nextClusterForward:
6278                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
6279                     break;
6280                 case R.styleable.View_minWidth:
6281                     mMinWidth = a.getDimensionPixelSize(attr, 0);
6282                     break;
6283                 case R.styleable.View_minHeight:
6284                     mMinHeight = a.getDimensionPixelSize(attr, 0);
6285                     break;
6286                 case R.styleable.View_onClick:
6287                     if (context.isRestricted()) {
6288                         throw new IllegalStateException("The android:onClick attribute cannot "
6289                                 + "be used within a restricted context");
6290                     }
6291 
6292                     final String handlerName = a.getString(attr);
6293                     if (handlerName != null) {
6294                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
6295                     }
6296                     break;
6297                 case R.styleable.View_overScrollMode:
6298                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
6299                     break;
6300                 case R.styleable.View_verticalScrollbarPosition:
6301                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
6302                     break;
6303                 case R.styleable.View_layerType:
6304                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
6305                     break;
6306                 case R.styleable.View_textDirection:
6307                     // Clear any text direction flag already set
6308                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
6309                     // Set the text direction flags depending on the value of the attribute
6310                     final int textDirection = a.getInt(attr, -1);
6311                     if (textDirection != -1) {
6312                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
6313                     }
6314                     break;
6315                 case R.styleable.View_textAlignment:
6316                     // Clear any text alignment flag already set
6317                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
6318                     // Set the text alignment flag depending on the value of the attribute
6319                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
6320                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
6321                     break;
6322                 case R.styleable.View_importantForAccessibility:
6323                     setImportantForAccessibility(a.getInt(attr,
6324                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
6325                     break;
6326                 case R.styleable.View_accessibilityDataSensitive:
6327                     setAccessibilityDataSensitive(a.getInt(attr,
6328                             ACCESSIBILITY_DATA_SENSITIVE_AUTO));
6329                     break;
6330                 case R.styleable.View_accessibilityLiveRegion:
6331                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
6332                     break;
6333                 case R.styleable.View_transitionName:
6334                     setTransitionName(a.getString(attr));
6335                     break;
6336                 case R.styleable.View_nestedScrollingEnabled:
6337                     setNestedScrollingEnabled(a.getBoolean(attr, false));
6338                     break;
6339                 case R.styleable.View_stateListAnimator:
6340                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
6341                             a.getResourceId(attr, 0)));
6342                     break;
6343                 case R.styleable.View_backgroundTint:
6344                     // This will get applied later during setBackground().
6345                     if (mBackgroundTint == null) {
6346                         mBackgroundTint = new TintInfo();
6347                     }
6348                     mBackgroundTint.mTintList = a.getColorStateList(
6349                             R.styleable.View_backgroundTint);
6350                     mBackgroundTint.mHasTintList = true;
6351                     break;
6352                 case R.styleable.View_backgroundTintMode:
6353                     // This will get applied later during setBackground().
6354                     if (mBackgroundTint == null) {
6355                         mBackgroundTint = new TintInfo();
6356                     }
6357                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
6358                             R.styleable.View_backgroundTintMode, -1), null);
6359                     mBackgroundTint.mHasTintMode = true;
6360                     break;
6361                 case R.styleable.View_outlineProvider:
6362                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
6363                             PROVIDER_BACKGROUND));
6364                     break;
6365                 case R.styleable.View_foreground:
6366                     setForeground(a.getDrawable(attr));
6367                     break;
6368                 case R.styleable.View_foregroundGravity:
6369                     setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
6370                     break;
6371                 case R.styleable.View_foregroundTintMode:
6372                     setForegroundTintBlendMode(
6373                             Drawable.parseBlendMode(a.getInt(attr, -1),
6374                                     null));
6375                     break;
6376                 case R.styleable.View_foregroundTint:
6377                     setForegroundTintList(a.getColorStateList(attr));
6378                     break;
6379                 case R.styleable.View_foregroundInsidePadding:
6380                     if (mForegroundInfo == null) {
6381                         mForegroundInfo = new ForegroundInfo();
6382                     }
6383                     mForegroundInfo.mInsidePadding = a.getBoolean(attr,
6384                             mForegroundInfo.mInsidePadding);
6385                     break;
6386                 case R.styleable.View_scrollIndicators:
6387                     final int scrollIndicators =
6388                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
6389                                     & SCROLL_INDICATORS_PFLAG3_MASK;
6390                     if (scrollIndicators != 0) {
6391                         mPrivateFlags3 |= scrollIndicators;
6392                         initializeScrollIndicators = true;
6393                     }
6394                     break;
6395                 case R.styleable.View_pointerIcon:
6396                     final int resourceId = a.getResourceId(attr, 0);
6397                     if (resourceId != 0) {
6398                         setPointerIcon(PointerIcon.load(
6399                                 context.getResources(), resourceId));
6400                     } else {
6401                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
6402                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
6403                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
6404                         }
6405                     }
6406                     break;
6407                 case R.styleable.View_forceHasOverlappingRendering:
6408                     if (a.peekValue(attr) != null) {
6409                         forceHasOverlappingRendering(a.getBoolean(attr, true));
6410                     }
6411                     break;
6412                 case R.styleable.View_tooltipText:
6413                     setTooltipText(a.getText(attr));
6414                     break;
6415                 case R.styleable.View_keyboardNavigationCluster:
6416                     if (a.peekValue(attr) != null) {
6417                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
6418                     }
6419                     break;
6420                 case R.styleable.View_focusedByDefault:
6421                     if (a.peekValue(attr) != null) {
6422                         setFocusedByDefault(a.getBoolean(attr, true));
6423                     }
6424                     break;
6425                 case R.styleable.View_autofillHints:
6426                     if (a.peekValue(attr) != null) {
6427                         CharSequence[] rawHints = null;
6428                         String rawString = null;
6429 
6430                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
6431                             int resId = a.getResourceId(attr, 0);
6432 
6433                             try {
6434                                 rawHints = a.getTextArray(attr);
6435                             } catch (Resources.NotFoundException e) {
6436                                 rawString = getResources().getString(resId);
6437                             }
6438                         } else {
6439                             rawString = a.getString(attr);
6440                         }
6441 
6442                         if (rawHints == null) {
6443                             if (rawString == null) {
6444                                 throw new IllegalArgumentException(
6445                                         "Could not resolve autofillHints");
6446                             } else {
6447                                 rawHints = rawString.split(",");
6448                             }
6449                         }
6450 
6451                         String[] hints = new String[rawHints.length];
6452 
6453                         int numHints = rawHints.length;
6454                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
6455                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
6456                         }
6457                         setAutofillHints(hints);
6458                     }
6459                     break;
6460                 case R.styleable.View_importantForAutofill:
6461                     if (a.peekValue(attr) != null) {
6462                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
6463                     }
6464                     break;
6465                 case R.styleable.View_importantForContentCapture:
6466                     if (a.peekValue(attr) != null) {
6467                         setImportantForContentCapture(a.getInt(attr,
6468                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
6469                     }
6470                     break;
6471                 case R.styleable.View_isCredential:
6472                     if (a.peekValue(attr) != null) {
6473                         setIsCredential(a.getBoolean(attr, false));
6474                     }
6475                     break;
6476                 case R.styleable.View_defaultFocusHighlightEnabled:
6477                     if (a.peekValue(attr) != null) {
6478                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
6479                     }
6480                     break;
6481                 case R.styleable.View_screenReaderFocusable:
6482                     if (a.peekValue(attr) != null) {
6483                         setScreenReaderFocusable(a.getBoolean(attr, false));
6484                     }
6485                     break;
6486                 case R.styleable.View_accessibilityPaneTitle:
6487                     if (a.peekValue(attr) != null) {
6488                         setAccessibilityPaneTitle(a.getString(attr));
6489                     }
6490                     break;
6491                 case R.styleable.View_outlineSpotShadowColor:
6492                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6493                     break;
6494                 case R.styleable.View_outlineAmbientShadowColor:
6495                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6496                     break;
6497                 case com.android.internal.R.styleable.View_accessibilityHeading:
6498                     setAccessibilityHeading(a.getBoolean(attr, false));
6499                     break;
6500                 case R.styleable.View_forceDarkAllowed:
6501                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6502                     break;
6503                 case R.styleable.View_scrollCaptureHint:
6504                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6505                     break;
6506                 case R.styleable.View_clipToOutline:
6507                     setClipToOutline(a.getBoolean(attr, false));
6508                     break;
6509                 case R.styleable.View_preferKeepClear:
6510                     setPreferKeepClear(a.getBoolean(attr, false));
6511                     break;
6512                 case R.styleable.View_autoHandwritingEnabled:
6513                     setAutoHandwritingEnabled(a.getBoolean(attr, false));
6514                     break;
6515                 case R.styleable.View_handwritingBoundsOffsetLeft:
6516                     mHandwritingBoundsOffsetLeft = a.getDimension(attr, 0);
6517                     break;
6518                 case R.styleable.View_handwritingBoundsOffsetTop:
6519                     mHandwritingBoundsOffsetTop = a.getDimension(attr, 0);
6520                     break;
6521                 case R.styleable.View_handwritingBoundsOffsetRight:
6522                     mHandwritingBoundsOffsetRight = a.getDimension(attr, 0);
6523                     break;
6524                 case R.styleable.View_handwritingBoundsOffsetBottom:
6525                     mHandwritingBoundsOffsetBottom = a.getDimension(attr, 0);
6526                     break;
6527                 case R.styleable.View_contentSensitivity:
6528                     setContentSensitivity(a.getInt(attr, CONTENT_SENSITIVITY_AUTO));
6529                     break;
6530             }
6531         }
6532 
6533         setOverScrollMode(overScrollMode);
6534 
6535         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6536         // the resolved layout direction). Those cached values will be used later during padding
6537         // resolution.
6538         mUserPaddingStart = startPadding;
6539         mUserPaddingEnd = endPadding;
6540 
6541         if (background != null) {
6542             setBackground(background);
6543         }
6544 
6545         // setBackground above will record that padding is currently provided by the background.
6546         // If we have padding specified via xml, record that here instead and use it.
6547         mLeftPaddingDefined = leftPaddingDefined;
6548         mRightPaddingDefined = rightPaddingDefined;
6549 
6550         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6551         // bottomPadding, and padding set by background.  Valid padding beats everything.
6552         if (padding >= 0) {
6553             leftPadding = padding;
6554             topPadding = padding;
6555             rightPadding = padding;
6556             bottomPadding = padding;
6557             mUserPaddingLeftInitial = padding;
6558             mUserPaddingRightInitial = padding;
6559         } else {
6560             if (paddingHorizontal >= 0) {
6561                 leftPadding = paddingHorizontal;
6562                 rightPadding = paddingHorizontal;
6563                 mUserPaddingLeftInitial = paddingHorizontal;
6564                 mUserPaddingRightInitial = paddingHorizontal;
6565             }
6566             if (paddingVertical >= 0) {
6567                 topPadding = paddingVertical;
6568                 bottomPadding = paddingVertical;
6569             }
6570         }
6571 
6572         if (isRtlCompatibilityMode()) {
6573             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6574             // left / right padding are used if defined (meaning here nothing to do). If they are not
6575             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6576             // start / end and resolve them as left / right (layout direction is not taken into account).
6577             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6578             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6579             // defined.
6580             if (!mLeftPaddingDefined && startPaddingDefined) {
6581                 leftPadding = startPadding;
6582             }
6583             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6584             if (!mRightPaddingDefined && endPaddingDefined) {
6585                 rightPadding = endPadding;
6586             }
6587             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6588         } else {
6589             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6590             // values defined. Otherwise, left /right values are used.
6591             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6592             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6593             // defined.
6594             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6595 
6596             if (mLeftPaddingDefined && !hasRelativePadding) {
6597                 mUserPaddingLeftInitial = leftPadding;
6598             }
6599             if (mRightPaddingDefined && !hasRelativePadding) {
6600                 mUserPaddingRightInitial = rightPadding;
6601             }
6602         }
6603 
6604         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6605         // them on if topPadding or bottomPadding are not valid.
6606         internalSetPadding(
6607                 mUserPaddingLeftInitial,
6608                 topPadding >= 0 ? topPadding : mPaddingTop,
6609                 mUserPaddingRightInitial,
6610                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6611 
6612         if (viewFlagMasks != 0) {
6613             setFlags(viewFlagValues, viewFlagMasks);
6614         }
6615 
6616         if (initializeScrollbars) {
6617             initializeScrollbarsInternal(a);
6618         }
6619 
6620         if (initializeScrollIndicators) {
6621             initializeScrollIndicatorsInternal();
6622         }
6623 
6624         a.recycle();
6625 
6626         // Needs to be called after mViewFlags is set
6627         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6628             recomputePadding();
6629         }
6630 
6631         if (x != 0 || y != 0) {
6632             scrollTo(x, y);
6633         }
6634 
6635         if (transformSet) {
6636             setTranslationX(tx);
6637             setTranslationY(ty);
6638             setTranslationZ(tz);
6639             setElevation(elevation);
6640             setRotation(rotation);
6641             setRotationX(rotationX);
6642             setRotationY(rotationY);
6643             setScaleX(sx);
6644             setScaleY(sy);
6645         }
6646 
6647         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6648             setScrollContainer(true);
6649         }
6650 
6651         computeOpaqueFlags();
6652     }
6653 
6654     /**
6655      * Returns the ordered list of resource ID that are considered when resolving attribute values
6656      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6657      * XML. It will also include a set of explicit styles if specified in XML using
6658      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6659      *
6660      * <p>
6661      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6662      * is enabled in Android developer options.
6663      *
6664      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6665      * @return ordered list of resource ID that are considered when resolving attribute values for
6666      * this {@link View}.
6667      */
6668     @NonNull
6669     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6670         if (!sDebugViewAttributes
6671                 || mAttributeResolutionStacks == null
6672                 || mAttributeResolutionStacks.get(attribute) == null) {
6673             return new int[0];
6674         }
6675         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6676         int stackSize = attributeResolutionStack.length;
6677         if (mSourceLayoutId != ID_NULL) {
6678             stackSize++;
6679         }
6680 
6681         int currentIndex = 0;
6682         int[] stack = new int[stackSize];
6683 
6684         if (mSourceLayoutId != ID_NULL) {
6685             stack[currentIndex] = mSourceLayoutId;
6686             currentIndex++;
6687         }
6688         for (int i = 0; i < attributeResolutionStack.length; i++) {
6689             stack[currentIndex] = attributeResolutionStack[i];
6690             currentIndex++;
6691         }
6692         return stack;
6693     }
6694 
6695     /**
6696      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6697      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6698      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6699      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6700      *
6701      * <p>
6702      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6703      * is enabled in Android developer options.
6704      *
6705      * @return mapping of attribute resource ID to source resource ID where the attribute value
6706      * was set.
6707      */
6708     @NonNull
6709     @SuppressWarnings("AndroidFrameworkEfficientCollections")
6710     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6711         HashMap<Integer, Integer> map = new HashMap<>();
6712         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6713             return map;
6714         }
6715         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6716             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6717         }
6718         return map;
6719     }
6720 
6721     /**
6722      * Returns the resource ID for the style specified using {@code style="..."} in the
6723      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6724      * specified or otherwise not applicable.
6725      * <p>
6726      * Each {@link View} can have an explicit style specified in the layout file.
6727      * This style is used first during the {@link View} attribute resolution, then if an attribute
6728      * is not defined there the resource system looks at default style and theme as fallbacks.
6729      *
6730      * <p>
6731      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6732      * is enabled in Android developer options.
6733      *
6734      * @return The resource ID for the style specified using {@code style="..."} in the
6735      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6736      *      if not specified or otherwise not applicable.
6737      */
6738     @StyleRes
6739     public int getExplicitStyle() {
6740         if (!sDebugViewAttributes) {
6741             return ID_NULL;
6742         }
6743         return mExplicitStyle;
6744     }
6745 
6746     /**
6747      * An implementation of OnClickListener that attempts to lazily load a
6748      * named click handling method from a parent or ancestor context.
6749      */
6750     private static class DeclaredOnClickListener implements OnClickListener {
6751         private final View mHostView;
6752         private final String mMethodName;
6753 
6754         private Method mResolvedMethod;
6755         private Context mResolvedContext;
6756 
6757         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6758             mHostView = hostView;
6759             mMethodName = methodName;
6760         }
6761 
6762         @Override
6763         public void onClick(@NonNull View v) {
6764             if (mResolvedMethod == null) {
6765                 resolveMethod(mHostView.getContext(), mMethodName);
6766             }
6767 
6768             try {
6769                 mResolvedMethod.invoke(mResolvedContext, v);
6770             } catch (IllegalAccessException e) {
6771                 throw new IllegalStateException(
6772                         "Could not execute non-public method for android:onClick", e);
6773             } catch (InvocationTargetException e) {
6774                 throw new IllegalStateException(
6775                         "Could not execute method for android:onClick", e);
6776             }
6777         }
6778 
6779         @NonNull
6780         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6781             while (context != null) {
6782                 try {
6783                     if (!context.isRestricted()) {
6784                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6785                         if (method != null) {
6786                             mResolvedMethod = method;
6787                             mResolvedContext = context;
6788                             return;
6789                         }
6790                     }
6791                 } catch (NoSuchMethodException e) {
6792                     // Failed to find method, keep searching up the hierarchy.
6793                 }
6794 
6795                 if (context instanceof ContextWrapper) {
6796                     context = ((ContextWrapper) context).getBaseContext();
6797                 } else {
6798                     // Can't search up the hierarchy, null out and fail.
6799                     context = null;
6800                 }
6801             }
6802 
6803             final int id = mHostView.getId();
6804             final String idText = id == NO_ID ? "" : " with id '"
6805                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6806             throw new IllegalStateException("Could not find method " + mMethodName
6807                     + "(View) in a parent or ancestor Context for android:onClick "
6808                     + "attribute defined on view " + mHostView.getClass() + idText);
6809         }
6810     }
6811 
6812     /**
6813      * Non-public constructor for use in testing
6814      */
6815     @UnsupportedAppUsage
6816     View() {
6817         mResources = null;
6818         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6819     }
6820 
6821     /**
6822      * Returns {@code true} when the View is attached and the system developer setting to show
6823      * the layout bounds is enabled or {@code false} otherwise.
6824      */
6825     public final boolean isShowingLayoutBounds() {
6826         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6827     }
6828 
6829     /**
6830      * Used to test isShowingLayoutBounds(). This sets the local value used
6831      * by that function. This method does nothing if the layout isn't attached.
6832      *
6833      * @hide
6834      */
6835     @TestApi
6836     public final void setShowingLayoutBounds(boolean debugLayout) {
6837         if (mAttachInfo != null) {
6838             mAttachInfo.mDebugLayout = debugLayout;
6839         }
6840     }
6841 
6842     private static SparseArray<String> getAttributeMap() {
6843         if (mAttributeMap == null) {
6844             mAttributeMap = new SparseArray<>();
6845         }
6846         return mAttributeMap;
6847     }
6848 
6849     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6850             @Nullable AttributeSet attrs) {
6851         if (!sDebugViewAttributes) {
6852             return;
6853         }
6854         mExplicitStyle = theme.getExplicitStyle(attrs);
6855     }
6856 
6857     /**
6858      * Stores debugging information about attributes. This should be called in a constructor by
6859      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6860      * then the custom attributes used by this view will not be visible in layout inspection tools.
6861      *
6862      *  @param context Context under which this view is created.
6863      * @param styleable A reference to styleable array R.styleable.Foo
6864      * @param attrs AttributeSet used to construct this view.
6865      * @param t Resolved {@link TypedArray} returned by a call to
6866      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6867      * @param defStyleAttr Default style attribute passed into the view constructor.
6868      * @param defStyleRes Default style resource passed into the view constructor.
6869      */
6870     public final void saveAttributeDataForStyleable(@NonNull Context context,
6871             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6872             int defStyleAttr, int defStyleRes) {
6873         if (!sDebugViewAttributes) {
6874             return;
6875         }
6876 
6877         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6878                 defStyleAttr, defStyleRes, mExplicitStyle);
6879 
6880         if (mAttributeResolutionStacks == null) {
6881             mAttributeResolutionStacks = new SparseArray<>();
6882         }
6883 
6884         if (mAttributeSourceResId == null) {
6885             mAttributeSourceResId = new SparseIntArray();
6886         }
6887 
6888         final int indexCount = t.getIndexCount();
6889         for (int j = 0; j < indexCount; ++j) {
6890             final int index = t.getIndex(j);
6891             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6892             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6893         }
6894     }
6895 
6896     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6897         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6898         final int indexCount = t.getIndexCount();
6899         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6900 
6901         int i = 0;
6902 
6903         // Store raw XML attributes.
6904         for (int j = 0; j < attrsCount; ++j) {
6905             attributes[i] = attrs.getAttributeName(j);
6906             attributes[i + 1] = attrs.getAttributeValue(j);
6907             i += 2;
6908         }
6909 
6910         // Store resolved styleable attributes.
6911         final Resources res = t.getResources();
6912         final SparseArray<String> attributeMap = getAttributeMap();
6913         for (int j = 0; j < indexCount; ++j) {
6914             final int index = t.getIndex(j);
6915             if (!t.hasValueOrEmpty(index)) {
6916                 // Value is undefined. Skip it.
6917                 continue;
6918             }
6919 
6920             final int resourceId = t.getResourceId(index, 0);
6921             if (resourceId == 0) {
6922                 // Value is not a reference. Skip it.
6923                 continue;
6924             }
6925 
6926             String resourceName = attributeMap.get(resourceId);
6927             if (resourceName == null) {
6928                 try {
6929                     resourceName = res.getResourceName(resourceId);
6930                 } catch (Resources.NotFoundException e) {
6931                     resourceName = "0x" + Integer.toHexString(resourceId);
6932                 }
6933                 attributeMap.put(resourceId, resourceName);
6934             }
6935 
6936             attributes[i] = resourceName;
6937             attributes[i + 1] = t.getString(index);
6938             i += 2;
6939         }
6940 
6941         // Trim to fit contents.
6942         final String[] trimmed = new String[i];
6943         System.arraycopy(attributes, 0, trimmed, 0, i);
6944         mAttributes = trimmed;
6945     }
6946 
6947     @Override
6948     public String toString() {
6949         StringBuilder out = new StringBuilder(256);
6950         out.append(getClass().getName());
6951         out.append('{');
6952         out.append(Integer.toHexString(System.identityHashCode(this)));
6953         out.append(' ');
6954         switch (mViewFlags&VISIBILITY_MASK) {
6955             case VISIBLE: out.append('V'); break;
6956             case INVISIBLE: out.append('I'); break;
6957             case GONE: out.append('G'); break;
6958             default: out.append('.'); break;
6959         }
6960         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6961         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6962         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6963         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6964         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6965         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6966         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6967         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6968         out.append(' ');
6969         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6970         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6971         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6972         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6973             out.append('p');
6974         } else {
6975             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6976         }
6977         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6978         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6979         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6980         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6981         out.append(' ');
6982         out.append(mLeft);
6983         out.append(',');
6984         out.append(mTop);
6985         out.append('-');
6986         out.append(mRight);
6987         out.append(',');
6988         out.append(mBottom);
6989         appendId(out);
6990         if (mAutofillId != null) {
6991             out.append(" aid="); out.append(mAutofillId);
6992         }
6993         out.append("}");
6994         return out.toString();
6995     }
6996 
6997     void appendId(StringBuilder out) {
6998         final int id = getId();
6999         if (id != NO_ID) {
7000             out.append(" #");
7001             out.append(Integer.toHexString(id));
7002             final Resources r = mResources;
7003             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
7004                 try {
7005                     String pkgname;
7006                     switch (id&0xff000000) {
7007                         case 0x7f000000:
7008                             pkgname="app";
7009                             break;
7010                         case 0x01000000:
7011                             pkgname="android";
7012                             break;
7013                         default:
7014                             pkgname = r.getResourcePackageName(id);
7015                             break;
7016                     }
7017                     String typename = r.getResourceTypeName(id);
7018                     String entryname = r.getResourceEntryName(id);
7019                     out.append(" ");
7020                     out.append(pkgname);
7021                     out.append(":");
7022                     out.append(typename);
7023                     out.append("/");
7024                     out.append(entryname);
7025                 } catch (Resources.NotFoundException e) {
7026                 }
7027             }
7028         }
7029     }
7030 
7031     /**
7032      * <p>
7033      * Initializes the fading edges from a given set of styled attributes. This
7034      * method should be called by subclasses that need fading edges and when an
7035      * instance of these subclasses is created programmatically rather than
7036      * being inflated from XML. This method is automatically called when the XML
7037      * is inflated.
7038      * </p>
7039      *
7040      * @param a the styled attributes set to initialize the fading edges from
7041      *
7042      * @removed
7043      */
7044     protected void initializeFadingEdge(TypedArray a) {
7045         // This method probably shouldn't have been included in the SDK to begin with.
7046         // It relies on 'a' having been initialized using an attribute filter array that is
7047         // not publicly available to the SDK. The old method has been renamed
7048         // to initializeFadingEdgeInternal and hidden for framework use only;
7049         // this one initializes using defaults to make it safe to call for apps.
7050 
7051         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
7052 
7053         initializeFadingEdgeInternal(arr);
7054 
7055         arr.recycle();
7056     }
7057 
7058     /**
7059      * <p>
7060      * Initializes the fading edges from a given set of styled attributes. This
7061      * method should be called by subclasses that need fading edges and when an
7062      * instance of these subclasses is created programmatically rather than
7063      * being inflated from XML. This method is automatically called when the XML
7064      * is inflated.
7065      * </p>
7066      *
7067      * @param a the styled attributes set to initialize the fading edges from
7068      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
7069      */
7070     protected void initializeFadingEdgeInternal(TypedArray a) {
7071         initScrollCache();
7072 
7073         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
7074                 R.styleable.View_fadingEdgeLength,
7075                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
7076     }
7077 
7078     /**
7079      * Returns the size of the vertical faded edges used to indicate that more
7080      * content in this view is visible.
7081      *
7082      * @return The size in pixels of the vertical faded edge or 0 if vertical
7083      *         faded edges are not enabled for this view.
7084      * @attr ref android.R.styleable#View_fadingEdgeLength
7085      */
7086     public int getVerticalFadingEdgeLength() {
7087         if (isVerticalFadingEdgeEnabled()) {
7088             ScrollabilityCache cache = mScrollCache;
7089             if (cache != null) {
7090                 return cache.fadingEdgeLength;
7091             }
7092         }
7093         return 0;
7094     }
7095 
7096     /**
7097      * Set the size of the faded edge used to indicate that more content in this
7098      * view is available.  Will not change whether the fading edge is enabled; use
7099      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
7100      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
7101      * for the vertical or horizontal fading edges.
7102      *
7103      * @param length The size in pixels of the faded edge used to indicate that more
7104      *        content in this view is visible.
7105      */
7106     public void setFadingEdgeLength(int length) {
7107         initScrollCache();
7108         mScrollCache.fadingEdgeLength = length;
7109     }
7110 
7111     /**
7112      * Clears the request and callback previously set
7113      * through {@link View#setPendingCredentialRequest}.
7114      * Once this API is invoked, there will be no request fired to {@link CredentialManager}
7115      * on future view focus events.
7116      *
7117      * @see #setPendingCredentialRequest
7118      */
7119     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
7120     public void clearPendingCredentialRequest() {
7121         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
7122             Log.v(AUTOFILL_LOG_TAG, "clearPendingCredentialRequest called");
7123         }
7124         mViewCredentialHandler = null;
7125     }
7126 
7127     /**
7128      * Sets a {@link CredentialManager} request to retrieve credentials, when the user focuses
7129      * on this given view.
7130      *
7131      * When this view is focused, the given {@code request} will be fired to
7132      * {@link CredentialManager}, which will fetch content from all
7133      * {@link android.service.credentials.CredentialProviderService} services on the
7134      * device, and then display credential options to the user on a relevant UI
7135      * (dropdown, keyboard suggestions etc.).
7136      *
7137      * When the user selects a credential, the final {@link GetCredentialResponse} will be
7138      * propagated to the given {@code callback}. Developers are expected to handle the response
7139      * programmatically and perform a relevant action, e.g. signing in the user.
7140      *
7141      * <p> For details on how to  build a Credential Manager request, please see
7142      * {@link GetCredentialRequest}.
7143      *
7144      * <p> This API should be called at any point before the user focuses on the view, e.g. during
7145      * {@code onCreate} of an Activity.
7146      *
7147      * @param request the request to be fired when this view is entered
7148      * @param callback to be invoked when either a response or an exception needs to be
7149      *                 propagated for the given view
7150      */
7151     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
7152     public void setPendingCredentialRequest(@NonNull GetCredentialRequest request,
7153             @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
7154         Preconditions.checkNotNull(request, "request must not be null");
7155         Preconditions.checkNotNull(callback, "callback must not be null");
7156 
7157         for (CredentialOption option : request.getCredentialOptions()) {
7158             ArrayList<AutofillId> ids = option.getCandidateQueryData()
7159                     .getParcelableArrayList(
7160                             CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class);
7161             ids = ids != null ? ids : new ArrayList<>();
7162             if (!ids.contains(getAutofillId())) {
7163                 ids.add(getAutofillId());
7164             }
7165             option.getCandidateQueryData()
7166                     .putParcelableArrayList(CredentialProviderService.EXTRA_AUTOFILL_ID, ids);
7167         }
7168         mViewCredentialHandler = new ViewCredentialHandler(request, callback);
7169     }
7170 
7171     /**
7172      *
7173      * @hide
7174      */
7175     @Nullable
7176     public ViewCredentialHandler getViewCredentialHandler() {
7177         return mViewCredentialHandler;
7178     }
7179 
7180     /**
7181      * Returns the size of the horizontal faded edges used to indicate that more
7182      * content in this view is visible.
7183      *
7184      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
7185      *         faded edges are not enabled for this view.
7186      * @attr ref android.R.styleable#View_fadingEdgeLength
7187      */
7188     public int getHorizontalFadingEdgeLength() {
7189         if (isHorizontalFadingEdgeEnabled()) {
7190             ScrollabilityCache cache = mScrollCache;
7191             if (cache != null) {
7192                 return cache.fadingEdgeLength;
7193             }
7194         }
7195         return 0;
7196     }
7197 
7198     /**
7199      * Returns the width of the vertical scrollbar.
7200      *
7201      * @return The width in pixels of the vertical scrollbar or 0 if there
7202      *         is no vertical scrollbar.
7203      */
7204     public int getVerticalScrollbarWidth() {
7205         ScrollabilityCache cache = mScrollCache;
7206         if (cache != null) {
7207             ScrollBarDrawable scrollBar = cache.scrollBar;
7208             if (scrollBar != null) {
7209                 int size = scrollBar.getSize(true);
7210                 if (size <= 0) {
7211                     size = cache.scrollBarSize;
7212                 }
7213                 return size;
7214             }
7215             return 0;
7216         }
7217         return 0;
7218     }
7219 
7220     /**
7221      * Returns the height of the horizontal scrollbar.
7222      *
7223      * @return The height in pixels of the horizontal scrollbar or 0 if
7224      *         there is no horizontal scrollbar.
7225      */
7226     protected int getHorizontalScrollbarHeight() {
7227         ScrollabilityCache cache = mScrollCache;
7228         if (cache != null) {
7229             ScrollBarDrawable scrollBar = cache.scrollBar;
7230             if (scrollBar != null) {
7231                 int size = scrollBar.getSize(false);
7232                 if (size <= 0) {
7233                     size = cache.scrollBarSize;
7234                 }
7235                 return size;
7236             }
7237             return 0;
7238         }
7239         return 0;
7240     }
7241 
7242     /**
7243      * <p>
7244      * Initializes the scrollbars from a given set of styled attributes. This
7245      * method should be called by subclasses that need scrollbars and when an
7246      * instance of these subclasses is created programmatically rather than
7247      * being inflated from XML. This method is automatically called when the XML
7248      * is inflated.
7249      * </p>
7250      *
7251      * @param a the styled attributes set to initialize the scrollbars from
7252      *
7253      * @removed
7254      */
7255     protected void initializeScrollbars(TypedArray a) {
7256         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
7257         // using the View filter array which is not available to the SDK. As such, internal
7258         // framework usage now uses initializeScrollbarsInternal and we grab a default
7259         // TypedArray with the right filter instead here.
7260         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
7261 
7262         initializeScrollbarsInternal(arr);
7263 
7264         // We ignored the method parameter. Recycle the one we actually did use.
7265         arr.recycle();
7266     }
7267 
7268     private void initializeScrollBarDrawable() {
7269         initScrollCache();
7270 
7271         if (mScrollCache.scrollBar == null) {
7272             mScrollCache.scrollBar = new ScrollBarDrawable();
7273             mScrollCache.scrollBar.setState(getDrawableState());
7274             mScrollCache.scrollBar.setCallback(this);
7275         }
7276     }
7277 
7278     /**
7279      * <p>
7280      * Initializes the scrollbars from a given set of styled attributes. This
7281      * method should be called by subclasses that need scrollbars and when an
7282      * instance of these subclasses is created programmatically rather than
7283      * being inflated from XML. This method is automatically called when the XML
7284      * is inflated.
7285      * </p>
7286      *
7287      * @param a the styled attributes set to initialize the scrollbars from
7288      * @hide
7289      */
7290     @UnsupportedAppUsage
7291     protected void initializeScrollbarsInternal(TypedArray a) {
7292         initScrollCache();
7293 
7294         final ScrollabilityCache scrollabilityCache = mScrollCache;
7295 
7296         if (scrollabilityCache.scrollBar == null) {
7297             scrollabilityCache.scrollBar = new ScrollBarDrawable();
7298             scrollabilityCache.scrollBar.setState(getDrawableState());
7299             scrollabilityCache.scrollBar.setCallback(this);
7300         }
7301 
7302         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
7303 
7304         if (!fadeScrollbars) {
7305             scrollabilityCache.state = ScrollabilityCache.ON;
7306         }
7307         scrollabilityCache.fadeScrollBars = fadeScrollbars;
7308 
7309 
7310         scrollabilityCache.scrollBarFadeDuration = a.getInt(
7311                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
7312                         .getScrollBarFadeDuration());
7313         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
7314                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
7315                 ViewConfiguration.getScrollDefaultDelay());
7316 
7317 
7318         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
7319                 com.android.internal.R.styleable.View_scrollbarSize,
7320                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
7321 
7322         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
7323         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
7324 
7325         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
7326         if (thumb != null) {
7327             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
7328         }
7329 
7330         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
7331                 false);
7332         if (alwaysDraw) {
7333             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
7334         }
7335 
7336         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
7337         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
7338 
7339         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
7340         if (thumb != null) {
7341             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
7342         }
7343 
7344         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
7345                 false);
7346         if (alwaysDraw) {
7347             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
7348         }
7349 
7350         // Apply layout direction to the new Drawables if needed
7351         final int layoutDirection = getLayoutDirection();
7352         if (track != null) {
7353             track.setLayoutDirection(layoutDirection);
7354         }
7355         if (thumb != null) {
7356             thumb.setLayoutDirection(layoutDirection);
7357         }
7358 
7359         // Re-apply user/background padding so that scrollbar(s) get added
7360         resolvePadding();
7361     }
7362 
7363     /**
7364      * Defines the vertical scrollbar thumb drawable
7365      * @attr ref android.R.styleable#View_scrollbarThumbVertical
7366      *
7367      * @see #awakenScrollBars(int)
7368      * @see #isVerticalScrollBarEnabled()
7369      * @see #setVerticalScrollBarEnabled(boolean)
7370      */
7371     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
7372         initializeScrollBarDrawable();
7373         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
7374     }
7375 
7376     /**
7377      * Defines the vertical scrollbar track drawable
7378      * @attr ref android.R.styleable#View_scrollbarTrackVertical
7379      *
7380      * @see #awakenScrollBars(int)
7381      * @see #isVerticalScrollBarEnabled()
7382      * @see #setVerticalScrollBarEnabled(boolean)
7383      */
7384     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
7385         initializeScrollBarDrawable();
7386         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
7387     }
7388 
7389     /**
7390      * Defines the horizontal thumb drawable
7391      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
7392      *
7393      * @see #awakenScrollBars(int)
7394      * @see #isHorizontalScrollBarEnabled()
7395      * @see #setHorizontalScrollBarEnabled(boolean)
7396      */
7397     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
7398         initializeScrollBarDrawable();
7399         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
7400     }
7401 
7402     /**
7403      * Defines the horizontal track drawable
7404      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
7405      *
7406      * @see #awakenScrollBars(int)
7407      * @see #isHorizontalScrollBarEnabled()
7408      * @see #setHorizontalScrollBarEnabled(boolean)
7409      */
7410     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
7411         initializeScrollBarDrawable();
7412         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
7413     }
7414 
7415     /**
7416      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
7417      * exists, null otherwise.
7418      *
7419      * @see #awakenScrollBars(int)
7420      * @see #isVerticalScrollBarEnabled()
7421      * @see #setVerticalScrollBarEnabled(boolean)
7422      */
7423     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
7424         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
7425     }
7426 
7427     /**
7428      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
7429      * exists, null otherwise.
7430      *
7431      * @see #awakenScrollBars(int)
7432      * @see #isVerticalScrollBarEnabled()
7433      * @see #setVerticalScrollBarEnabled(boolean)
7434      */
7435     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
7436         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
7437     }
7438 
7439     /**
7440      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
7441      * exists, null otherwise.
7442      *
7443      * @see #awakenScrollBars(int)
7444      * @see #isHorizontalScrollBarEnabled()
7445      * @see #setHorizontalScrollBarEnabled(boolean)
7446      */
7447     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
7448         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
7449     }
7450 
7451     /**
7452      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
7453      * exists, null otherwise.
7454      *
7455      * @see #awakenScrollBars(int)
7456      * @see #isHorizontalScrollBarEnabled()
7457      * @see #setHorizontalScrollBarEnabled(boolean)
7458      */
7459     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
7460         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
7461     }
7462 
7463     private void initializeScrollIndicatorsInternal() {
7464         // Some day maybe we'll break this into top/left/start/etc. and let the
7465         // client control it. Until then, you can have any scroll indicator you
7466         // want as long as it's a 1dp foreground-colored rectangle.
7467         if (mScrollIndicatorDrawable == null) {
7468             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
7469         }
7470     }
7471 
7472     /**
7473      * <p>
7474      * Initalizes the scrollability cache if necessary.
7475      * </p>
7476      */
7477     private void initScrollCache() {
7478         if (mScrollCache == null) {
7479             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
7480         }
7481     }
7482 
7483     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
7484     private ScrollabilityCache getScrollCache() {
7485         initScrollCache();
7486         return mScrollCache;
7487     }
7488 
7489     /**
7490      * Set the position of the vertical scroll bar. Should be one of
7491      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
7492      * {@link #SCROLLBAR_POSITION_RIGHT}.
7493      *
7494      * @param position Where the vertical scroll bar should be positioned.
7495      */
7496     public void setVerticalScrollbarPosition(int position) {
7497         if (mVerticalScrollbarPosition != position) {
7498             mVerticalScrollbarPosition = position;
7499             computeOpaqueFlags();
7500             resolvePadding();
7501         }
7502     }
7503 
7504     /**
7505      * @return The position where the vertical scroll bar will show, if applicable.
7506      * @see #setVerticalScrollbarPosition(int)
7507      */
7508     public int getVerticalScrollbarPosition() {
7509         return mVerticalScrollbarPosition;
7510     }
7511 
7512     boolean isOnScrollbar(float x, float y) {
7513         if (mScrollCache == null) {
7514             return false;
7515         }
7516         x += getScrollX();
7517         y += getScrollY();
7518         final boolean canScrollVertically =
7519                 computeVerticalScrollRange() > computeVerticalScrollExtent();
7520         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
7521             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7522             getVerticalScrollBarBounds(null, touchBounds);
7523             if (touchBounds.contains((int) x, (int) y)) {
7524                 return true;
7525             }
7526         }
7527         final boolean canScrollHorizontally =
7528                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
7529         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
7530             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7531             getHorizontalScrollBarBounds(null, touchBounds);
7532             if (touchBounds.contains((int) x, (int) y)) {
7533                 return true;
7534             }
7535         }
7536         return false;
7537     }
7538 
7539     @UnsupportedAppUsage
7540     boolean isOnScrollbarThumb(float x, float y) {
7541         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
7542     }
7543 
7544     private boolean isOnVerticalScrollbarThumb(float x, float y) {
7545         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
7546             return false;
7547         }
7548         final int range = computeVerticalScrollRange();
7549         final int extent = computeVerticalScrollExtent();
7550         if (range > extent) {
7551             x += getScrollX();
7552             y += getScrollY();
7553             final Rect bounds = mScrollCache.mScrollBarBounds;
7554             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7555             getVerticalScrollBarBounds(bounds, touchBounds);
7556             final int offset = computeVerticalScrollOffset();
7557             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
7558                     extent, range);
7559             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
7560                     extent, range, offset);
7561             final int thumbTop = bounds.top + thumbOffset;
7562             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7563             if (x >= touchBounds.left && x <= touchBounds.right
7564                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
7565                 return true;
7566             }
7567         }
7568         return false;
7569     }
7570 
7571     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
7572         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
7573             return false;
7574         }
7575         final int range = computeHorizontalScrollRange();
7576         final int extent = computeHorizontalScrollExtent();
7577         if (range > extent) {
7578             x += getScrollX();
7579             y += getScrollY();
7580             final Rect bounds = mScrollCache.mScrollBarBounds;
7581             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7582             getHorizontalScrollBarBounds(bounds, touchBounds);
7583             final int offset = computeHorizontalScrollOffset();
7584 
7585             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
7586                     extent, range);
7587             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7588                     extent, range, offset);
7589             final int thumbLeft = bounds.left + thumbOffset;
7590             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7591             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7592                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7593                 return true;
7594             }
7595         }
7596         return false;
7597     }
7598 
7599     @UnsupportedAppUsage
7600     boolean isDraggingScrollBar() {
7601         return mScrollCache != null
7602                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7603     }
7604 
7605     /**
7606      * Sets the state of all scroll indicators.
7607      * <p>
7608      * See {@link #setScrollIndicators(int, int)} for usage information.
7609      *
7610      * @param indicators a bitmask of indicators that should be enabled, or
7611      *                   {@code 0} to disable all indicators
7612      * @see #setScrollIndicators(int, int)
7613      * @see #getScrollIndicators()
7614      * @attr ref android.R.styleable#View_scrollIndicators
7615      */
7616     @RemotableViewMethod
7617     public void setScrollIndicators(@ScrollIndicators int indicators) {
7618         setScrollIndicators(indicators,
7619                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7620     }
7621 
7622     /**
7623      * Sets the state of the scroll indicators specified by the mask. To change
7624      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7625      * <p>
7626      * When a scroll indicator is enabled, it will be displayed if the view
7627      * can scroll in the direction of the indicator.
7628      * <p>
7629      * Multiple indicator types may be enabled or disabled by passing the
7630      * logical OR of the desired types. If multiple types are specified, they
7631      * will all be set to the same enabled state.
7632      * <p>
7633      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7634      *
7635      * @param indicators the indicator direction, or the logical OR of multiple
7636      *             indicator directions. One or more of:
7637      *             <ul>
7638      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7639      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7640      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7641      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7642      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7643      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7644      *             </ul>
7645      * @see #setScrollIndicators(int)
7646      * @see #getScrollIndicators()
7647      * @attr ref android.R.styleable#View_scrollIndicators
7648      */
7649     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7650         // Shift and sanitize mask.
7651         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7652         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7653 
7654         // Shift and mask indicators.
7655         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7656         indicators &= mask;
7657 
7658         // Merge with non-masked flags.
7659         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7660 
7661         if (mPrivateFlags3 != updatedFlags) {
7662             mPrivateFlags3 = updatedFlags;
7663 
7664             if (indicators != 0) {
7665                 initializeScrollIndicatorsInternal();
7666             }
7667             invalidate();
7668         }
7669     }
7670 
7671     /**
7672      * Returns a bitmask representing the enabled scroll indicators.
7673      * <p>
7674      * For example, if the top and left scroll indicators are enabled and all
7675      * other indicators are disabled, the return value will be
7676      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7677      * <p>
7678      * To check whether the bottom scroll indicator is enabled, use the value
7679      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7680      *
7681      * @return a bitmask representing the enabled scroll indicators
7682      */
7683     @InspectableProperty(flagMapping = {
7684             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7685             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7686             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7687             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7688             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7689             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7690             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7691     })
7692     @ScrollIndicators
7693     public int getScrollIndicators() {
7694         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7695                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7696     }
7697 
7698     @UnsupportedAppUsage
7699     ListenerInfo getListenerInfo() {
7700         if (mListenerInfo != null) {
7701             return mListenerInfo;
7702         }
7703         mListenerInfo = new ListenerInfo();
7704         return mListenerInfo;
7705     }
7706 
7707     /**
7708      * Register a callback to be invoked when the scroll X or Y positions of
7709      * this view change.
7710      * <p>
7711      * <b>Note:</b> Some views handle scrolling independently from View and may
7712      * have their own separate listeners for scroll-type events. For example,
7713      * {@link android.widget.ListView ListView} allows clients to register an
7714      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7715      * to listen for changes in list scroll position.
7716      *
7717      * @param l The listener to notify when the scroll X or Y position changes.
7718      * @see android.view.View#getScrollX()
7719      * @see android.view.View#getScrollY()
7720      */
7721     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7722         getListenerInfo().mOnScrollChangeListener = l;
7723     }
7724 
7725     /**
7726      * Register a callback to be invoked when focus of this view changed.
7727      *
7728      * @param l The callback that will run.
7729      */
7730     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7731         getListenerInfo().mOnFocusChangeListener = l;
7732     }
7733 
7734     /**
7735      * Add a listener that will be called when the bounds of the view change due to
7736      * layout processing.
7737      *
7738      * @param listener The listener that will be called when layout bounds change.
7739      */
7740     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7741         ListenerInfo li = getListenerInfo();
7742         if (li.mOnLayoutChangeListeners == null) {
7743             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7744         }
7745         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7746             li.mOnLayoutChangeListeners.add(listener);
7747         }
7748     }
7749 
7750     /**
7751      * Remove a listener for layout changes.
7752      *
7753      * @param listener The listener for layout bounds change.
7754      */
7755     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7756         ListenerInfo li = mListenerInfo;
7757         if (li == null || li.mOnLayoutChangeListeners == null) {
7758             return;
7759         }
7760         li.mOnLayoutChangeListeners.remove(listener);
7761     }
7762 
7763     /**
7764      * Add a listener for attach state changes.
7765      *
7766      * This listener will be called whenever this view is attached or detached
7767      * from a window. Remove the listener using
7768      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7769      *
7770      * @param listener Listener to attach
7771      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7772      */
7773     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7774         ListenerInfo li = getListenerInfo();
7775         if (li.mOnAttachStateChangeListeners == null) {
7776             li.mOnAttachStateChangeListeners
7777                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7778         }
7779         li.mOnAttachStateChangeListeners.add(listener);
7780     }
7781 
7782     /**
7783      * Remove a listener for attach state changes. The listener will receive no further
7784      * notification of window attach/detach events.
7785      *
7786      * @param listener Listener to remove
7787      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7788      */
7789     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7790         ListenerInfo li = mListenerInfo;
7791         if (li == null || li.mOnAttachStateChangeListeners == null) {
7792             return;
7793         }
7794         li.mOnAttachStateChangeListeners.remove(listener);
7795     }
7796 
7797     /**
7798      * Returns the focus-change callback registered for this view.
7799      *
7800      * @return The callback, or null if one is not registered.
7801      */
7802     public OnFocusChangeListener getOnFocusChangeListener() {
7803         ListenerInfo li = mListenerInfo;
7804         return li != null ? li.mOnFocusChangeListener : null;
7805     }
7806 
7807     /**
7808      * Register a callback to be invoked when this view is clicked. If this view is not
7809      * clickable, it becomes clickable.
7810      *
7811      * @param l The callback that will run
7812      *
7813      * @see #setClickable(boolean)
7814      */
7815     public void setOnClickListener(@Nullable OnClickListener l) {
7816         if (!isClickable()) {
7817             setClickable(true);
7818         }
7819         getListenerInfo().mOnClickListener = l;
7820     }
7821 
7822     /**
7823      * Return whether this view has an attached OnClickListener.  Returns
7824      * true if there is a listener, false if there is none.
7825      */
7826     public boolean hasOnClickListeners() {
7827         ListenerInfo li = mListenerInfo;
7828         return (li != null && li.mOnClickListener != null);
7829     }
7830 
7831     /**
7832      * Register a callback to be invoked when this view is clicked and held. If this view is not
7833      * long clickable, it becomes long clickable.
7834      *
7835      * @param l The callback that will run
7836      *
7837      * @see #setLongClickable(boolean)
7838      */
7839     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7840         if (!isLongClickable()) {
7841             setLongClickable(true);
7842         }
7843         getListenerInfo().mOnLongClickListener = l;
7844     }
7845 
7846     /**
7847      * Return whether this view has an attached OnLongClickListener.  Returns
7848      * true if there is a listener, false if there is none.
7849      */
7850     public boolean hasOnLongClickListeners() {
7851         ListenerInfo li = mListenerInfo;
7852         return (li != null && li.mOnLongClickListener != null);
7853     }
7854 
7855     /**
7856      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7857      * @hide
7858      */
7859     @Nullable
7860     public OnLongClickListener getOnLongClickListener() {
7861         ListenerInfo li = mListenerInfo;
7862         return (li != null) ? li.mOnLongClickListener : null;
7863     }
7864 
7865     /**
7866      * Register a callback to be invoked when this view is context clicked. If the view is not
7867      * context clickable, it becomes context clickable.
7868      *
7869      * @param l The callback that will run
7870      * @see #setContextClickable(boolean)
7871      */
7872     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7873         if (!isContextClickable()) {
7874             setContextClickable(true);
7875         }
7876         getListenerInfo().mOnContextClickListener = l;
7877     }
7878 
7879     /**
7880      * Register a callback to be invoked when the context menu for this view is
7881      * being built. If this view is not long clickable, it becomes long clickable.
7882      *
7883      * @param l The callback that will run
7884      *
7885      */
7886     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7887         if (!isLongClickable()) {
7888             setLongClickable(true);
7889         }
7890         getListenerInfo().mOnCreateContextMenuListener = l;
7891     }
7892 
7893     /**
7894      * Set an observer to collect stats for each frame rendered for this view.
7895      *
7896      * @hide
7897      */
7898     public void addFrameMetricsListener(Window window,
7899             Window.OnFrameMetricsAvailableListener listener,
7900             Handler handler) {
7901         if (mAttachInfo != null) {
7902             if (mAttachInfo.mThreadedRenderer != null) {
7903                 if (mFrameMetricsObservers == null) {
7904                     mFrameMetricsObservers = new ArrayList<>();
7905                 }
7906 
7907                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7908                 mFrameMetricsObservers.add(fmo);
7909                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7910             } else {
7911                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7912             }
7913         } else {
7914             if (mFrameMetricsObservers == null) {
7915                 mFrameMetricsObservers = new ArrayList<>();
7916             }
7917 
7918             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7919             mFrameMetricsObservers.add(fmo);
7920         }
7921     }
7922 
7923     /**
7924      * Remove observer configured to collect frame stats for this view.
7925      *
7926      * @hide
7927      */
7928     public void removeFrameMetricsListener(
7929             Window.OnFrameMetricsAvailableListener listener) {
7930         ThreadedRenderer renderer = getThreadedRenderer();
7931         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7932         if (fmo == null) {
7933             throw new IllegalArgumentException(
7934                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7935         }
7936 
7937         if (mFrameMetricsObservers != null) {
7938             mFrameMetricsObservers.remove(fmo);
7939             if (renderer != null) {
7940                 renderer.removeObserver(fmo.getRendererObserver());
7941             }
7942         }
7943     }
7944 
7945     private void registerPendingFrameMetricsObservers() {
7946         if (mFrameMetricsObservers != null) {
7947             ThreadedRenderer renderer = getThreadedRenderer();
7948             if (renderer != null) {
7949                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7950                     renderer.addObserver(fmo.getRendererObserver());
7951                 }
7952             } else {
7953                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7954             }
7955         }
7956     }
7957 
7958     private FrameMetricsObserver findFrameMetricsObserver(
7959             Window.OnFrameMetricsAvailableListener listener) {
7960         if (mFrameMetricsObservers != null) {
7961             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7962                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7963                 if (observer.mListener == listener) {
7964                     return observer;
7965                 }
7966             }
7967         }
7968 
7969         return null;
7970     }
7971 
7972     /** @hide */
7973     public void setNotifyAutofillManagerOnClick(boolean notify) {
7974         if (notify) {
7975             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7976         } else {
7977             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7978         }
7979     }
7980 
7981     private void notifyAutofillManagerOnClick() {
7982         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7983             try {
7984                 getAutofillManager().notifyViewClicked(this);
7985             } finally {
7986                 // Set it to already called so it's not called twice when called by
7987                 // performClickInternal()
7988                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7989             }
7990         }
7991     }
7992 
7993     /**
7994      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7995      * {@code performClick()} directly to make sure the autofill manager is notified when
7996      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7997      * method).
7998      */
7999     private boolean performClickInternal() {
8000         // Must notify autofill manager before performing the click actions to avoid scenarios where
8001         // the app has a click listener that changes the state of views the autofill service might
8002         // be interested on.
8003         notifyAutofillManagerOnClick();
8004 
8005         return performClick();
8006     }
8007 
8008     /**
8009      * Call this view's OnClickListener, if it is defined.  Performs all normal
8010      * actions associated with clicking: reporting accessibility event, playing
8011      * a sound, etc.
8012      *
8013      * @return True there was an assigned OnClickListener that was called, false
8014      *         otherwise is returned.
8015      */
8016     // NOTE: other methods on View should not call this method directly, but performClickInternal()
8017     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
8018     // could extend this method without calling super.performClick()).
8019     public boolean performClick() {
8020         // We still need to call this method to handle the cases where performClick() was called
8021         // externally, instead of through performClickInternal()
8022         notifyAutofillManagerOnClick();
8023 
8024         final boolean result;
8025         final ListenerInfo li = mListenerInfo;
8026         if (li != null && li.mOnClickListener != null) {
8027             playSoundEffect(SoundEffectConstants.CLICK);
8028             li.mOnClickListener.onClick(this);
8029             result = true;
8030         } else {
8031             result = false;
8032         }
8033 
8034         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
8035 
8036         notifyEnterOrExitForAutoFillIfNeeded(true);
8037 
8038         return result;
8039     }
8040 
8041     /**
8042      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
8043      * this only calls the listener, and does not do any associated clicking
8044      * actions like reporting an accessibility event.
8045      *
8046      * @return True there was an assigned OnClickListener that was called, false
8047      *         otherwise is returned.
8048      */
8049     public boolean callOnClick() {
8050         ListenerInfo li = mListenerInfo;
8051         if (li != null && li.mOnClickListener != null) {
8052             li.mOnClickListener.onClick(this);
8053             return true;
8054         }
8055         return false;
8056     }
8057 
8058     /**
8059      * Calls this view's OnLongClickListener, if it is defined. Invokes the
8060      * context menu if the OnLongClickListener did not consume the event.
8061      *
8062      * @return {@code true} if one of the above receivers consumed the event,
8063      *         {@code false} otherwise
8064      */
8065     public boolean performLongClick() {
8066         return performLongClickInternal(mLongClickX, mLongClickY);
8067     }
8068 
8069     /**
8070      * Calls this view's OnLongClickListener, if it is defined. Invokes the
8071      * context menu if the OnLongClickListener did not consume the event,
8072      * anchoring it to an (x,y) coordinate.
8073      *
8074      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
8075      *          to disable anchoring
8076      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
8077      *          to disable anchoring
8078      * @return {@code true} if one of the above receivers consumed the event,
8079      *         {@code false} otherwise
8080      */
8081     public boolean performLongClick(float x, float y) {
8082         mLongClickX = x;
8083         mLongClickY = y;
8084         final boolean handled = performLongClick();
8085         mLongClickX = Float.NaN;
8086         mLongClickY = Float.NaN;
8087         return handled;
8088     }
8089 
8090     /**
8091      * Calls this view's OnLongClickListener, if it is defined. Invokes the
8092      * context menu if the OnLongClickListener did not consume the event,
8093      * optionally anchoring it to an (x,y) coordinate.
8094      *
8095      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
8096      *          to disable anchoring
8097      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
8098      *          to disable anchoring
8099      * @return {@code true} if one of the above receivers consumed the event,
8100      *         {@code false} otherwise
8101      */
8102     private boolean performLongClickInternal(float x, float y) {
8103         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
8104 
8105         boolean handled = false;
8106         final OnLongClickListener listener =
8107                 mListenerInfo == null ? null : mListenerInfo.mOnLongClickListener;
8108         boolean shouldPerformHapticFeedback = true;
8109         if (listener != null) {
8110             handled = listener.onLongClick(View.this);
8111             if (handled) {
8112                 shouldPerformHapticFeedback = listener.onLongClickUseDefaultHapticFeedback(
8113                         View.this);
8114             }
8115         }
8116         if (!handled) {
8117             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
8118             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
8119         }
8120         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
8121             if (!handled) {
8122                 handled = showLongClickTooltip((int) x, (int) y);
8123             }
8124         }
8125         if (handled && shouldPerformHapticFeedback) {
8126             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
8127         }
8128         return handled;
8129     }
8130 
8131     /**
8132      * Call this view's OnContextClickListener, if it is defined.
8133      *
8134      * @param x the x coordinate of the context click
8135      * @param y the y coordinate of the context click
8136      * @return True if there was an assigned OnContextClickListener that consumed the event, false
8137      *         otherwise.
8138      */
8139     public boolean performContextClick(float x, float y) {
8140         return performContextClick();
8141     }
8142 
8143     /**
8144      * Call this view's OnContextClickListener, if it is defined.
8145      *
8146      * @return True if there was an assigned OnContextClickListener that consumed the event, false
8147      *         otherwise.
8148      */
8149     public boolean performContextClick() {
8150         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
8151 
8152         boolean handled = false;
8153         ListenerInfo li = mListenerInfo;
8154         if (li != null && li.mOnContextClickListener != null) {
8155             handled = li.mOnContextClickListener.onContextClick(View.this);
8156         }
8157         if (handled) {
8158             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
8159         }
8160         return handled;
8161     }
8162 
8163     /**
8164      * Performs button-related actions during a touch down event.
8165      *
8166      * @param event The event.
8167      * @return True if the down was consumed.
8168      *
8169      * @hide
8170      */
8171     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
8172         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
8173             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
8174             showContextMenu(event.getX(), event.getY());
8175             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8176             return true;
8177         }
8178         return false;
8179     }
8180 
8181     /**
8182      * Shows the context menu for this view.
8183      *
8184      * @return {@code true} if the context menu was shown, {@code false}
8185      *         otherwise
8186      * @see #showContextMenu(float, float)
8187      */
8188     public boolean showContextMenu() {
8189         return getParent().showContextMenuForChild(this);
8190     }
8191 
8192     /**
8193      * Shows the context menu for this view anchored to the specified
8194      * view-relative coordinate.
8195      *
8196      * @param x the X coordinate in pixels relative to the view to which the
8197      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
8198      * @param y the Y coordinate in pixels relative to the view to which the
8199      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
8200      * @return {@code true} if the context menu was shown, {@code false}
8201      *         otherwise
8202      */
8203     public boolean showContextMenu(float x, float y) {
8204         return getParent().showContextMenuForChild(this, x, y);
8205     }
8206 
8207     /**
8208      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
8209      *
8210      * @param callback Callback that will control the lifecycle of the action mode
8211      * @return The new action mode if it is started, null otherwise
8212      *
8213      * @see ActionMode
8214      * @see #startActionMode(android.view.ActionMode.Callback, int)
8215      */
8216     public ActionMode startActionMode(ActionMode.Callback callback) {
8217         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
8218     }
8219 
8220     /**
8221      * Start an action mode with the given type.
8222      *
8223      * @param callback Callback that will control the lifecycle of the action mode
8224      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
8225      * @return The new action mode if it is started, null otherwise
8226      *
8227      * @see ActionMode
8228      */
8229     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
8230         ViewParent parent = getParent();
8231         if (parent == null) return null;
8232         try {
8233             return parent.startActionModeForChild(this, callback, type);
8234         } catch (AbstractMethodError ame) {
8235             // Older implementations of custom views might not implement this.
8236             return parent.startActionModeForChild(this, callback);
8237         }
8238     }
8239 
8240     /**
8241      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
8242      * Context, creating a unique View identifier to retrieve the result.
8243      *
8244      * @param intent The Intent to be started.
8245      * @param requestCode The request code to use.
8246      * @hide
8247      */
8248     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
8249     public void startActivityForResult(Intent intent, int requestCode) {
8250         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
8251         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
8252     }
8253 
8254     /**
8255      * If this View corresponds to the calling who, dispatches the activity result.
8256      * @param who The identifier for the targeted View to receive the result.
8257      * @param requestCode The integer request code originally supplied to
8258      *                    startActivityForResult(), allowing you to identify who this
8259      *                    result came from.
8260      * @param resultCode The integer result code returned by the child activity
8261      *                   through its setResult().
8262      * @param data An Intent, which can return result data to the caller
8263      *               (various data can be attached to Intent "extras").
8264      * @return {@code true} if the activity result was dispatched.
8265      * @hide
8266      */
8267     public boolean dispatchActivityResult(
8268             String who, int requestCode, int resultCode, Intent data) {
8269         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
8270             onActivityResult(requestCode, resultCode, data);
8271             mStartActivityRequestWho = null;
8272             return true;
8273         }
8274         return false;
8275     }
8276 
8277     /**
8278      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
8279      *
8280      * @param requestCode The integer request code originally supplied to
8281      *                    startActivityForResult(), allowing you to identify who this
8282      *                    result came from.
8283      * @param resultCode The integer result code returned by the child activity
8284      *                   through its setResult().
8285      * @param data An Intent, which can return result data to the caller
8286      *               (various data can be attached to Intent "extras").
8287      * @hide
8288      */
8289     public void onActivityResult(int requestCode, int resultCode, Intent data) {
8290         // Do nothing.
8291     }
8292 
8293     /**
8294      * Register a callback to be invoked when a hardware key is pressed in this view.
8295      * Key presses in software input methods will generally not trigger the methods of
8296      * this listener.
8297      * @param l the key listener to attach to this view
8298      */
8299     public void setOnKeyListener(OnKeyListener l) {
8300         getListenerInfo().mOnKeyListener = l;
8301     }
8302 
8303     /**
8304      * Register a callback to be invoked when a touch event is sent to this view.
8305      * @param l the touch listener to attach to this view
8306      */
8307     public void setOnTouchListener(OnTouchListener l) {
8308         getListenerInfo().mOnTouchListener = l;
8309     }
8310 
8311     /**
8312      * Register a callback to be invoked when a generic motion event is sent to this view.
8313      * @param l the generic motion listener to attach to this view
8314      */
8315     public void setOnGenericMotionListener(OnGenericMotionListener l) {
8316         getListenerInfo().mOnGenericMotionListener = l;
8317     }
8318 
8319     /**
8320      * Register a callback to be invoked when a hover event is sent to this view.
8321      * @param l the hover listener to attach to this view
8322      */
8323     public void setOnHoverListener(OnHoverListener l) {
8324         getListenerInfo().mOnHoverListener = l;
8325     }
8326 
8327     /**
8328      * Register a drag event listener callback object for this View. The parameter is
8329      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
8330      * View, the system calls the
8331      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
8332      * @param l An implementation of {@link android.view.View.OnDragListener}.
8333      */
8334     public void setOnDragListener(OnDragListener l) {
8335         getListenerInfo().mOnDragListener = l;
8336     }
8337 
8338     /**
8339      * Give this view focus. This will cause
8340      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
8341      *
8342      * Note: this does not check whether this {@link View} should get focus, it just
8343      * gives it focus no matter what.  It should only be called internally by framework
8344      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
8345      *
8346      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
8347      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
8348      *        focus moved when requestFocus() is called. It may not always
8349      *        apply, in which case use the default View.FOCUS_DOWN.
8350      * @param previouslyFocusedRect The rectangle of the view that had focus
8351      *        prior in this View's coordinate system.
8352      */
8353     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
8354         if (DBG) {
8355             System.out.println(this + " requestFocus()");
8356         }
8357 
8358         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
8359             mPrivateFlags |= PFLAG_FOCUSED;
8360 
8361             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
8362 
8363             if (mParent != null) {
8364                 mParent.requestChildFocus(this, this);
8365                 updateFocusedInCluster(oldFocus, direction);
8366             }
8367 
8368             if (mAttachInfo != null) {
8369                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
8370             }
8371 
8372             onFocusChanged(true, direction, previouslyFocusedRect);
8373             refreshDrawableState();
8374         }
8375     }
8376 
8377     /**
8378      * Sets this view's preference for reveal behavior when it gains focus.
8379      *
8380      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
8381      * this view would prefer to be brought fully into view when it gains focus.
8382      * For example, a text field that a user is meant to type into. Other views such
8383      * as scrolling containers may prefer to opt-out of this behavior.</p>
8384      *
8385      * <p>The default value for views is true, though subclasses may change this
8386      * based on their preferred behavior.</p>
8387      *
8388      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
8389      *
8390      * @see #getRevealOnFocusHint()
8391      */
8392     public final void setRevealOnFocusHint(boolean revealOnFocus) {
8393         if (revealOnFocus) {
8394             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
8395         } else {
8396             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
8397         }
8398     }
8399 
8400     /**
8401      * Returns this view's preference for reveal behavior when it gains focus.
8402      *
8403      * <p>When this method returns true for a child view requesting focus, ancestor
8404      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
8405      * should make a best effort to make the newly focused child fully visible to the user.
8406      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
8407      * other properties affecting visibility to the user as part of the focus change.</p>
8408      *
8409      * @return true if this view would prefer to become fully visible when it gains focus,
8410      *         false if it would prefer not to disrupt scroll positioning
8411      *
8412      * @see #setRevealOnFocusHint(boolean)
8413      */
8414     public final boolean getRevealOnFocusHint() {
8415         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
8416     }
8417 
8418     /**
8419      * Populates <code>outRect</code> with the hotspot bounds. By default,
8420      * the hotspot bounds are identical to the screen bounds.
8421      *
8422      * @param outRect rect to populate with hotspot bounds
8423      * @hide Only for internal use by views and widgets.
8424      */
8425     public void getHotspotBounds(Rect outRect) {
8426         final Drawable background = getBackground();
8427         if (background != null) {
8428             background.getHotspotBounds(outRect);
8429         } else {
8430             getBoundsOnScreen(outRect);
8431         }
8432     }
8433 
8434     /**
8435      * Request that a rectangle of this view be visible on the screen,
8436      * scrolling if necessary just enough.
8437      *
8438      * <p>A View should call this if it maintains some notion of which part
8439      * of its content is interesting.  For example, a text editing view
8440      * should call this when its cursor moves.
8441      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
8442      * It should not be affected by which part of the View is currently visible or its scroll
8443      * position.
8444      *
8445      * @param rectangle The rectangle in the View's content coordinate space
8446      * @return Whether any parent scrolled.
8447      * @see AccessibilityAction#ACTION_SHOW_ON_SCREEN
8448      */
8449     public boolean requestRectangleOnScreen(Rect rectangle) {
8450         return requestRectangleOnScreen(rectangle, false);
8451     }
8452 
8453     /**
8454      * Request that a rectangle of this view be visible on the screen,
8455      * scrolling if necessary just enough.
8456      *
8457      * <p>A View should call this if it maintains some notion of which part
8458      * of its content is interesting.  For example, a text editing view
8459      * should call this when its cursor moves.
8460      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
8461      * It should not be affected by which part of the View is currently visible or its scroll
8462      * position.
8463      * <p>When <code>immediate</code> is set to true, scrolling will not be
8464      * animated.
8465      *
8466      * @param rectangle The rectangle in the View's content coordinate space
8467      * @param immediate True to forbid animated scrolling, false otherwise
8468      * @return Whether any parent scrolled.
8469      */
8470     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
8471         if (mParent == null) {
8472             return false;
8473         }
8474 
8475         View child = this;
8476 
8477         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
8478         position.set(rectangle);
8479 
8480         ViewParent parent = mParent;
8481         boolean scrolled = false;
8482         while (parent != null) {
8483             rectangle.set((int) position.left, (int) position.top,
8484                     (int) position.right, (int) position.bottom);
8485 
8486             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
8487 
8488             if (!(parent instanceof View)) {
8489                 break;
8490             }
8491 
8492             // move it from child's content coordinate space to parent's content coordinate space
8493             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
8494 
8495             child = (View) parent;
8496             parent = child.getParent();
8497         }
8498 
8499         return scrolled;
8500     }
8501 
8502     /**
8503      * Called when this view wants to give up focus. If focus is cleared
8504      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
8505      * <p>
8506      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
8507      * to the first focusable View from the top after focus is cleared. Hence, if this
8508      * View is the first from the top that can take focus, then all callbacks
8509      * related to clearing focus will be invoked after which the framework will
8510      * give focus to this view.
8511      * </p>
8512      */
8513     public void clearFocus() {
8514         if (DBG) {
8515             System.out.println(this + " clearFocus()");
8516         }
8517 
8518         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
8519         clearFocusInternal(null, true, refocus);
8520     }
8521 
8522     /**
8523      * Clears focus from the view, optionally propagating the change up through
8524      * the parent hierarchy and requesting that the root view place new focus.
8525      *
8526      * @param propagate whether to propagate the change up through the parent
8527      *            hierarchy
8528      * @param refocus when propagate is true, specifies whether to request the
8529      *            root view place new focus
8530      * @hide
8531      */
8532     public void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
8533         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
8534             mPrivateFlags &= ~PFLAG_FOCUSED;
8535             clearParentsWantFocus();
8536 
8537             if (propagate && mParent != null) {
8538                 mParent.clearChildFocus(this);
8539             }
8540 
8541             onFocusChanged(false, 0, null);
8542             refreshDrawableState();
8543 
8544             if (propagate && (!refocus || !rootViewRequestFocus())) {
8545                 notifyGlobalFocusCleared(this);
8546             }
8547         }
8548     }
8549 
8550     void notifyGlobalFocusCleared(View oldFocus) {
8551         if (oldFocus != null && mAttachInfo != null) {
8552             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
8553         }
8554     }
8555 
8556     boolean rootViewRequestFocus() {
8557         final View root = getRootView();
8558         return root != null && root.requestFocus();
8559     }
8560 
8561     /**
8562      * Called internally by the view system when a new view is getting focus.
8563      * This is what clears the old focus.
8564      * <p>
8565      * <b>NOTE:</b> The parent view's focused child must be updated manually
8566      * after calling this method. Otherwise, the view hierarchy may be left in
8567      * an inconstent state.
8568      */
8569     void unFocus(View focused) {
8570         if (DBG) {
8571             System.out.println(this + " unFocus()");
8572         }
8573 
8574         clearFocusInternal(focused, false, false);
8575     }
8576 
8577     /**
8578      * Returns true if this view has focus itself, or is the ancestor of the
8579      * view that has focus.
8580      *
8581      * @return True if this view has or contains focus, false otherwise.
8582      */
8583     @ViewDebug.ExportedProperty(category = "focus")
8584     public boolean hasFocus() {
8585         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8586     }
8587 
8588     /**
8589      * Returns true if this view is focusable or if it contains a reachable View
8590      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
8591      * is a view whose parents do not block descendants focus.
8592      * Only {@link #VISIBLE} views are considered focusable.
8593      *
8594      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8595      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8596      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8597      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8598      * {@code false} for views not explicitly marked as focusable.
8599      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8600      * behavior.</p>
8601      *
8602      * @return {@code true} if the view is focusable or if the view contains a focusable
8603      *         view, {@code false} otherwise
8604      *
8605      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8606      * @see ViewGroup#getTouchscreenBlocksFocus()
8607      * @see #hasExplicitFocusable()
8608      */
8609     public boolean hasFocusable() {
8610         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8611     }
8612 
8613     /**
8614      * Returns true if this view is focusable or if it contains a reachable View
8615      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8616      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8617      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8618      * {@link #FOCUSABLE} are considered focusable.
8619      *
8620      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8621      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8622      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8623      * to focusable will not.</p>
8624      *
8625      * @return {@code true} if the view is focusable or if the view contains a focusable
8626      *         view, {@code false} otherwise
8627      *
8628      * @see #hasFocusable()
8629      */
8630     public boolean hasExplicitFocusable() {
8631         return hasFocusable(false, true);
8632     }
8633 
8634     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8635         if (!isFocusableInTouchMode()) {
8636             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8637                 final ViewGroup g = (ViewGroup) p;
8638                 if (g.shouldBlockFocusForTouchscreen()) {
8639                     return false;
8640                 }
8641             }
8642         }
8643 
8644         // Invisible, gone, or disabled views are never focusable.
8645         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8646                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8647             return false;
8648         }
8649 
8650         // Only use effective focusable value when allowed.
8651         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8652             return true;
8653         }
8654 
8655         return false;
8656     }
8657 
8658     /**
8659      * Called by the view system when the focus state of this view changes.
8660      * When the focus change event is caused by directional navigation, direction
8661      * and previouslyFocusedRect provide insight into where the focus is coming from.
8662      * When overriding, be sure to call up through to the super class so that
8663      * the standard focus handling will occur.
8664      *
8665      * @param gainFocus True if the View has focus; false otherwise.
8666      * @param direction The direction focus has moved when requestFocus()
8667      *                  is called to give this view focus. Values are
8668      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8669      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8670      *                  It may not always apply, in which case use the default.
8671      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8672      *        system, of the previously focused view.  If applicable, this will be
8673      *        passed in as finer grained information about where the focus is coming
8674      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8675      */
8676     @CallSuper
8677     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8678             @Nullable Rect previouslyFocusedRect) {
8679         if (DBG) {
8680             Log.d(VIEW_LOG_TAG, "onFocusChanged() entered. gainFocus: "
8681                     + gainFocus);
8682         }
8683         if (gainFocus) {
8684             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8685         } else {
8686             notifyViewAccessibilityStateChangedIfNeeded(
8687                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8688         }
8689 
8690         // Here we check whether we still need the default focus highlight, and switch it on/off.
8691         switchDefaultFocusHighlight();
8692 
8693         if (!gainFocus) {
8694             if (isPressed()) {
8695                 setPressed(false);
8696             }
8697             if (hasWindowFocus()) {
8698                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8699             }
8700             onFocusLost();
8701         } else if (hasWindowFocus()) {
8702             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8703             ViewRootImpl viewRoot = getViewRootImpl();
8704             if (viewRoot != null) {
8705                 if (mIsHandwritingDelegate) {
8706                     viewRoot.getHandwritingInitiator().onDelegateViewFocused(this);
8707                 } else if (initiationWithoutInputConnection() && onCheckIsTextEditor()) {
8708                     viewRoot.getHandwritingInitiator().onEditorFocused(this);
8709                 }
8710             }
8711         }
8712 
8713         invalidate(true);
8714         ListenerInfo li = mListenerInfo;
8715         if (li != null && li.mOnFocusChangeListener != null) {
8716             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8717         }
8718 
8719         if (mAttachInfo != null) {
8720             mAttachInfo.mKeyDispatchState.reset(this);
8721         }
8722 
8723         if (mParent != null) {
8724             mParent.onDescendantUnbufferedRequested();
8725         }
8726 
8727         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8728         updatePreferKeepClearForFocus();
8729     }
8730 
8731     /**
8732      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8733      *
8734      * @param hasFocus {@code true} when the {@link View} is being focused.
8735      */
8736     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8737         if (mAttachInfo == null) {
8738             return;
8739         }
8740         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8741     }
8742 
8743     /** @hide */
8744     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8745         if (canNotifyAutofillEnterExitEvent()) {
8746             AutofillManager afm = getAutofillManager();
8747             if (afm != null) {
8748                 if (DBG) {
8749                     Log.d(VIEW_LOG_TAG, this + " afm is not null");
8750                 }
8751                 if (enter) {
8752                     // We have not been laid out yet, hence cannot evaluate
8753                     // whether this view is visible to the user, we will do
8754                     // the evaluation once layout is complete.
8755                     // Sometimes, views are already laid out, but it's still
8756                     // not visible to the user, we also do the evaluation once
8757                     // the view is visible. ex: There is a fade-in animation
8758                     // for the activity, the view will be laid out when the
8759                     // animation beginning. On the time, the view is not visible
8760                     // to the user. And then as the animation progresses, the view
8761                     // becomes visible to the user.
8762                     if (DBG) {
8763                         Log.d(VIEW_LOG_TAG,
8764                                 "notifyEnterOrExitForAutoFillIfNeeded:"
8765                                 + " isLaidOut(): " + isLaidOut()
8766                                 + " isVisibleToUser(): " + isVisibleToUser()
8767                                 + " isFocused(): " + isFocused());
8768                     }
8769                     if (!isLaidOut() || !isVisibleToUser()) {
8770                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8771                     } else if (isVisibleToUser()) {
8772                         if (isFocused()) {
8773                             // TODO This is a potential problem that View gets focus before it's
8774                             // visible to User. Ideally View should handle the event when
8775                             // isVisibleToUser() becomes true where it should issue
8776                             // notifyViewEntered().
8777                             afm.notifyViewEntered(this);
8778                         } else {
8779                             afm.notifyViewEnteredForFillDialog(this);
8780                         }
8781                     }
8782                 } else if (!isFocused()) {
8783                     afm.notifyViewExited(this);
8784                 }
8785             }
8786         }
8787     }
8788 
8789     /**
8790      * Visually distinct portion of a window with window-like semantics are considered panes for
8791      * accessibility purposes. One example is the content view of a large fragment that is replaced.
8792      * In order for accessibility services to understand a pane's window-like behavior, panes
8793      * should have descriptive titles. Views with pane titles produce
8794      * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}s when they appear, disappear, or change
8795      * title.
8796      *
8797      * <p>
8798      * When transitioning from one Activity to another, instead of using
8799      * {@code setAccessibilityPaneTitle()}, set a descriptive title for its window by using
8800      * {@code android:label}
8801      * for the matching Activity entry in your application's manifest or updating the title at
8802      * runtime with {@link android.app.Activity#setTitle(CharSequence)}.
8803      *
8804      * <p>
8805      * <aside>
8806      * <b>Note:</b> Use
8807      * {@link androidx.core.view.ViewCompat#setAccessibilityPaneTitle(View, CharSequence)}
8808      * for backwards-compatibility.
8809      * </aside>
8810      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8811      *                               View is not a pane.
8812      *
8813      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8814      *
8815      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8816      */
8817     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8818         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8819             boolean currentPaneTitleEmpty = mAccessibilityPaneTitle == null;
8820             boolean newPaneTitleEmpty =  accessibilityPaneTitle == null;
8821             mAccessibilityPaneTitle = accessibilityPaneTitle;
8822             // Make explicitly important as nulled titles need to be important for DISAPPEARED
8823             // events.
8824             if (mAccessibilityPaneTitle != null
8825                     && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8826                 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8827             }
8828             if (currentPaneTitleEmpty) {
8829                 notifyViewAccessibilityStateChangedIfNeeded(
8830                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED);
8831             } else if (newPaneTitleEmpty) {
8832                 notifyViewAccessibilityStateChangedIfNeeded(
8833                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
8834             } else {
8835                 notifyViewAccessibilityStateChangedIfNeeded(
8836                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8837             }
8838         }
8839     }
8840 
8841     /**
8842      * Get the title of the pane for purposes of accessibility.
8843      *
8844      * @return The current pane title.
8845      *
8846      * {@see #setAccessibilityPaneTitle}.
8847      *
8848      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8849      */
8850     @InspectableProperty
8851     @Nullable
8852     public CharSequence getAccessibilityPaneTitle() {
8853         return mAccessibilityPaneTitle;
8854     }
8855 
8856     private boolean isAccessibilityPane() {
8857         return mAccessibilityPaneTitle != null;
8858     }
8859 
8860     /**
8861      * Sends an accessibility event of the given type. If accessibility is
8862      * not enabled this method has no effect. The default implementation calls
8863      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8864      * to populate information about the event source (this View), then calls
8865      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8866      * populate the text content of the event source including its descendants,
8867      * then for events type {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
8868      * and {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} with
8869      * subtype {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION},
8870      * throttle the events, and last calls
8871      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8872      * on its parent to request sending of the event to interested parties.
8873      * <p>
8874      * If an {@link AccessibilityDelegate} has been specified via calling
8875      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8876      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8877      * responsible for handling this call.
8878      * </p>
8879      * <p>
8880      * If this view uses {@link AccessibilityNodeProvider} to provide virtual view hierarchy rooted
8881      * at this view, this method should not be called to send events from virtual children because
8882      * it will populate the events with wrong information and the events should be throttled per
8883      * child instead at the virtual root level. To send events from virtual children, call
8884      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} on the view's
8885      * parent to request sending of the event to interested parties.
8886      * </p>
8887      *
8888      * @param eventType The type of the event to send, as defined by several types from
8889      * {@link AccessibilityEvent}, such as
8890      * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} or
8891      * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8892      *
8893      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8894      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8895      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8896      * @see AccessibilityDelegate
8897      */
8898     public void sendAccessibilityEvent(int eventType) {
8899         if (mAccessibilityDelegate != null) {
8900             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8901         } else {
8902             sendAccessibilityEventInternal(eventType);
8903         }
8904     }
8905 
8906     /**
8907      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8908      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8909      * specified text to its users.
8910      * <p>
8911      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8912      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8913      * accurately supplying the semantics of their UI.
8914      * They should not need to specify what exactly is announced to users.
8915      *
8916      * <p>
8917      * In general, only announce transitions and don't generate a confirmation message for simple
8918      * actions like a button press. Label your controls concisely and precisely instead, and for
8919      * significant UI changes like window changes, use
8920      * {@link android.app.Activity#setTitle(CharSequence)} and
8921      * {@link #setAccessibilityPaneTitle(CharSequence)}.
8922      *
8923      * <p>
8924      * Use {@link #setAccessibilityLiveRegion(int)} to inform the user of changes to critical
8925      * views within the user interface. These should still be used sparingly as they may generate
8926      * announcements every time a View is updated.
8927      *
8928      * <p>
8929      * For notifying users about errors, such as in a login screen with text that displays an
8930      * "incorrect password" notification, that view should send an AccessibilityEvent of type
8931      * {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR} and set
8932      * {@link AccessibilityNodeInfo#setError(CharSequence)} instead. Custom widgets should expose
8933      * error-setting methods that support accessibility automatically. For example, instead of
8934      * explicitly sending this event when using a TextView, use
8935      * {@link android.widget.TextView#setError(CharSequence)}.
8936      *
8937      * <p>
8938      * Use {@link #setStateDescription(CharSequence)} to convey state changes to views within the
8939      * user interface. While a live region may send different types of events generated by the view,
8940      * state description will send {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events of
8941      * type {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION}.
8942      *
8943      * @param text The announcement text.
8944      */
8945     public void announceForAccessibility(CharSequence text) {
8946         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8947             AccessibilityEvent event = AccessibilityEvent.obtain(
8948                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8949             onInitializeAccessibilityEvent(event);
8950             event.getText().add(text);
8951             event.setContentDescription(null);
8952             mParent.requestSendAccessibilityEvent(this, event);
8953         }
8954     }
8955 
8956     /**
8957      * @see #sendAccessibilityEvent(int)
8958      *
8959      * Note: Called from the default {@link AccessibilityDelegate}.
8960      *
8961      * @hide
8962      */
8963     public void sendAccessibilityEventInternal(int eventType) {
8964         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8965             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8966         }
8967     }
8968 
8969     /**
8970      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8971      * takes as an argument an empty {@link AccessibilityEvent} and does not
8972      * perform a check whether accessibility is enabled.
8973      * <p>
8974      * If an {@link AccessibilityDelegate} has been specified via calling
8975      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8976      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8977      * is responsible for handling this call.
8978      * </p>
8979      *
8980      * @param event The event to send.
8981      *
8982      * @see #sendAccessibilityEvent(int)
8983      */
8984     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8985         if (mAccessibilityDelegate != null) {
8986             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8987         } else {
8988             sendAccessibilityEventUncheckedInternal(event);
8989         }
8990     }
8991 
8992     /**
8993      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8994      *
8995      * Note: Called from the default {@link AccessibilityDelegate}.
8996      *
8997      * @hide
8998      */
8999     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
9000         // Panes disappearing are relevant even if though the view is no longer visible.
9001         boolean isWindowStateChanged =
9002                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
9003         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
9004                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
9005         boolean detached = detached();
9006         if (!isShown() && !isWindowDisappearedEvent && !detached) {
9007             return;
9008         }
9009         onInitializeAccessibilityEvent(event);
9010         // Only a subset of accessibility events populates text content.
9011         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
9012             dispatchPopulateAccessibilityEvent(event);
9013         }
9014         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
9015         if (throttle != null) {
9016             throttle.post(event);
9017         } else if (!isWindowDisappearedEvent && detached) {
9018             // Views could be attached soon later. Accessibility events during this temporarily
9019             // detached period should be sent too.
9020             postDelayed(() -> {
9021                 if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
9022                     requestParentSendAccessibilityEvent(event);
9023                 }
9024             }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
9025         } else {
9026             requestParentSendAccessibilityEvent(event);
9027         }
9028     }
9029 
9030     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
9031         ViewParent parent = getParent();
9032         if (parent != null) {
9033             getParent().requestSendAccessibilityEvent(this, event);
9034         }
9035     }
9036 
9037     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
9038             AccessibilityEvent event) {
9039         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
9040             if (mSendViewScrolledAccessibilityEvent == null) {
9041                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
9042             }
9043             return mSendViewScrolledAccessibilityEvent;
9044         }
9045         boolean isStateContentChanged = (event.getContentChangeTypes()
9046                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
9047         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
9048                 && isStateContentChanged) {
9049             if (mSendStateChangedAccessibilityEvent == null) {
9050                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
9051             }
9052             return mSendStateChangedAccessibilityEvent;
9053         }
9054         return null;
9055     }
9056 
9057     private void clearAccessibilityThrottles() {
9058         cancel(mSendViewScrolledAccessibilityEvent);
9059         cancel(mSendStateChangedAccessibilityEvent);
9060     }
9061 
9062     /**
9063      * Dispatches an {@link AccessibilityEvent} to the {@link View} to add the text content of the
9064      * view and its children.
9065      * <p>
9066      * <b>Note:</b> This method should only be used with event.setText().
9067      * Avoid mutating other event state in this method. In general, put UI metadata in the node for
9068      * services to easily query.
9069      * <ul>
9070      *     <li> If you are modifying other event properties, you may be eliminating semantics
9071      *     accessibility services may want. Instead, send a separate event using
9072      *     {@link #sendAccessibilityEvent(int)} and override
9073      *     {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
9074      *     </li>
9075      *     <li>If you are checking for type {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
9076      *     to generate window/title announcements, you may be causing disruptive announcements
9077      *     (or making no announcements at all). Instead, follow the practices described in
9078      *     {@link View#announceForAccessibility(CharSequence)}. <b>Note:</b> this does not suggest
9079      *     calling announceForAccessibility(), but using the suggestions listed in its
9080      *     documentation.
9081      *     </li>
9082      *     <li>If you are making changes based on the state of accessibility, such as checking for
9083      *     an event type to trigger a UI update, while well-intentioned, you are creating brittle,
9084      *     less well-maintained code that works for some users but not others. Instead, leverage
9085      *     existing code for equitable experiences and less technical debt. See
9086      *     {@link AccessibilityManager#isEnabled()} for an example.
9087      *     </li>
9088      * </ul>
9089      * <p>
9090      * Note that the event text is populated in a separate dispatch path
9091      * ({@link #onPopulateAccessibilityEvent(AccessibilityEvent)}) since we add to the
9092      * event not only the text of the source but also the text of all its descendants.
9093      * <p>
9094      * A typical implementation will call
9095      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on this view
9096      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
9097      * on each child or the first child that is visible. Override this method if custom population
9098      * of the event text content is required.
9099      *
9100      * <p>
9101      * If an {@link AccessibilityDelegate} has been specified via calling
9102      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9103      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
9104      * is responsible for handling this call.
9105      * </p>
9106      * <p>
9107      * If this view sets {@link #isAccessibilityDataSensitive()} then this view should only append
9108      * sensitive information to an event that also sets
9109      * {@link AccessibilityEvent#isAccessibilityDataSensitive()}.
9110      * </p>
9111      * <p>
9112      * <em>Note:</em> Accessibility events of certain types are not dispatched for
9113      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
9114      * </p>
9115      *
9116      * @param event The event.
9117      *
9118      * @return True if the event population was completed.
9119      */
9120     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
9121         if (mAccessibilityDelegate != null) {
9122             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
9123         } else {
9124             return dispatchPopulateAccessibilityEventInternal(event);
9125         }
9126     }
9127 
9128     /**
9129      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
9130      *
9131      * Note: Called from the default {@link AccessibilityDelegate}.
9132      *
9133      * @hide
9134      */
9135     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
9136         onPopulateAccessibilityEvent(event);
9137         return false;
9138     }
9139 
9140     /**
9141      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
9142      * giving a chance to this View to populate the accessibility event with its
9143      * text content.
9144      * <p>
9145      * <b>Note:</b> This method should only be used with event.setText().
9146      * Avoid mutating other event state in this method. Instead, follow the practices described in
9147      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}. In general, put UI
9148      * metadata in the node for services to easily query, than in transient events.
9149      * <p>
9150      * Example: Adding formatted date string to an accessibility event in addition
9151      *          to the text added by the super implementation:
9152      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
9153      *     super.onPopulateAccessibilityEvent(event);
9154      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
9155      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
9156      *         mCurrentDate.getTimeInMillis(), flags);
9157      *     event.getText().add(selectedDateUtterance);
9158      * }</pre>
9159      * <p>
9160      * If an {@link AccessibilityDelegate} has been specified via calling
9161      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9162      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
9163      * is responsible for handling this call.
9164      * </p>
9165      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
9166      * information to the event, in case the default implementation has basic information to add.
9167      * </p>
9168      *
9169      * @param event The accessibility event which to populate.
9170      *
9171      * @see #sendAccessibilityEvent(int)
9172      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
9173      */
9174     @CallSuper
9175     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
9176         if (mAccessibilityDelegate != null) {
9177             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
9178         } else {
9179             onPopulateAccessibilityEventInternal(event);
9180         }
9181     }
9182 
9183     /**
9184      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
9185      *
9186      * Note: Called from the default {@link AccessibilityDelegate}.
9187      *
9188      * @hide
9189      */
9190     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
9191         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
9192                 && isAccessibilityPane()) {
9193             event.getText().add(getAccessibilityPaneTitle());
9194         }
9195     }
9196 
9197     /**
9198      * Initializes an {@link AccessibilityEvent} with information about
9199      * this View which is the event source. In other words, the source of
9200      * an accessibility event is the view whose state change triggered firing
9201      * the event.
9202      * <p>
9203      * Example: Setting the password property of an event in addition
9204      *          to properties set by the super implementation:
9205      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
9206      *     super.onInitializeAccessibilityEvent(event);
9207      *     event.setPassword(true);
9208      * }</pre>
9209      * <p>
9210      * If an {@link AccessibilityDelegate} has been specified via calling
9211      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9212      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
9213      * is responsible for handling this call.
9214      * </p>
9215      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
9216      * information to the event, in case the default implementation has basic information to add.
9217      * </p>
9218      * @param event The event to initialize.
9219      *
9220      * @see #sendAccessibilityEvent(int)
9221      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
9222      */
9223     @CallSuper
9224     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
9225         if (mAccessibilityDelegate != null) {
9226             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
9227         } else {
9228             onInitializeAccessibilityEventInternal(event);
9229         }
9230     }
9231 
9232     /**
9233      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
9234      *
9235      * Note: Called from the default {@link AccessibilityDelegate}.
9236      *
9237      * @hide
9238      */
9239     @UnsupportedAppUsage
9240     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
9241         event.setSource(this);
9242         event.setClassName(getAccessibilityClassName());
9243         event.setPackageName(getContext().getPackageName());
9244         event.setEnabled(isEnabled());
9245         event.setContentDescription(mContentDescription);
9246         event.setScrollX(getScrollX());
9247         event.setScrollY(getScrollY());
9248 
9249         switch (event.getEventType()) {
9250             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
9251                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
9252                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
9253                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
9254                 event.setItemCount(focusablesTempList.size());
9255                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
9256                 if (mAttachInfo != null) {
9257                     focusablesTempList.clear();
9258                 }
9259             } break;
9260             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
9261                 CharSequence text = getIterableTextForAccessibility();
9262                 if (text != null && text.length() > 0) {
9263                     event.setFromIndex(getAccessibilitySelectionStart());
9264                     event.setToIndex(getAccessibilitySelectionEnd());
9265                     event.setItemCount(text.length());
9266                 }
9267             } break;
9268         }
9269     }
9270 
9271     /**
9272      * Returns an {@link AccessibilityNodeInfo} representing this view from the
9273      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
9274      * This method is responsible for obtaining an accessibility node info from a
9275      * pool of reusable instances and calling
9276      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
9277      * initialize the former.
9278      * <p>
9279      * Note: The client is responsible for recycling the obtained instance by calling
9280      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
9281      * </p>
9282      *
9283      * @return A populated {@link AccessibilityNodeInfo}.
9284      *
9285      * @see AccessibilityNodeInfo
9286      */
9287     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
9288         if (mAccessibilityDelegate != null) {
9289             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
9290         } else {
9291             return createAccessibilityNodeInfoInternal();
9292         }
9293     }
9294 
9295     /**
9296      * @see #createAccessibilityNodeInfo()
9297      *
9298      * @hide
9299      */
9300     public @Nullable AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
9301         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9302         if (provider != null) {
9303             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
9304         } else {
9305             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
9306             onInitializeAccessibilityNodeInfo(info);
9307             return info;
9308         }
9309     }
9310 
9311     /**
9312      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
9313      * The base implementation sets:
9314      * <ul>
9315      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
9316      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
9317      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
9318      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
9319      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
9320      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
9321      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
9322      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
9323      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
9324      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
9325      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
9326      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
9327      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
9328      * </ul>
9329      * <p>
9330      * Subclasses should override this method, call the super implementation,
9331      * and set additional attributes.
9332      * </p>
9333      * <p>
9334      * If an {@link AccessibilityDelegate} has been specified via calling
9335      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9336      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
9337      * is responsible for handling this call.
9338      * </p>
9339      *
9340      * @param info The instance to initialize.
9341      */
9342     @CallSuper
9343     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
9344         if (mAccessibilityDelegate != null) {
9345             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
9346         } else {
9347             onInitializeAccessibilityNodeInfoInternal(info);
9348         }
9349     }
9350 
9351     /**
9352      * Gets the location of this view in screen coordinates.
9353      *
9354      * @param outRect The output location
9355      * @hide
9356      */
9357     @UnsupportedAppUsage
9358     public void getBoundsOnScreen(Rect outRect) {
9359         getBoundsOnScreen(outRect, false);
9360     }
9361 
9362     /**
9363      * Gets the location of this view in screen coordinates.
9364      *
9365      * @param outRect The output location
9366      * @param clipToParent Whether to clip child bounds to the parent ones.
9367      * @hide
9368      */
9369     @UnsupportedAppUsage
9370     @TestApi
9371     public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
9372         if (mAttachInfo == null) {
9373             return;
9374         }
9375         RectF position = mAttachInfo.mTmpTransformRect;
9376         getBoundsToScreenInternal(position, clipToParent);
9377         outRect.set(Math.round(position.left), Math.round(position.top),
9378                 Math.round(position.right), Math.round(position.bottom));
9379         // If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
9380         // will sandbox outRect within window bounds.
9381         mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
9382     }
9383 
9384     /**
9385      * Gets the location of this view in screen coordinates.
9386      *
9387      * @param outRect The output location
9388      * @param clipToParent Whether to clip child bounds to the parent ones.
9389      * @hide
9390      */
9391     public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
9392         if (mAttachInfo == null) {
9393             return;
9394         }
9395         RectF position = mAttachInfo.mTmpTransformRect;
9396         getBoundsToScreenInternal(position, clipToParent);
9397         outRect.set(position.left, position.top, position.right, position.bottom);
9398     }
9399 
9400     /**
9401      * Gets the location of this view in window coordinates.
9402      *
9403      * @param outRect The output location
9404      * @param clipToParent Whether to clip child bounds to the parent ones.
9405      * @hide
9406      */
9407     public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
9408         if (mAttachInfo == null) {
9409             return;
9410         }
9411         RectF position = mAttachInfo.mTmpTransformRect;
9412         getBoundsToWindowInternal(position, clipToParent);
9413         outRect.set(Math.round(position.left), Math.round(position.top),
9414                 Math.round(position.right), Math.round(position.bottom));
9415     }
9416 
9417     private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
9418         position.set(0, 0, mRight - mLeft, mBottom - mTop);
9419         mapRectFromViewToScreenCoords(position, clipToParent);
9420     }
9421 
9422     private void getBoundsToWindowInternal(RectF position, boolean clipToParent) {
9423         position.set(0, 0, mRight - mLeft, mBottom - mTop);
9424         mapRectFromViewToWindowCoords(position, clipToParent);
9425     }
9426 
9427     /**
9428      * Map a rectangle from view-relative coordinates to screen-relative coordinates
9429      *
9430      * @param rect The rectangle to be mapped
9431      * @param clipToParent Whether to clip child bounds to the parent ones.
9432      * @hide
9433      */
9434     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
9435         mapRectFromViewToWindowCoords(rect, clipToParent);
9436         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
9437     }
9438 
9439     /**
9440      * Map a rectangle from view-relative coordinates to window-relative coordinates
9441      *
9442      * @param rect The rectangle to be mapped
9443      * @param clipToParent Whether to clip child bounds to the parent ones.
9444      * @hide
9445      */
9446     public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
9447         if (!hasIdentityMatrix()) {
9448             getMatrix().mapRect(rect);
9449         }
9450 
9451         rect.offset(mLeft, mTop);
9452 
9453         ViewParent parent = mParent;
9454         while (parent instanceof View) {
9455             View parentView = (View) parent;
9456 
9457             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
9458 
9459             if (clipToParent) {
9460                 rect.left = Math.max(rect.left, 0);
9461                 rect.top = Math.max(rect.top, 0);
9462                 rect.right = Math.min(rect.right, parentView.getWidth());
9463                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
9464             }
9465 
9466             if (!parentView.hasIdentityMatrix()) {
9467                 parentView.getMatrix().mapRect(rect);
9468             }
9469 
9470             rect.offset(parentView.mLeft, parentView.mTop);
9471 
9472             parent = parentView.mParent;
9473         }
9474 
9475         if (parent instanceof ViewRootImpl) {
9476             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
9477             rect.offset(0, -viewRootImpl.mCurScrollY);
9478         }
9479     }
9480 
9481     /**
9482      * Return the class name of this object to be used for accessibility purposes.
9483      * Subclasses should only override this if they are implementing something that
9484      * should be seen as a completely new class of view when used by accessibility,
9485      * unrelated to the class it is deriving from.  This is used to fill in
9486      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
9487      */
9488     public CharSequence getAccessibilityClassName() {
9489         return View.class.getName();
9490     }
9491 
9492     /**
9493      * Called when assist structure is being retrieved from a view as part of
9494      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
9495      * @param structure Fill in with structured view data.  The default implementation
9496      * fills in all data that can be inferred from the view itself.
9497      */
9498     public void onProvideStructure(ViewStructure structure) {
9499         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
9500     }
9501 
9502     /**
9503      * Populates a {@link ViewStructure} to fullfil an autofill request.
9504      *
9505      * <p>The structure should contain at least the following properties:
9506      * <ul>
9507      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
9508      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
9509      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
9510      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
9511      * </ul>
9512      *
9513      * <p>It's also recommended to set the following properties - the more properties the structure
9514      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
9515      * using the structure:
9516      *
9517      * <ul>
9518      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
9519      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
9520      *       view can only be filled with predefined values (typically used when the autofill type
9521      *       is {@link #AUTOFILL_TYPE_LIST}).
9522      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
9523      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
9524      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
9525      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
9526      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
9527      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
9528      *   <li>For views representing text fields, text properties such as the text itself
9529      *       ({@link ViewStructure#setText(CharSequence)}), text hints
9530      *       ({@link ViewStructure#setHint(CharSequence)}, input type
9531      *       ({@link ViewStructure#setInputType(int)}),
9532      *   <li>For views representing HTML nodes, its web domain
9533      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
9534      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
9535      * </ul>
9536      *
9537      * <p>The default implementation of this method already sets most of these properties based on
9538      * related {@link View} methods (for example, the autofill id is set using
9539      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
9540      * and views in the standard Android widgets library also override it to set their
9541      * relevant properties (for example, {@link android.widget.TextView} already sets the text
9542      * properties), so it's recommended to only override this method
9543      * (and call {@code super.onProvideAutofillStructure()}) when:
9544      *
9545      * <ul>
9546      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
9547      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
9548      *   <li>The view can only be autofilled with predefined options, so it can call
9549      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
9550      * </ul>
9551      *
9552      * <p><b>Note:</b> The {@code left} and {@code top} values set in
9553      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
9554      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
9555      *
9556      * <p>Views support the Autofill Framework mainly by:
9557      * <ul>
9558      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9559      *   <li>Notifying the Android System when the view value changed by calling
9560      *       {@link AutofillManager#notifyValueChanged(View)}.
9561      *   <li>Implementing the methods that autofill the view.
9562      * </ul>
9563      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
9564      * for the latter.
9565      *
9566      * @param structure fill in with structured view data for autofill purposes.
9567      * @param flags optional flags.
9568      *
9569      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9570      */
9571     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
9572         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
9573     }
9574 
9575     /**
9576      * Populates a {@link ViewStructure} for content capture.
9577      *
9578      * <p>This method is called after a view that is eligible for content capture
9579      * (for example, if it {@link #isImportantForContentCapture()}, an intelligence service is
9580      * enabled for the user, and the activity rendering the view is enabled for content capture)
9581      * is laid out and is visible. The populated structure is then passed to the service through
9582      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
9583      *
9584      * <p>The default implementation of this method sets the most relevant properties based on
9585      * related {@link View} methods, and views in the standard Android widgets library also
9586      * override it to set their relevant properties. Therefore, if overriding this method, it
9587      * is recommended to call {@code super.onProvideContentCaptureStructure()}.
9588      *
9589      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
9590      * the node representing this view and return right away, then asynchronously report (not
9591      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
9592      * changed by calling
9593      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
9594      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
9595      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
9596      * respectively. The structure for a child must be created using
9597      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
9598      * {@code autofillId} for a child can be obtained either through
9599      * {@code childStructure.getAutofillId()} or
9600      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
9601      *
9602      * <p>When the virtual view hierarchy represents a web page, you should also:
9603      *
9604      * <ul>
9605      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
9606      *   capture events should be generate for that URL.
9607      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
9608      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
9609      *   that subtree.
9610      * </ul>
9611      *
9612      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
9613      * <ul>
9614      *   <li>{@link ViewStructure#setChildCount(int)}
9615      *   <li>{@link ViewStructure#addChildCount(int)}
9616      *   <li>{@link ViewStructure#getChildCount()}
9617      *   <li>{@link ViewStructure#newChild(int)}
9618      *   <li>{@link ViewStructure#asyncNewChild(int)}
9619      *   <li>{@link ViewStructure#asyncCommit()}
9620      *   <li>{@link ViewStructure#setWebDomain(String)}
9621      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
9622      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
9623      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
9624      *   <li>{@link ViewStructure#setAlpha(float)}
9625      *   <li>{@link ViewStructure#setElevation(float)}
9626      *   <li>{@link ViewStructure#setTransformation(Matrix)}
9627      *
9628      * </ul>
9629      */
9630     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
9631         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
9632     }
9633 
9634     /** @hide */
9635     protected void onProvideStructure(@NonNull ViewStructure structure,
9636             @ViewStructureType int viewFor, int flags) {
9637         final int id = mID;
9638         if (id != NO_ID && !isViewIdGenerated(id)) {
9639             String pkg, type, entry;
9640             try {
9641                 final Resources res = getResources();
9642                 entry = res.getResourceEntryName(id);
9643                 type = res.getResourceTypeName(id);
9644                 pkg = res.getResourcePackageName(id);
9645             } catch (Resources.NotFoundException e) {
9646                 entry = type = pkg = null;
9647             }
9648             structure.setId(id, pkg, type, entry);
9649         } else {
9650             structure.setId(id, null, null, null);
9651         }
9652 
9653         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9654                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
9655             final @AutofillType int autofillType = getAutofillType();
9656             // Don't need to fill autofill info if view does not support it.
9657             // For example, only TextViews that are editable support autofill
9658             if (autofillType != AUTOFILL_TYPE_NONE) {
9659                 structure.setAutofillType(autofillType);
9660                 structure.setAutofillHints(getAutofillHints());
9661                 structure.setAutofillValue(getAutofillValue());
9662                 structure.setIsCredential(isCredential());
9663             }
9664             if (getViewCredentialHandler() != null) {
9665                 structure.setPendingCredentialRequest(
9666                         getViewCredentialHandler().getRequest(),
9667                         getViewCredentialHandler().getCallback());
9668             }
9669             structure.setImportantForAutofill(getImportantForAutofill());
9670             structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
9671         }
9672 
9673         int ignoredParentLeft = 0;
9674         int ignoredParentTop = 0;
9675         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9676                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
9677             View parentGroup = null;
9678 
9679             ViewParent viewParent = getParent();
9680             if (viewParent instanceof View) {
9681                 parentGroup = (View) viewParent;
9682             }
9683 
9684             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
9685                 ignoredParentLeft += parentGroup.mLeft - parentGroup.mScrollX;
9686                 ignoredParentTop += parentGroup.mTop - parentGroup.mScrollY;
9687 
9688                 viewParent = parentGroup.getParent();
9689                 if (viewParent instanceof View) {
9690                     parentGroup = (View) viewParent;
9691                 } else {
9692                     break;
9693                 }
9694             }
9695         }
9696 
9697         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
9698                 mRight - mLeft, mBottom - mTop);
9699         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
9700             if (!hasIdentityMatrix()) {
9701                 structure.setTransformation(getMatrix());
9702             }
9703             structure.setElevation(getZ());
9704         }
9705         structure.setVisibility(getVisibility());
9706         structure.setEnabled(isEnabled());
9707         if (isClickable()) {
9708             structure.setClickable(true);
9709         }
9710         if (isFocusable()) {
9711             structure.setFocusable(true);
9712         }
9713         if (isFocused()) {
9714             structure.setFocused(true);
9715         }
9716         if (isAccessibilityFocused()) {
9717             structure.setAccessibilityFocused(true);
9718         }
9719         if (isSelected()) {
9720             structure.setSelected(true);
9721         }
9722         if (isActivated()) {
9723             structure.setActivated(true);
9724         }
9725         if (isLongClickable()) {
9726             structure.setLongClickable(true);
9727         }
9728         if (this instanceof Checkable) {
9729             structure.setCheckable(true);
9730             if (((Checkable)this).isChecked()) {
9731                 structure.setChecked(true);
9732             }
9733         }
9734         if (isOpaque()) {
9735             structure.setOpaque(true);
9736         }
9737         if (isContextClickable()) {
9738             structure.setContextClickable(true);
9739         }
9740         structure.setClassName(getAccessibilityClassName().toString());
9741         structure.setContentDescription(getContentDescription());
9742     }
9743 
9744     /**
9745      * Called when assist structure is being retrieved from a view as part of
9746      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
9747      * generate additional virtual structure under this view.  The default implementation
9748      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
9749      * view's virtual accessibility nodes, if any.  You can override this for a more
9750      * optimal implementation providing this data.
9751      */
9752     public void onProvideVirtualStructure(ViewStructure structure) {
9753         onProvideVirtualStructureCompat(structure, false);
9754     }
9755 
9756     /**
9757      * Fallback implementation to populate a ViewStructure from accessibility state.
9758      *
9759      * @param structure The structure to populate.
9760      * @param forAutofill Whether the structure is needed for autofill.
9761      */
9762     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
9763         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9764         if (provider != null) {
9765             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9766                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
9767             }
9768             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
9769             structure.setChildCount(1);
9770             final ViewStructure root = structure.newChild(0);
9771             if (info != null) {
9772                 populateVirtualStructure(root, provider, info, forAutofill);
9773                 info.recycle();
9774             } else {
9775                 Log.w(AUTOFILL_LOG_TAG, "AccessibilityNodeInfo is null.");
9776             }
9777         }
9778     }
9779 
9780     /**
9781      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
9782      * request.
9783      *
9784      * <p>This method should be used when the view manages a virtual structure under this view. For
9785      * example, a view that draws input fields using {@link #draw(Canvas)}.
9786      *
9787      * <p>When implementing this method, subclasses must follow the rules below:
9788      *
9789      * <ul>
9790      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
9791      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
9792      *       identifying the children in the virtual structure.
9793      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
9794      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
9795      *       autofill performance.
9796      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
9797      *       children.
9798      *   <li>Set the autofill properties of the child structure as defined by
9799      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
9800      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
9801      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
9802      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
9803      *       when the focused virtual child changed.
9804      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9805      *       whether a given virtual view is visible to the user in order to support triggering
9806      *       save when all views of interest go away.
9807      *   <li>Call
9808      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9809      *       when the value of a virtual child changed.
9810      *   <li>Call {@link
9811      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9812      *       when the visibility of a virtual child changed.
9813      *   <li>Call
9814      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9815      *       child is clicked.
9816      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9817      *       changed and the current context should be committed (for example, when the user tapped
9818      *       a {@code SUBMIT} button in an HTML page).
9819      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9820      *       changed and the current context should be canceled (for example, when the user tapped
9821      *       a {@code CANCEL} button in an HTML page).
9822      *   <li>Provide ways for users to manually request autofill by calling
9823      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9824      *   <li>The {@code left} and {@code top} values set in
9825      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9826      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9827      *       structure.
9828      * </ul>
9829      *
9830      * <p>Views with virtual children support the Autofill Framework mainly by:
9831      * <ul>
9832      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9833      *       autofilled.
9834      *   <li>Implementing the methods that autofill the virtual children.
9835      * </ul>
9836      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9837      * for the latter.
9838      *
9839      * @param structure fill in with virtual children data for autofill purposes.
9840      * @param flags optional flags.
9841      *
9842      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9843      */
9844     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9845         if (mContext.isAutofillCompatibilityEnabled()) {
9846             onProvideVirtualStructureCompat(structure, true);
9847         }
9848     }
9849 
9850     /**
9851      * Sets the listener to be {@link #performReceiveContent used} to handle insertion of
9852      * content into this view.
9853      *
9854      * <p>Depending on the type of view, this listener may be invoked for different scenarios. For
9855      * example, for an editable {@link android.widget.TextView}, this listener will be invoked for
9856      * the following scenarios:
9857      * <ol>
9858      *     <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
9859      *     insertion/selection menu)
9860      *     <li>Content insertion from the keyboard (from {@link InputConnection#commitContent})
9861      *     <li>Drag and drop (drop events from {@link #onDragEvent})
9862      *     <li>Autofill
9863      *     <li>Selection replacement via {@link Intent#ACTION_PROCESS_TEXT}
9864      * </ol>
9865      *
9866      * <p>When setting a listener, clients must also declare the accepted MIME types.
9867      * The listener will still be invoked even if the MIME type of the content is not one of the
9868      * declared MIME types (e.g. if the user pastes content whose type is not one of the declared
9869      * MIME types).
9870      * In that case, the listener may reject the content (defer to the default platform behavior)
9871      * or execute some other fallback logic (e.g. show an appropriate message to the user).
9872      * The declared MIME types serve as a hint to allow different features to optionally alter
9873      * their behavior. For example, a soft keyboard may optionally choose to hide its UI for
9874      * inserting GIFs for a particular input field if the MIME types set here for that field
9875      * don't include "image/gif" or "image/*".
9876      *
9877      * <p>Note: MIME type matching in the Android framework is case-sensitive, unlike formal RFC
9878      * MIME types. As a result, you should always write your MIME types with lowercase letters,
9879      * or use {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9880      * lowercase.
9881      *
9882      * @param mimeTypes The MIME types accepted by the given listener. These may use patterns
9883      *                  such as "image/*", but may not start with a wildcard. This argument must
9884      *                  not be null or empty if a non-null listener is passed in.
9885      * @param listener The listener to use. This can be null to reset to the default behavior.
9886      */
9887     public void setOnReceiveContentListener(
9888             @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
9889             @Nullable OnReceiveContentListener listener) {
9890         if (listener != null) {
9891             Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
9892                     "When the listener is set, MIME types must also be set");
9893         }
9894         if (mimeTypes != null) {
9895             Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
9896                     "A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
9897         }
9898         mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
9899         getListenerInfo().mOnReceiveContentListener = listener;
9900     }
9901 
9902     /**
9903      * Receives the given content. If no listener is set, invokes {@link #onReceiveContent}. If a
9904      * listener is {@link #setOnReceiveContentListener set}, invokes the listener instead; if the
9905      * listener returns a non-null result, invokes {@link #onReceiveContent} to handle it.
9906      *
9907      * @param payload The content to insert and related metadata.
9908      *
9909      * @return The portion of the passed-in content that was not accepted (may be all, some, or none
9910      * of the passed-in content).
9911      */
9912     @Nullable
9913     public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
9914         final OnReceiveContentListener listener = (mListenerInfo == null) ? null
9915                 : getListenerInfo().mOnReceiveContentListener;
9916         if (listener != null) {
9917             final ContentInfo remaining = listener.onReceiveContent(this, payload);
9918             return (remaining == null) ? null : onReceiveContent(remaining);
9919         }
9920         return onReceiveContent(payload);
9921     }
9922 
9923     /**
9924      * Implements the default behavior for receiving content for this type of view. The default
9925      * view implementation is a no-op (returns the passed-in content without acting on it).
9926      *
9927      * <p>Widgets should override this method to define their default behavior for receiving
9928      * content. Apps should {@link #setOnReceiveContentListener set a listener} to provide
9929      * app-specific handling for receiving content.
9930      *
9931      * <p>See {@link #setOnReceiveContentListener} and {@link #performReceiveContent} for more info.
9932      *
9933      * @param payload The content to insert and related metadata.
9934      *
9935      * @return The portion of the passed-in content that was not handled (may be all, some, or none
9936      * of the passed-in content).
9937      */
9938     @Nullable
9939     public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
9940         return payload;
9941     }
9942 
9943     /**
9944      * Returns the MIME types accepted by {@link #performReceiveContent} for this view, as
9945      * configured via {@link #setOnReceiveContentListener}. By default returns null.
9946      *
9947      * <p>Different features (e.g. pasting from the clipboard, inserting stickers from the soft
9948      * keyboard, etc) may optionally use this metadata to conditionally alter their behavior. For
9949      * example, a soft keyboard may choose to hide its UI for inserting GIFs for a particular
9950      * input field if the MIME types returned here for that field don't include "image/gif" or
9951      * "image/*".
9952      *
9953      * <p>Note: Comparisons of MIME types should be performed using utilities such as
9954      * {@link ClipDescription#compareMimeTypes} rather than simple string equality, in order to
9955      * correctly handle patterns such as "text/*", "image/*", etc. Note that MIME type matching
9956      * in the Android framework is case-sensitive, unlike formal RFC MIME types. As a result,
9957      * you should always write your MIME types with lowercase letters, or use
9958      * {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9959      * lowercase.
9960      *
9961      * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
9962      * include patterns such as "image/*").
9963      */
9964     @SuppressLint("NullableCollection")
9965     @Nullable
9966     public String[] getReceiveContentMimeTypes() {
9967         return mReceiveContentMimeTypes;
9968     }
9969 
9970     /**
9971      * Automatically fills the content of this view with the {@code value}.
9972      *
9973      * <p>Views support the Autofill Framework mainly by:
9974      * <ul>
9975      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9976      *   <li>Implementing the methods that autofill the view.
9977      * </ul>
9978      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
9979      * this method is responsible for latter.
9980      *
9981      * <p>This method does nothing by default, but when overridden it typically:
9982      * <ol>
9983      *   <li>Checks if the provided value matches the expected type (which is defined by
9984      *       {@link #getAutofillType()}).
9985      *   <li>Checks if the view is editable - if it isn't, it should return right away.
9986      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
9987      *   <li>Pass the actual value to the equivalent setter in the view.
9988      * </ol>
9989      *
9990      * <p>For example, a text-field view could implement the method this way:
9991      *
9992      * <pre class="prettyprint">
9993      * &#64;Override
9994      * public void autofill(AutofillValue value) {
9995      *   if (!value.isText() || !this.isEditable()) {
9996      *      return;
9997      *   }
9998      *   CharSequence text = value.getTextValue();
9999      *   if (text != null) {
10000      *     this.setText(text);
10001      *   }
10002      * }
10003      * </pre>
10004      *
10005      * <p>If the value is updated asynchronously, the next call to
10006      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
10007      * changed to the autofilled value. If not, the view will not be considered autofilled.
10008      *
10009      * <p><b>Note:</b> After this method is called, the value returned by
10010      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
10011      * view will not be highlighted as autofilled.
10012      *
10013      * @param value value to be autofilled.
10014      */
10015     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
10016     }
10017 
10018     /**
10019      * Automatically fills the content of the virtual children within this view.
10020      *
10021      * <p>Views with virtual children support the Autofill Framework mainly by:
10022      * <ul>
10023      *   <li>Providing the metadata defining what the virtual children mean and how they can be
10024      *       autofilled.
10025      *   <li>Implementing the methods that autofill the virtual children.
10026      * </ul>
10027      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
10028      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
10029      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
10030      *
10031      * <p>If a child value is updated asynchronously, the next call to
10032      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
10033      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
10034      * considered autofilled.
10035      *
10036      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
10037      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
10038      * changes.
10039      *
10040      * @param values map of values to be autofilled, keyed by virtual child id.
10041      *
10042      * @attr ref android.R.styleable#Theme_autofilledHighlight
10043      */
10044     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
10045         if (!mContext.isAutofillCompatibilityEnabled()) {
10046             return;
10047         }
10048         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10049         if (provider == null) {
10050             return;
10051         }
10052         final int valueCount = values.size();
10053         for (int i = 0; i < valueCount; i++) {
10054             final AutofillValue value = values.valueAt(i);
10055             if (value.isText()) {
10056                 final int virtualId = values.keyAt(i);
10057                 final CharSequence text = value.getTextValue();
10058                 final Bundle arguments = new Bundle();
10059                 arguments.putCharSequence(
10060                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
10061                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
10062             }
10063         }
10064     }
10065 
10066     /**
10067      * @hide
10068      */
10069     public void onGetCredentialResponse(GetCredentialResponse response) {
10070         if (getPendingCredentialCallback() == null) {
10071             Log.w(AUTOFILL_LOG_TAG, "onGetCredentialResponse called but no callback found");
10072             return;
10073         }
10074         getPendingCredentialCallback().onResult(response);
10075     }
10076 
10077     /**
10078      * @hide
10079      */
10080     public void onGetCredentialException(String errorType, String errorMsg) {
10081         if (getPendingCredentialCallback() == null) {
10082             Log.w(AUTOFILL_LOG_TAG, "onGetCredentialException called but no callback found");
10083             return;
10084         }
10085         getPendingCredentialCallback().onError(new GetCredentialException(errorType, errorMsg));
10086     }
10087 
10088     /**
10089      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
10090      *
10091      * <p>The autofill id is created on demand, unless it is explicitly set by
10092      * {@link #setAutofillId(AutofillId)}.
10093      *
10094      * <p>See {@link #setAutofillId(AutofillId)} for more info.
10095      *
10096      * @return The View's autofill id.
10097      */
10098     public final AutofillId getAutofillId() {
10099         if (mAutofillId == null) {
10100             // The autofill id needs to be unique, but its value doesn't matter,
10101             // so it's better to reuse the accessibility id to save space.
10102             mAutofillId = new AutofillId(getAutofillViewId());
10103         }
10104         return mAutofillId;
10105     }
10106 
10107     /**
10108      * Returns the {@link GetCredentialRequest} associated with the view.
10109      * If the return value is null, that means no request has been set
10110      * on the view and no {@link CredentialManager} flow will be invoked
10111      * when this view is focused. Traditioanl autofill flows will still
10112      * work, autofilling content if applicable, from
10113      * the active {@link android.service.autofill.AutofillService} on
10114      * the device.
10115      *
10116      * <p>See {@link #setPendingCredentialRequest} for more info.
10117      *
10118      * @return The credential request associated with this View.
10119      */
10120     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
10121     @Nullable
10122     public final GetCredentialRequest getPendingCredentialRequest() {
10123         if (mViewCredentialHandler == null) {
10124             return null;
10125         }
10126         return mViewCredentialHandler.getRequest();
10127     }
10128 
10129 
10130     /**
10131      * Returns the callback that has previously been set up on this view through
10132      * the {@link #setPendingCredentialRequest} API.
10133      * If the return value is null, that means no callback, or request, has been set
10134      * on the view and no {@link CredentialManager} flow will be invoked
10135      * when this view is focused. Traditioanl autofill flows will still
10136      * work, and autofillable content will still be returned through the
10137      * {@link #autofill(AutofillValue)} )} API.
10138      *
10139      * <p>See {@link #setPendingCredentialRequest} for more info.
10140      *
10141      * @return The callback associated with this view that will be invoked on a response from
10142      * {@link CredentialManager} .
10143      */
10144     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
10145     @Nullable
10146     public final OutcomeReceiver<GetCredentialResponse,
10147             GetCredentialException> getPendingCredentialCallback() {
10148         if (mViewCredentialHandler == null) {
10149             return null;
10150         }
10151         return mViewCredentialHandler.getCallback();
10152     }
10153 
10154     /**
10155      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
10156      *
10157      * <p>The autofill id is created on demand, and this method should only be called when a view is
10158      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
10159      * that method creates a snapshot of the view that is passed along to the autofill service.
10160      *
10161      * <p>This method is typically used when view subtrees are recycled to represent different
10162      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
10163      * out, and restored later when it's swapped back in. For example:
10164      *
10165      * <pre>
10166      * EditText reusableView = ...;
10167      * ViewGroup parentView = ...;
10168      * AutofillManager afm = ...;
10169      *
10170      * // Swap out the view and change its contents
10171      * AutofillId oldId = reusableView.getAutofillId();
10172      * CharSequence oldText = reusableView.getText();
10173      * parentView.removeView(reusableView);
10174      * AutofillId newId = afm.getNextAutofillId();
10175      * reusableView.setText("New I am");
10176      * reusableView.setAutofillId(newId);
10177      * parentView.addView(reusableView);
10178      *
10179      * // Later, swap the old content back in
10180      * parentView.removeView(reusableView);
10181      * reusableView.setAutofillId(oldId);
10182      * reusableView.setText(oldText);
10183      * parentView.addView(reusableView);
10184      * </pre>
10185      *
10186      * <p>NOTE: If this view is a descendant of an {@link android.widget.AdapterView}, the system
10187      * may reset its autofill id when this view is recycled. If the autofill ids need to be stable,
10188      * they should be set again in
10189      * {@link android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
10190      *
10191      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
10192      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
10193      * obtained through {@link #getAutofillId()}), or a new value obtained through
10194      * {@link AutofillManager#getNextAutofillId()}.
10195      *
10196      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
10197      * a window}.
10198      *
10199      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
10200      */
10201     public void setAutofillId(@Nullable AutofillId id) {
10202         // TODO(b/37566627): add unit / CTS test for all possible combinations below
10203         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10204             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
10205         }
10206         if (isAttachedToWindow()) {
10207             throw new IllegalStateException("Cannot set autofill id when view is attached");
10208         }
10209         if (id != null && !id.isNonVirtual()) {
10210             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
10211         }
10212         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
10213             // Ignore reset because it was never explicitly set before.
10214             return;
10215         }
10216         mAutofillId = id;
10217         if (id != null) {
10218             mAutofillViewId = id.getViewId();
10219             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
10220         } else {
10221             mAutofillViewId = NO_ID;
10222             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
10223         }
10224     }
10225 
10226     /**
10227      * Forces a reset of the autofill ids of the subtree rooted at this view. Like calling
10228      * {@link #setAutofillId(AutofillId) setAutofillId(null)} for each view, but works even if the
10229      * views are attached to a window.
10230      *
10231      * <p>This is useful if the views are being recycled, since an autofill id should uniquely
10232      * identify a particular piece of content.
10233      *
10234      * @hide
10235      */
10236     public void resetSubtreeAutofillIds() {
10237         if (mAutofillViewId == NO_ID) {
10238             return;
10239         }
10240         if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10241             Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
10242         } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10243             Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
10244         }
10245         mAutofillId = null;
10246         mAutofillViewId = NO_ID;
10247         mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
10248     }
10249 
10250     /**
10251      * Describes the autofill type of this view, so an
10252      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
10253      * when autofilling the view.
10254      *
10255      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
10256      * support the Autofill Framework.
10257      *
10258      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
10259      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
10260      *
10261      * @see #onProvideAutofillStructure(ViewStructure, int)
10262      * @see #autofill(AutofillValue)
10263      */
10264     public @AutofillType int getAutofillType() {
10265         return AUTOFILL_TYPE_NONE;
10266     }
10267 
10268     /**
10269      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
10270      * to autofill the view with the user's data.
10271      *
10272      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
10273      *
10274      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
10275      * {@code null} if no hints were set.
10276      *
10277      * @attr ref android.R.styleable#View_autofillHints
10278      */
10279     @ViewDebug.ExportedProperty()
10280     @InspectableProperty
10281     @Nullable public String[] getAutofillHints() {
10282         return mAutofillHints;
10283     }
10284 
10285     /**
10286      * @hide
10287      */
10288     @TestApi
10289     public boolean isAutofilled() {
10290         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
10291     }
10292 
10293     /**
10294      * @hide
10295      */
10296     public boolean hideAutofillHighlight() {
10297         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
10298     }
10299 
10300     /**
10301      * Gets the {@link View}'s current autofill value.
10302      *
10303      * <p>By default returns {@code null}, but subclasses should override it and return an
10304      * appropriate value to properly support the Autofill Framework.
10305      *
10306      * @see #onProvideAutofillStructure(ViewStructure, int)
10307      * @see #autofill(AutofillValue)
10308      */
10309     @Nullable
10310     public AutofillValue getAutofillValue() {
10311         return null;
10312     }
10313 
10314     /**
10315      * Gets the mode for determining whether this view is important for autofill.
10316      *
10317      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
10318      * info about this mode.
10319      *
10320      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
10321      * {@link #setImportantForAutofill(int)}.
10322      *
10323      * @attr ref android.R.styleable#View_importantForAutofill
10324      */
10325     @ViewDebug.ExportedProperty(mapping = {
10326             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
10327             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
10328             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
10329             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
10330                 to = "yesExcludeDescendants"),
10331             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
10332                 to = "noExcludeDescendants")})
10333     @InspectableProperty(enumMapping = {
10334             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
10335             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
10336             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
10337             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
10338                     name = "yesExcludeDescendants"),
10339             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
10340                     name = "noExcludeDescendants"),
10341     })
10342     public @AutofillImportance int getImportantForAutofill() {
10343         return (mPrivateFlags3
10344                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
10345     }
10346 
10347     /**
10348      * Sets the mode for determining whether this view is considered important for autofill.
10349      *
10350      * <p>The platform determines the importance for autofill automatically but you
10351      * can use this method to customize the behavior. For example:
10352      *
10353      * <ol>
10354      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
10355      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
10356      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
10357      *       view of an activity containing a spreadhseet editor), it should be
10358      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
10359      *   <li>When the view content is relevant for autofill but its children aren't (for example,
10360      *       a credit card expiration date represented by a custom view that overrides the proper
10361      *       autofill methods and has 2 children representing the month and year), it should
10362      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
10363      * </ol>
10364      *
10365      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
10366      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
10367      * children) will not be used for autofill purpose; for example, when the user explicitly
10368      * makes an autofill request, all views are included in the ViewStructure, and starting in
10369      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} the system uses other factors along
10370      * with importance to determine the autofill behavior. See {@link #isImportantForAutofill()}
10371      * for more details about how the View's importance for autofill is used.
10372      *
10373      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
10374      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
10375      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
10376      *
10377      * @attr ref android.R.styleable#View_importantForAutofill
10378      */
10379     public void setImportantForAutofill(@AutofillImportance int mode) {
10380         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
10381         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
10382                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
10383     }
10384 
10385     /**
10386      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
10387      * associated with this view is considered important for autofill purposes.
10388      *
10389      * <p>Generally speaking, a view is important for autofill if:
10390      * <ol>
10391      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
10392      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
10393      *     determine how other views can be autofilled.
10394      * <ol>
10395      *
10396      * <p>For example, view containers should typically return {@code false} for performance reasons
10397      * (since the important info is provided by their children), but if its properties have relevant
10398      * information (for example, a resource id called {@code credentials}, it should return
10399      * {@code true}. On the other hand, views representing labels or editable fields should
10400      * typically return {@code true}, but in some cases they could return {@code false}
10401      * (for example, if they're part of a "Captcha" mechanism).
10402      *
10403      * <p>The value returned by this method depends on the value returned by
10404      * {@link #getImportantForAutofill()}:
10405      *
10406      * <ol>
10407      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
10408      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
10409      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
10410      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
10411      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
10412      *       that can return {@code true} in some cases (like a container with a resource id),
10413      *       but {@code false} in most.
10414      *   <li>otherwise, it returns {@code false}.
10415      * </ol>
10416      *
10417      * <p> The behavior of importances depends on Android version:
10418      * <ol>
10419      *   <li>For {@link android.os.Build.VERSION_CODES#TIRAMISU} and below:
10420      *     <ol>
10421      *       <li>When a view is considered important for autofill:
10422      *          <ol>
10423      *            <li>The view might automatically trigger an autofill request when focused on.
10424      *            <li>The contents of the view are included in the {@link ViewStructure} used in an
10425      *                autofill request.
10426      *          </ol>
10427      *        <li>On the other hand, when a view is considered not important for autofill:
10428      *          <ol>
10429      *            <li>The view never automatically triggers autofill requests, but it can trigger a
10430      *                manual request through {@link AutofillManager#requestAutofill(View)}.
10431      *            <li>The contents of the view are not included in the {@link ViewStructure} used in
10432      *                an autofill request, unless the request has the
10433      *                {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
10434      *          </ol>
10435      *      </ol>
10436      *  <li>For {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above:
10437      *    <ol>
10438      *      <li>The system uses importance, along with other view properties and other optimization
10439      *          factors, to determine if a view should trigger autofill on focus.
10440      *      <li>The contents of {@link #IMPORTANT_FOR_AUTOFILL_AUTO},
10441      *        {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@link #IMPORTANT_FOR_AUTOFILL_NO},
10442      *        {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, and
10443      *        {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} views will be included in the
10444      *        {@link ViewStructure} used in an autofill request.
10445      *    </ol>
10446      * </ol>
10447      *
10448      * @return whether the view is considered important for autofill.
10449      *
10450      * @see #setImportantForAutofill(int)
10451      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
10452      * @see #IMPORTANT_FOR_AUTOFILL_YES
10453      * @see #IMPORTANT_FOR_AUTOFILL_NO
10454      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
10455      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
10456      * @see AutofillManager#requestAutofill(View)
10457      */
10458     public final boolean isImportantForAutofill() {
10459         // Check parent mode to ensure we're not hidden.
10460         ViewParent parent = mParent;
10461         while (parent instanceof View) {
10462             final int parentImportance = ((View) parent).getImportantForAutofill();
10463             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
10464                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
10465                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10466                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
10467                             + "because parent " + parent + "'s importance is " + parentImportance);
10468                 }
10469                 return false;
10470             }
10471             parent = parent.getParent();
10472         }
10473 
10474         final int importance = getImportantForAutofill();
10475 
10476         // First, check the explicit states.
10477         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
10478                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
10479             return true;
10480         }
10481         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
10482                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
10483             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10484                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
10485                         + "because its importance is " + importance);
10486             }
10487             return false;
10488         }
10489 
10490         // Then use some heuristics to handle AUTO.
10491         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
10492             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
10493                     + this);
10494             return false;
10495         }
10496 
10497         // Always include views that have an explicit resource id.
10498         final int id = mID;
10499         if (id != NO_ID && !isViewIdGenerated(id)) {
10500             final Resources res = getResources();
10501             String entry = null;
10502             String pkg = null;
10503             try {
10504                 entry = res.getResourceEntryName(id);
10505                 pkg = res.getResourcePackageName(id);
10506             } catch (Resources.NotFoundException e) {
10507                 // ignore
10508             }
10509             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
10510                 return true;
10511             }
10512         }
10513 
10514         // If the app developer explicitly set hints for it, it's important.
10515         if (getAutofillHints() != null) {
10516             return true;
10517         }
10518 
10519         // Otherwise, assume it's not important...
10520         return false;
10521     }
10522 
10523     /**
10524      * Sets content sensitivity mode to determine whether this view displays sensitive content
10525      * (e.g. username, password etc.). The system will improve user privacy i.e. hide content
10526      * drawn by a sensitive view from screen sharing and recording.
10527      *
10528      * <p> The window hosting a sensitive view will be marked as secure during an active media
10529      * projection session. This would be equivalent to applying
10530      * {@link android.view.WindowManager.LayoutParams#FLAG_SECURE} to the window.
10531      *
10532      * @param mode {@link #CONTENT_SENSITIVITY_AUTO}, {@link #CONTENT_SENSITIVITY_NOT_SENSITIVE}
10533      *                                            or {@link #CONTENT_SENSITIVITY_SENSITIVE}
10534      */
10535     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
10536     public final void setContentSensitivity(@ContentSensitivity int mode)  {
10537         mPrivateFlags4 &= ~PFLAG4_CONTENT_SENSITIVITY_MASK;
10538         mPrivateFlags4 |= ((mode << PFLAG4_CONTENT_SENSITIVITY_SHIFT)
10539                 & PFLAG4_CONTENT_SENSITIVITY_MASK);
10540         if (sensitiveContentAppProtection()) {
10541             updateSensitiveViewsCountIfNeeded(isAggregatedVisible());
10542         }
10543     }
10544 
10545     /**
10546      * Gets content sensitivity mode to determine whether this view displays sensitive content.
10547      *
10548      * <p>See {@link #setContentSensitivity(int)} and
10549      * {@link #isContentSensitive()} for more info about this mode.
10550      *
10551      * @return {@link #CONTENT_SENSITIVITY_AUTO} by default, or value passed to
10552      * {@link #setContentSensitivity(int)}.
10553      */
10554     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
10555     public @ContentSensitivity final int getContentSensitivity() {
10556         return (mPrivateFlags4 & PFLAG4_CONTENT_SENSITIVITY_MASK)
10557                 >> PFLAG4_CONTENT_SENSITIVITY_SHIFT;
10558     }
10559 
10560     /**
10561      * Returns whether this view displays sensitive content, based
10562      * on the value explicitly set by {@link #setContentSensitivity(int)}.
10563      *
10564      * @return whether the view displays sensitive content.
10565      *
10566      * @see #setContentSensitivity(int)
10567      * @see #CONTENT_SENSITIVITY_AUTO
10568      * @see #CONTENT_SENSITIVITY_SENSITIVE
10569      * @see #CONTENT_SENSITIVITY_NOT_SENSITIVE
10570      */
10571     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
10572     public final boolean isContentSensitive() {
10573         final int contentSensitivity = getContentSensitivity();
10574         if (contentSensitivity == CONTENT_SENSITIVITY_SENSITIVE) {
10575             return true;
10576         } else if (contentSensitivity == CONTENT_SENSITIVITY_NOT_SENSITIVE) {
10577             return false;
10578         } else if (sensitiveContentAppProtection()) {
10579             return SensitiveAutofillHintsHelper
10580                     .containsSensitiveAutofillHint(getAutofillHints());
10581         }
10582         return false;
10583     }
10584 
10585     /**
10586      * Helper used to track sensitive views when they are added or removed from the window
10587      * based on whether it's laid out and visible.
10588      *
10589      * <p>This method is called from many places (visibility changed, view laid out, view attached
10590      * or detached to/from window, etc...)
10591      */
10592     private void updateSensitiveViewsCountIfNeeded(boolean appeared) {
10593         if (!sensitiveContentAppProtection() || mAttachInfo == null) {
10594             return;
10595         }
10596 
10597         if (appeared && isContentSensitive()) {
10598             if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) == 0) {
10599                 mPrivateFlags4 |= PFLAG4_IS_COUNTED_AS_SENSITIVE;
10600                 mAttachInfo.increaseSensitiveViewsCount();
10601             }
10602         } else {
10603             if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) != 0) {
10604                 mPrivateFlags4 &= ~PFLAG4_IS_COUNTED_AS_SENSITIVE;
10605                 mAttachInfo.decreaseSensitiveViewsCount();
10606             }
10607         }
10608     }
10609 
10610     /**
10611      * Gets the mode for determining whether this view is important for content capture.
10612      *
10613      * <p>See {@link #setImportantForContentCapture(int)} and
10614      * {@link #isImportantForContentCapture()} for more info about this mode.
10615      *
10616      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
10617      * {@link #setImportantForContentCapture(int)}.
10618      *
10619      * @attr ref android.R.styleable#View_importantForContentCapture
10620      */
10621     @ViewDebug.ExportedProperty(mapping = {
10622             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
10623             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
10624             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
10625             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
10626                 to = "yesExcludeDescendants"),
10627             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
10628                 to = "noExcludeDescendants")})
10629     @InspectableProperty(enumMapping = {
10630             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
10631             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
10632             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
10633             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
10634                     name = "yesExcludeDescendants"),
10635             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
10636                     name = "noExcludeDescendants"),
10637     })
10638     public @ContentCaptureImportance int getImportantForContentCapture() {
10639         // NOTE: the important for content capture values were the first flags added and are set in
10640         // the rightmost position, so we don't need to shift them
10641         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
10642     }
10643 
10644     /**
10645      * Sets the mode for determining whether this view is considered important for content capture.
10646      *
10647      * <p>The platform determines the importance for autofill automatically but you
10648      * can use this method to customize the behavior. Typically, a view that provides text should
10649      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
10650      *
10651      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
10652      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
10653      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
10654      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
10655      *
10656      * @attr ref android.R.styleable#View_importantForContentCapture
10657      */
10658     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
10659         // Reset first
10660         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
10661         // Then set again
10662         // NOTE: the important for content capture values were the first flags added and are set in
10663         // the rightmost position, so we don't need to shift them
10664         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
10665     }
10666 
10667     /**
10668      * Hints the Android System whether this view is considered important for content capture, based
10669      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
10670      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
10671      *
10672      * <p>See {@link ContentCaptureManager} for more info about content capture.
10673      *
10674      * @return whether the view is considered important for content capture.
10675      *
10676      * @see #setImportantForContentCapture(int)
10677      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
10678      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
10679      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
10680      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
10681      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10682      */
10683     public final boolean isImportantForContentCapture() {
10684         boolean isImportant;
10685         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
10686             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
10687             return isImportant;
10688         }
10689 
10690         isImportant = calculateIsImportantForContentCapture();
10691 
10692         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
10693         if (isImportant) {
10694             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
10695         }
10696         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
10697         return isImportant;
10698     }
10699 
10700     /**
10701      * Calculates whether the flag is important for content capture so it can be used by
10702      * {@link #isImportantForContentCapture()} while the tree is traversed.
10703      */
10704     private boolean calculateIsImportantForContentCapture() {
10705         // Check parent mode to ensure we're important
10706         ViewParent parent = mParent;
10707         while (parent instanceof View) {
10708             final int parentImportance = ((View) parent).getImportantForContentCapture();
10709             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10710                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
10711                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10712                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
10713                             + "content capture because parent " + parent + "'s importance is "
10714                             + parentImportance);
10715                 }
10716                 return false;
10717             }
10718             parent = parent.getParent();
10719         }
10720 
10721         final int importance = getImportantForContentCapture();
10722 
10723         // First, check the explicit states.
10724         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
10725                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
10726             return true;
10727         }
10728         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10729                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
10730             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10731                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
10732                         + "capture because its importance is " + importance);
10733             }
10734             return false;
10735         }
10736 
10737         // Then use some heuristics to handle AUTO.
10738         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
10739             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
10740                     + " on view " + this);
10741             return false;
10742         }
10743 
10744         // View group is important if at least one children also is
10745         if (this instanceof ViewGroup) {
10746             final ViewGroup group = (ViewGroup) this;
10747             for (int i = 0; i < group.getChildCount(); i++) {
10748                 final View child = group.getChildAt(i);
10749                 if (child.isImportantForContentCapture()) {
10750                     return true;
10751                 }
10752             }
10753         }
10754 
10755         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
10756         if (getAutofillHints() != null) {
10757             return true;
10758         }
10759 
10760         // Otherwise, assume it's not important...
10761         return false;
10762     }
10763 
10764     /**
10765      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
10766      * added, based on whether it's laid out and visible, and without knowing if the parent removed
10767      * it from the view hierarchy.
10768      *
10769      * <p>This method is called from many places (visibility changed, view laid out, view attached
10770      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
10771      * described below:
10772      *
10773      * <ol>
10774      *   <li>It should only be called when content capture is enabled for the view.
10775      *   <li>It must call viewAppeared() before viewDisappeared()
10776      *   <li>viewAppeared() can only be called when the view is visible and laid out
10777      *   <li>It should not call the same event twice.
10778      * </ol>
10779      */
10780     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
10781         AttachInfo ai = mAttachInfo;
10782         // Skip it while the view is being laid out for the first time
10783         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
10784 
10785         // First check if context has client, so it saves a service lookup when it doesn't
10786         if (mContext.getContentCaptureOptions() == null) return;
10787 
10788         if (appeared) {
10789             // The appeared event stops sending to AiAi.
10790             // 1. The view is hidden.
10791             // 2. The same event was sent.
10792             // 3. The view is not laid out, and it will be laid out in the future.
10793             //    Some recycled views cached its layout and a relayout is unnecessary. In this case,
10794             // system still needs to notify content capture the view appeared. When a view is
10795             // recycled, it will set the flag PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED.
10796             final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
10797                     && getVisibility() == VISIBLE
10798                     && !isLayoutRequested();
10799             if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
10800                     || !(isLaidOut() || isRecycledWithoutRelayout)) {
10801                 if (DEBUG_CONTENT_CAPTURE) {
10802                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
10803                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10804                             + ", visible=" + (getVisibility() == VISIBLE)
10805                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10806                             + ", alreadyNotifiedDisappeared="
10807                             + getNotifiedContentCaptureDisappeared());
10808                 }
10809                 return;
10810             }
10811         } else {
10812             if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
10813                 if (DEBUG_CONTENT_CAPTURE) {
10814                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
10815                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10816                             + ", visible=" + (getVisibility() == VISIBLE)
10817                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10818                             + ", alreadyNotifiedDisappeared="
10819                             + getNotifiedContentCaptureDisappeared());
10820                 }
10821                 return;
10822             }
10823         }
10824 
10825         ContentCaptureSession session = getContentCaptureSession();
10826         if (session == null) return;
10827 
10828         // ... and finally at the view level
10829         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
10830         if (!isImportantForContentCapture()) return;
10831 
10832         if (appeared) {
10833             setNotifiedContentCaptureAppeared();
10834 
10835             if (ai != null) {
10836                 makeParentImportantAndNotifyAppearedEventIfNeed();
10837                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10838             } else {
10839                 if (DEBUG_CONTENT_CAPTURE) {
10840                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
10841                 }
10842             }
10843         } else {
10844             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10845             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10846 
10847             if (ai != null) {
10848                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10849             } else {
10850                 if (DEBUG_CONTENT_CAPTURE) {
10851                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
10852                 }
10853             }
10854 
10855             // We reset any translation state as views may be re-used (e.g., as in ListView and
10856             // RecyclerView). We only need to do this for views important for content capture since
10857             // views unimportant for content capture won't be translated anyway.
10858             if (!isTemporarilyDetached()) {
10859                 clearTranslationState();
10860             }
10861         }
10862     }
10863 
10864     private void makeParentImportantAndNotifyAppearedEventIfNeed() {
10865         // If view sent the appeared event to Content Capture, Content Capture also
10866         // would like to receive its parents' appeared events. So checks its parents
10867         // whether the appeared event is sent or not. If not, send the appeared event.
10868         final ViewParent parent = getParent();
10869         if (parent instanceof View) {
10870             View p = ((View) parent);
10871             if (p.getNotifiedContentCaptureAppeared()) {
10872                 return;
10873             }
10874             // Set important for content capture in the cache.
10875             p.mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
10876             p.notifyAppearedOrDisappearedForContentCaptureIfNeeded(/* appeared */ true);
10877         }
10878     }
10879 
10880     private void setNotifiedContentCaptureAppeared() {
10881         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10882         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10883     }
10884 
10885     /** @hide */
10886     protected boolean getNotifiedContentCaptureAppeared() {
10887         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
10888     }
10889 
10890 
10891     private boolean getNotifiedContentCaptureDisappeared() {
10892         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
10893     }
10894 
10895     /**
10896      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
10897      *
10898      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
10899      * the content capture events associated with this view or its view hierarchy (if it's a
10900      * {@link ViewGroup}).
10901      *
10902      * <p>For example, if your activity is associated with a web domain, first you would need to
10903      * set the context for the main DOM:
10904      *
10905      * <pre>
10906      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
10907      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
10908      * </pre>
10909      *
10910      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
10911      *
10912      * <pre>
10913      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
10914      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
10915      *   iframeView.setContentCaptureSession(iframeSession);
10916      * </pre>
10917      *
10918      * @param contentCaptureSession a session created by
10919      * {@link ContentCaptureSession#createContentCaptureSession(
10920      *        android.view.contentcapture.ContentCaptureContext)}.
10921      */
10922     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
10923         mContentCaptureSession = contentCaptureSession;
10924     }
10925 
10926     /**
10927      * Gets the session used to notify content capture events.
10928      *
10929      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
10930      * inherited by ancestors, default session or {@code null} if content capture is disabled for
10931      * this view.
10932      */
10933     @Nullable
10934     public final ContentCaptureSession getContentCaptureSession() {
10935         if (mContentCaptureSessionCached) {
10936             return mContentCaptureSession;
10937         }
10938 
10939         mContentCaptureSession = getAndCacheContentCaptureSession();
10940         mContentCaptureSessionCached = true;
10941         return mContentCaptureSession;
10942     }
10943 
10944     @Nullable
10945     private ContentCaptureSession getAndCacheContentCaptureSession() {
10946         // First try the session explicitly set by setContentCaptureSession()
10947         if (mContentCaptureSession != null) {
10948             return mContentCaptureSession;
10949         }
10950 
10951         // Then the session explicitly set in an ancestor
10952         ContentCaptureSession session = null;
10953         if (mParent instanceof View) {
10954             session = ((View) mParent).getContentCaptureSession();
10955         }
10956 
10957         // Finally, if no session was explicitly set, use the context's default session.
10958         if (session == null) {
10959             final ContentCaptureManager ccm = mContext
10960                     .getSystemService(ContentCaptureManager.class);
10961             return ccm == null ? null : ccm.getMainContentCaptureSession();
10962         }
10963         return session;
10964     }
10965 
10966     @Nullable
10967     private AutofillManager getAutofillManager() {
10968         return mContext.getSystemService(AutofillManager.class);
10969     }
10970 
10971     /**
10972      * Check whether current activity / package is in autofill denylist.
10973      *
10974      * Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
10975      * assist structure
10976      */
10977     final boolean isActivityDeniedForAutofillForUnimportantView() {
10978         final AutofillManager afm = getAutofillManager();
10979         if (afm == null) return false;
10980         return afm.isActivityDeniedForAutofill();
10981     }
10982 
10983     /**
10984      * Check whether current view matches autofillable heuristics
10985      *
10986      * Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
10987      * assist structure
10988      */
10989     final boolean isMatchingAutofillableHeuristics() {
10990         final AutofillManager afm = getAutofillManager();
10991         if (afm == null) return false;
10992         // check the flag to see if trigger fill request on not important views is enabled
10993         return afm.isTriggerFillRequestOnUnimportantViewEnabled()
10994             ? afm.isAutofillable(this) : false;
10995     }
10996 
10997     private boolean isAutofillable() {
10998         if (DBG) {
10999             Log.d(VIEW_LOG_TAG, "isAutofillable() entered.");
11000         }
11001         if (getAutofillType() == AUTOFILL_TYPE_NONE) {
11002             if (DBG) {
11003                 Log.d(VIEW_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
11004             }
11005             return false;
11006         }
11007 
11008         final AutofillManager afm = getAutofillManager();
11009         if (afm == null) {
11010             if (DBG) {
11011                 Log.d(VIEW_LOG_TAG, "AutofillManager is null");
11012             }
11013             return false;
11014         }
11015 
11016         // Check whether view is not part of an activity. If it's not, return false.
11017         if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
11018             if (DBG) {
11019                 Log.d(VIEW_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
11020             }
11021             return false;
11022         }
11023 
11024         // If view is important and filter important view flag is turned on, or view is not
11025         // important and trigger fill request on not important view flag is turned on, then use
11026         // AutofillManager.isAutofillable() to decide whether view is autofillable instead.
11027         if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
11028                 || (!isImportantForAutofill()
11029                     && afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
11030             if (DBG) {
11031                 Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill()
11032                         + "afm.isAutofillable(): " + afm.isAutofillable(this));
11033             }
11034             return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
11035         }
11036 
11037         // If the previous condition is not met, fall back to the previous way to trigger fill
11038         // request based on autofill importance instead.
11039         if (DBG) {
11040             Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
11041         }
11042         return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
11043     }
11044 
11045     private boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
11046         final AutofillOptions options = mContext.getAutofillOptions();
11047         if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
11048             return false;
11049         }
11050         afm.notifyViewEnteredForAugmentedAutofill(this);
11051         return true;
11052     }
11053 
11054     /** @hide */
11055     public boolean canNotifyAutofillEnterExitEvent() {
11056         if (DBG) {
11057             Log.d(VIEW_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
11058                     + " isAutofillable(): " + isAutofillable()
11059                     + " isAttachedToWindow(): " + isAttachedToWindow());
11060         }
11061         return isAutofillable() && isAttachedToWindow();
11062     }
11063 
11064     private void populateVirtualStructure(ViewStructure structure,
11065             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
11066             boolean forAutofill) {
11067         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
11068                 null, null, info.getViewIdResourceName());
11069         Rect rect = structure.getTempRect();
11070         info.getBoundsInParent(rect);
11071         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
11072         structure.setVisibility(VISIBLE);
11073         structure.setEnabled(info.isEnabled());
11074         if (info.isClickable()) {
11075             structure.setClickable(true);
11076         }
11077         if (info.isFocusable()) {
11078             structure.setFocusable(true);
11079         }
11080         if (info.isFocused()) {
11081             structure.setFocused(true);
11082         }
11083         if (info.isAccessibilityFocused()) {
11084             structure.setAccessibilityFocused(true);
11085         }
11086         if (info.isSelected()) {
11087             structure.setSelected(true);
11088         }
11089         if (info.isLongClickable()) {
11090             structure.setLongClickable(true);
11091         }
11092         if (info.isCheckable()) {
11093             structure.setCheckable(true);
11094             if (info.isChecked()) {
11095                 structure.setChecked(true);
11096             }
11097         }
11098         if (info.isContextClickable()) {
11099             structure.setContextClickable(true);
11100         }
11101         if (forAutofill) {
11102             structure.setAutofillId(new AutofillId(getAutofillId(),
11103                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
11104         }
11105         if (getViewCredentialHandler() != null) {
11106             structure.setPendingCredentialRequest(
11107                     getViewCredentialHandler().getRequest(),
11108                     getViewCredentialHandler().getCallback());
11109         }
11110         CharSequence cname = info.getClassName();
11111         structure.setClassName(cname != null ? cname.toString() : null);
11112         structure.setContentDescription(info.getContentDescription());
11113         if (forAutofill) {
11114             final int maxTextLength = info.getMaxTextLength();
11115             if (maxTextLength != -1) {
11116                 structure.setMaxTextLength(maxTextLength);
11117             }
11118             structure.setHint(info.getHintText());
11119         }
11120         CharSequence text = info.getText();
11121         boolean hasText = text != null || info.getError() != null;
11122         if (hasText) {
11123             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
11124         }
11125         if (forAutofill) {
11126             if (info.isEditable()) {
11127                 structure.setDataIsSensitive(true);
11128                 if (hasText) {
11129                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
11130                     structure.setAutofillValue(AutofillValue.forText(text));
11131                 }
11132                 int inputType = info.getInputType();
11133                 if (inputType == 0 && info.isPassword()) {
11134                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
11135                 }
11136                 structure.setInputType(inputType);
11137             } else {
11138                 structure.setDataIsSensitive(false);
11139             }
11140         }
11141         final int NCHILDREN = info.getChildCount();
11142         if (NCHILDREN > 0) {
11143             structure.setChildCount(NCHILDREN);
11144             for (int i=0; i<NCHILDREN; i++) {
11145                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
11146                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
11147                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
11148                     continue;
11149                 }
11150                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
11151                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
11152                 if (cinfo != null) {
11153                     ViewStructure child = structure.newChild(i);
11154                     populateVirtualStructure(child, provider, cinfo, forAutofill);
11155                     cinfo.recycle();
11156                 }
11157             }
11158         }
11159     }
11160 
11161     /**
11162      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
11163      * implementation calls {@link #onProvideStructure} and
11164      * {@link #onProvideVirtualStructure}.
11165      */
11166     public void dispatchProvideStructure(ViewStructure structure) {
11167         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
11168     }
11169 
11170     /**
11171      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
11172      * when an Assist structure is being created as part of an autofill request.
11173      *
11174      * <p>The default implementation does the following:
11175      * <ul>
11176      *   <li>Sets the {@link AutofillId} in the structure.
11177      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
11178      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
11179      * </ul>
11180      *
11181      * <p>Typically, this method should only be overridden by subclasses that provide a view
11182      * hierarchy (such as {@link ViewGroup}) - other classes should override
11183      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
11184      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
11185      *
11186      * <p>When overridden, it must:
11187      *
11188      * <ul>
11189      *   <li>Either call
11190      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
11191      *       set the {@link AutofillId} in the structure (for example, by calling
11192      *       {@code structure.setAutofillId(getAutofillId())}).
11193      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
11194      *       set, all views in the structure should be considered important for autofill,
11195      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
11196      *       respect this flag to provide a better user experience - this flag is typically used
11197      *       when an user explicitly requested autofill. If the flag is not set,
11198      *       then only views marked as important for autofill should be included in the
11199      *       structure - skipping non-important views optimizes the overall autofill performance.
11200      * </ul>
11201      *
11202      * @param structure fill in with structured view data for autofill purposes.
11203      * @param flags optional flags.
11204      *
11205      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
11206      */
11207     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
11208             @AutofillFlags int flags) {
11209         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
11210     }
11211 
11212     private void dispatchProvideStructure(@NonNull ViewStructure structure,
11213             @ViewStructureType int viewFor, @AutofillFlags int flags) {
11214         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
11215             structure.setAutofillId(getAutofillId());
11216             onProvideAutofillStructure(structure, flags);
11217             onProvideAutofillVirtualStructure(structure, flags);
11218         } else if (!isAssistBlocked()) {
11219             onProvideStructure(structure);
11220             onProvideVirtualStructure(structure);
11221         } else {
11222             structure.setClassName(getAccessibilityClassName().toString());
11223             structure.setAssistBlocked(true);
11224         }
11225     }
11226 
11227     /**
11228      * Dispatches the initial content capture events for a view structure.
11229      *
11230      * @hide
11231      */
11232     public void dispatchInitialProvideContentCaptureStructure() {
11233         AttachInfo ai = mAttachInfo;
11234         if (ai == null) {
11235             Log.w(CONTENT_CAPTURE_LOG_TAG,
11236                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
11237             return;
11238         }
11239         ContentCaptureManager ccm = ai.mContentCaptureManager;
11240         if (ccm == null) {
11241             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
11242                     + "no ContentCaptureManager for " + this);
11243             return;
11244         }
11245 
11246         // We must set it before checkign if the view itself is important, because it might
11247         // initially not be (for example, if it's empty), although that might change later (for
11248         // example, if important views are added)
11249         ai.mReadyForContentCaptureUpdates = true;
11250 
11251         if (!isImportantForContentCapture()) {
11252             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
11253                 Log.d(CONTENT_CAPTURE_LOG_TAG,
11254                         "dispatchProvideContentCaptureStructure(): decorView is not important");
11255             }
11256             return;
11257         }
11258 
11259         ai.mContentCaptureManager = ccm;
11260 
11261         ContentCaptureSession session = getContentCaptureSession();
11262         if (session == null) {
11263             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
11264                 Log.d(CONTENT_CAPTURE_LOG_TAG,
11265                         "dispatchProvideContentCaptureStructure(): no session for " + this);
11266             }
11267             return;
11268         }
11269 
11270         session.notifyViewTreeEvent(/* started= */ true);
11271         try {
11272             dispatchProvideContentCaptureStructure();
11273         } finally {
11274             session.notifyViewTreeEvent(/* started= */ false);
11275         }
11276     }
11277 
11278     /** @hide */
11279     void dispatchProvideContentCaptureStructure() {
11280         ContentCaptureSession session = getContentCaptureSession();
11281         if (session != null) {
11282             ViewStructure structure = session.newViewStructure(this);
11283             onProvideContentCaptureStructure(structure, /* flags= */ 0);
11284             setNotifiedContentCaptureAppeared();
11285             session.notifyViewAppeared(structure);
11286         }
11287     }
11288 
11289     /**
11290      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
11291      *
11292      * Note: Called from the default {@link AccessibilityDelegate}.
11293      *
11294      * @hide
11295      */
11296     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
11297         if (mAttachInfo == null) {
11298             return;
11299         }
11300 
11301         Rect bounds = mAttachInfo.mTmpInvalRect;
11302 
11303         getDrawingRect(bounds);
11304         info.setBoundsInParent(bounds);
11305 
11306         getBoundsOnScreen(bounds, true);
11307         info.setBoundsInScreen(bounds);
11308         getBoundsInWindow(bounds, true);
11309         info.setBoundsInWindow(bounds);
11310 
11311         ViewParent parent = getParentForAccessibility();
11312         if (parent instanceof View) {
11313             info.setParent((View) parent);
11314         }
11315 
11316         if (mID != View.NO_ID) {
11317             View rootView = getRootView();
11318             if (rootView == null) {
11319                 rootView = this;
11320             }
11321 
11322             View label = rootView.findLabelForView(this, mID);
11323             if (label != null) {
11324                 info.setLabeledBy(label);
11325             }
11326 
11327             if ((mAttachInfo.mAccessibilityFetchFlags
11328                     & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS) != 0
11329                     && Resources.resourceHasPackage(mID)) {
11330                 try {
11331                     String viewId = getResources().getResourceName(mID);
11332                     info.setViewIdResourceName(viewId);
11333                 } catch (Resources.NotFoundException nfe) {
11334                     /* ignore */
11335                 }
11336             }
11337         }
11338 
11339         if (mLabelForId != View.NO_ID) {
11340             View rootView = getRootView();
11341             if (rootView == null) {
11342                 rootView = this;
11343             }
11344             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
11345             if (labeled != null) {
11346                 info.setLabelFor(labeled);
11347             }
11348         }
11349 
11350         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
11351             View rootView = getRootView();
11352             if (rootView == null) {
11353                 rootView = this;
11354             }
11355             View next = rootView.findViewInsideOutShouldExist(this,
11356                     mAccessibilityTraversalBeforeId);
11357             if (next != null && next.includeForAccessibility()) {
11358                 info.setTraversalBefore(next);
11359             }
11360         }
11361 
11362         if (mAccessibilityTraversalAfterId != View.NO_ID) {
11363             View rootView = getRootView();
11364             if (rootView == null) {
11365                 rootView = this;
11366             }
11367             View next = rootView.findViewInsideOutShouldExist(this,
11368                     mAccessibilityTraversalAfterId);
11369             if (next != null && next.includeForAccessibility()) {
11370                 info.setTraversalAfter(next);
11371             }
11372         }
11373 
11374         info.setVisibleToUser(isVisibleToUser());
11375 
11376         info.setImportantForAccessibility(isImportantForAccessibility());
11377         info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
11378         info.setPackageName(mContext.getPackageName());
11379         info.setClassName(getAccessibilityClassName());
11380         info.setStateDescription(getStateDescription());
11381         info.setContentDescription(getContentDescription());
11382 
11383         info.setEnabled(isEnabled());
11384         info.setClickable(isClickable());
11385         info.setFocusable(isFocusable());
11386         info.setScreenReaderFocusable(isScreenReaderFocusable());
11387         info.setFocused(isFocused());
11388         info.setAccessibilityFocused(isAccessibilityFocused());
11389         info.setSelected(isSelected());
11390         info.setLongClickable(isLongClickable());
11391         info.setContextClickable(isContextClickable());
11392         info.setLiveRegion(getAccessibilityLiveRegion());
11393         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
11394             info.setTooltipText(mTooltipInfo.mTooltipText);
11395             info.addAction((mTooltipInfo.mTooltipPopup == null)
11396                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
11397                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
11398         }
11399 
11400         // TODO: These make sense only if we are in an AdapterView but all
11401         // views can be selected. Maybe from accessibility perspective
11402         // we should report as selectable view in an AdapterView.
11403         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
11404         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
11405 
11406         if (isFocusable()) {
11407             if (isFocused()) {
11408                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
11409             } else {
11410                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
11411             }
11412         }
11413 
11414         if (!isAccessibilityFocused()) {
11415             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
11416         } else {
11417             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
11418         }
11419 
11420         if (isClickable() && isEnabled()) {
11421             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
11422         }
11423 
11424         if (isLongClickable() && isEnabled()) {
11425             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
11426         }
11427 
11428         if (isContextClickable() && isEnabled()) {
11429             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
11430         }
11431 
11432         CharSequence text = getIterableTextForAccessibility();
11433         if (text != null && text.length() > 0) {
11434             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
11435 
11436             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
11437             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
11438             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
11439             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
11440                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
11441                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
11442         }
11443 
11444         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
11445         populateAccessibilityNodeInfoDrawingOrderInParent(info);
11446         info.setPaneTitle(mAccessibilityPaneTitle);
11447         info.setHeading(isAccessibilityHeading());
11448 
11449         if (mTouchDelegate != null) {
11450             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
11451         }
11452 
11453         if (startedSystemDragForAccessibility()) {
11454             info.addAction(AccessibilityAction.ACTION_DRAG_CANCEL);
11455         }
11456 
11457         if (canAcceptAccessibilityDrop()) {
11458             info.addAction(AccessibilityAction.ACTION_DRAG_DROP);
11459         }
11460     }
11461 
11462 
11463     /**
11464      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
11465      * additional data.
11466      * <p>
11467      * This method only needs overloading if the node is marked as having extra data available.
11468      * </p>
11469      *
11470      * @param info The info to which to add the extra data. Never {@code null}.
11471      * @param extraDataKey A key specifying the type of extra data to add to the info. The
11472      *                     extra data should be added to the {@link Bundle} returned by
11473      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
11474      *                     {@code null}.
11475      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
11476      *                  {@code null} if the service provided no arguments.
11477      *
11478      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
11479      */
11480     public void addExtraDataToAccessibilityNodeInfo(
11481             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
11482             @Nullable Bundle arguments) {
11483     }
11484 
11485     /**
11486      * Determine the order in which this view will be drawn relative to its siblings for a11y
11487      *
11488      * @param info The info whose drawing order should be populated
11489      */
11490     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
11491         /*
11492          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
11493          * drawing order may not be well-defined, and some Views with custom drawing order may
11494          * not be initialized sufficiently to respond properly getChildDrawingOrder.
11495          */
11496         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
11497             info.setDrawingOrder(0);
11498             return;
11499         }
11500         int drawingOrderInParent = 1;
11501         // Iterate up the hierarchy if parents are not important for a11y
11502         View viewAtDrawingLevel = this;
11503         final ViewParent parent = getParentForAccessibility();
11504         while (viewAtDrawingLevel != parent) {
11505             final ViewParent currentParent = viewAtDrawingLevel.getParent();
11506             if (!(currentParent instanceof ViewGroup)) {
11507                 // Should only happen for the Decor
11508                 drawingOrderInParent = 0;
11509                 break;
11510             } else {
11511                 final ViewGroup parentGroup = (ViewGroup) currentParent;
11512                 final int childCount = parentGroup.getChildCount();
11513                 if (childCount > 1) {
11514                     List<View> preorderedList = parentGroup.buildOrderedChildList();
11515                     if (preorderedList != null) {
11516                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
11517                         for (int i = 0; i < childDrawIndex; i++) {
11518                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
11519                         }
11520                         preorderedList.clear();
11521                     } else {
11522                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
11523                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
11524                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
11525                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
11526                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
11527                         if (childDrawIndex != 0) {
11528                             for (int i = 0; i < numChildrenToIterate; i++) {
11529                                 final int otherDrawIndex = (customOrder ?
11530                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
11531                                 if (otherDrawIndex < childDrawIndex) {
11532                                     drawingOrderInParent +=
11533                                             numViewsForAccessibility(parentGroup.getChildAt(i));
11534                                 }
11535                             }
11536                         }
11537                     }
11538                 }
11539             }
11540             viewAtDrawingLevel = (View) currentParent;
11541         }
11542         info.setDrawingOrder(drawingOrderInParent);
11543     }
11544 
11545     private static int numViewsForAccessibility(View view) {
11546         if (view != null) {
11547             if (view.includeForAccessibility()) {
11548                 return 1;
11549             } else if (view instanceof ViewGroup) {
11550                 return ((ViewGroup) view).getNumChildrenForAccessibility();
11551             }
11552         }
11553         return 0;
11554     }
11555 
11556     private View findLabelForView(View view, int labeledId) {
11557         if (mMatchLabelForPredicate == null) {
11558             mMatchLabelForPredicate = new MatchLabelForPredicate();
11559         }
11560         mMatchLabelForPredicate.mLabeledId = labeledId;
11561         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
11562     }
11563 
11564     /**
11565      * Computes whether this virtual autofill view is visible to the user.
11566      *
11567      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
11568      * view must override it.
11569      *
11570      * @return Whether the view is visible on the screen.
11571      */
11572     public boolean isVisibleToUserForAutofill(int virtualId) {
11573         if (mContext.isAutofillCompatibilityEnabled()) {
11574             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
11575             if (provider != null) {
11576                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
11577                 if (node != null) {
11578                     return node.isVisibleToUser();
11579                 }
11580                 // if node is null, assume it's not visible anymore
11581             } else {
11582                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
11583             }
11584             return false;
11585         }
11586         return true;
11587     }
11588 
11589     /**
11590      * Computes whether this view is visible to the user. Such a view is
11591      * attached, visible, all its predecessors are visible, it is not clipped
11592      * entirely by its predecessors, and has an alpha greater than zero.
11593      *
11594      * @return Whether the view is visible on the screen.
11595      *
11596      * @hide
11597      */
11598     @UnsupportedAppUsage
11599     public boolean isVisibleToUser() {
11600         return isVisibleToUser(null);
11601     }
11602 
11603     /**
11604      * Computes whether the given portion of this view is visible to the user.
11605      * Such a view is attached, visible, all its predecessors are visible,
11606      * has an alpha greater than zero, and the specified portion is not
11607      * clipped entirely by its predecessors.
11608      *
11609      * @param boundInView the portion of the view to test; coordinates should be relative; may be
11610      *                    <code>null</code>, and the entire view will be tested in this case.
11611      *                    When <code>true</code> is returned by the function, the actual visible
11612      *                    region will be stored in this parameter; that is, if boundInView is fully
11613      *                    contained within the view, no modification will be made, otherwise regions
11614      *                    outside of the visible area of the view will be clipped.
11615      *
11616      * @return Whether the specified portion of the view is visible on the screen.
11617      *
11618      * @hide
11619      */
11620     @UnsupportedAppUsage(trackingBug = 171933273)
11621     protected boolean isVisibleToUser(Rect boundInView) {
11622         if (mAttachInfo != null) {
11623             // Attached to invisible window means this view is not visible.
11624             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
11625                 return false;
11626             }
11627             // An invisible predecessor or one with alpha zero means
11628             // that this view is not visible to the user.
11629             Object current = this;
11630             while (current instanceof View) {
11631                 View view = (View) current;
11632                 // We have attach info so this view is attached and there is no
11633                 // need to check whether we reach to ViewRootImpl on the way up.
11634                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
11635                         view.getVisibility() != VISIBLE) {
11636                     return false;
11637                 }
11638                 current = view.mParent;
11639             }
11640             // Check if the view is entirely covered by its predecessors.
11641             Rect visibleRect = mAttachInfo.mTmpInvalRect;
11642             Point offset = mAttachInfo.mPoint;
11643             if (!getGlobalVisibleRect(visibleRect, offset)) {
11644                 return false;
11645             }
11646             // Check if the visible portion intersects the rectangle of interest.
11647             if (boundInView != null) {
11648                 visibleRect.offset(-offset.x, -offset.y);
11649                 return boundInView.intersect(visibleRect);
11650             }
11651             return true;
11652         }
11653         return false;
11654     }
11655 
11656     /**
11657      * Returns the delegate for implementing accessibility support via
11658      * composition. For more details see {@link AccessibilityDelegate}.
11659      *
11660      * @return The delegate, or null if none set.
11661      */
11662     public AccessibilityDelegate getAccessibilityDelegate() {
11663         return mAccessibilityDelegate;
11664     }
11665 
11666     /**
11667      * Sets a delegate for implementing accessibility support via composition
11668      * (as opposed to inheritance). For more details, see
11669      * {@link AccessibilityDelegate}.
11670      * <p>
11671      * <strong>Note:</strong> On platform versions prior to
11672      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
11673      * views in the {@code android.widget.*} package are called <i>before</i>
11674      * host methods. This prevents certain properties such as class name from
11675      * being modified by overriding
11676      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
11677      * as any changes will be overwritten by the host class.
11678      * <p>
11679      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
11680      * methods are called <i>after</i> host methods, which all properties to be
11681      * modified without being overwritten by the host class.
11682      *
11683      * @param delegate the object to which accessibility method calls should be
11684      *                 delegated
11685      * @see AccessibilityDelegate
11686      */
11687     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
11688         mAccessibilityDelegate = delegate;
11689     }
11690 
11691     /**
11692      * Gets the provider for managing a virtual view hierarchy rooted at this View
11693      * and reported to {@link android.accessibilityservice.AccessibilityService}s
11694      * that explore the window content.
11695      * <p>
11696      * If this method returns an instance, this instance is responsible for managing
11697      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
11698      * View including the one representing the View itself. Similarly the returned
11699      * instance is responsible for performing accessibility actions on any virtual
11700      * view or the root view itself.
11701      * </p>
11702      * <p>
11703      * If an {@link AccessibilityDelegate} has been specified via calling
11704      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11705      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
11706      * is responsible for handling this call.
11707      * </p>
11708      *
11709      * @return The provider.
11710      *
11711      * @see AccessibilityNodeProvider
11712      */
11713     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
11714         if (mAccessibilityDelegate != null) {
11715             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
11716         } else {
11717             return null;
11718         }
11719     }
11720 
11721     /**
11722      * Gets the unique identifier of this view on the screen for accessibility purposes.
11723      *
11724      * @return The view accessibility id.
11725      *
11726      * @hide
11727      */
11728     @UnsupportedAppUsage
11729     public int getAccessibilityViewId() {
11730         if (mAccessibilityViewId == NO_ID) {
11731             mAccessibilityViewId = sNextAccessibilityViewId++;
11732         }
11733         return mAccessibilityViewId;
11734     }
11735 
11736     /**
11737      * Gets the unique identifier of this view on the screen for autofill purposes.
11738      *
11739      * @return The view autofill id.
11740      *
11741      * @hide
11742      */
11743     public int getAutofillViewId() {
11744         if (mAutofillViewId == NO_ID) {
11745             mAutofillViewId = mContext.getNextAutofillId();
11746         }
11747         return mAutofillViewId;
11748     }
11749 
11750     /**
11751      * Gets the unique identifier of the window in which this View resides.
11752      *
11753      * @return The window accessibility id.
11754      *
11755      * @hide
11756      */
11757     public int getAccessibilityWindowId() {
11758         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
11759                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
11760     }
11761 
11762     /**
11763      * Returns the {@link View}'s state description.
11764      * <p>
11765      * <strong>Note:</strong> Do not override this method, as it will have no
11766      * effect on the state description presented to accessibility services.
11767      * You must call {@link #setStateDescription(CharSequence)} to modify the
11768      * state description.
11769      *
11770      * @return the state description
11771      * @see #setStateDescription(CharSequence)
11772      */
11773     @ViewDebug.ExportedProperty(category = "accessibility")
11774     public final @Nullable CharSequence getStateDescription() {
11775         return mStateDescription;
11776     }
11777 
11778     /**
11779      * Returns the {@link View}'s content description.
11780      * <p>
11781      * <strong>Note:</strong> Do not override this method, as it will have no
11782      * effect on the content description presented to accessibility services.
11783      * You must call {@link #setContentDescription(CharSequence)} to modify the
11784      * content description.
11785      *
11786      * @return the content description
11787      * @see #setContentDescription(CharSequence)
11788      * @attr ref android.R.styleable#View_contentDescription
11789      */
11790     @ViewDebug.ExportedProperty(category = "accessibility")
11791     @InspectableProperty
11792     public CharSequence getContentDescription() {
11793         return mContentDescription;
11794     }
11795 
11796     /**
11797      * Sets the {@link View}'s state description.
11798      * <p>
11799      * A state description briefly describes the states of the view and is primarily used
11800      * for accessibility support to determine how the states of a view should be presented to
11801      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
11802      * it is used for customized state description (for example, "wifi, connected, three bars").
11803      * State description changes frequently while content description should change less often.
11804      * State description should be localized. For android widgets which have default state
11805      * descriptions, app developers can call this method to override the state descriptions.
11806      * Setting state description to null restores the default behavior.
11807      *
11808      * @param stateDescription The state description.
11809      * @see #getStateDescription()
11810      * @see #setContentDescription(CharSequence) for the difference between content and
11811      * state descriptions.
11812      */
11813     @RemotableViewMethod
11814     public void setStateDescription(@Nullable CharSequence stateDescription) {
11815         if (mStateDescription == null) {
11816             if (stateDescription == null) {
11817                 return;
11818             }
11819         } else if (mStateDescription.equals(stateDescription)) {
11820             return;
11821         }
11822         mStateDescription = stateDescription;
11823         if (!TextUtils.isEmpty(stateDescription)
11824                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
11825             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
11826         }
11827         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11828             AccessibilityEvent event = AccessibilityEvent.obtain();
11829             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11830             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
11831             sendAccessibilityEventUnchecked(event);
11832         }
11833     }
11834 
11835     /**
11836      * Sets the {@link View}'s content description.
11837      * <p>
11838      * A content description briefly describes the view and is primarily used
11839      * for accessibility support to determine how a view should be presented to
11840      * the user. In the case of a view with no textual representation, such as
11841      * {@link android.widget.ImageButton}, a useful content description
11842      * explains what the view does. For example, an image button with a phone
11843      * icon that is used to place a call may use "Call" as its content
11844      * description. An image of a floppy disk that is used to save a file may
11845      * use "Save".
11846      *
11847      * <p>
11848      * This should omit role or state. Role refers to the kind of user-interface element the View
11849      * is, such as a Button or Checkbox. State refers to a frequently changing property of the View,
11850      * such as an On/Off state of a button or the audio level of a volume slider.
11851      *
11852      * <p>
11853      * Content description updates are not frequent, and are used when the semantic content - not
11854      * the state - of the element changes. For example, a Play button might change to a Pause
11855      * button during music playback.
11856      *
11857      * @param contentDescription The content description.
11858      * @see #getContentDescription()
11859      * @see #setStateDescription(CharSequence)} for state changes.
11860      * @attr ref android.R.styleable#View_contentDescription
11861      */
11862     @RemotableViewMethod
11863     public void setContentDescription(CharSequence contentDescription) {
11864         if (mContentDescription == null) {
11865             if (contentDescription == null) {
11866                 return;
11867             }
11868         } else if (mContentDescription.equals(contentDescription)) {
11869             return;
11870         }
11871         mContentDescription = contentDescription;
11872         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
11873         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
11874             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
11875             notifySubtreeAccessibilityStateChangedIfNeeded();
11876         } else {
11877             notifyViewAccessibilityStateChangedIfNeeded(
11878                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
11879         }
11880     }
11881 
11882     /**
11883      * Sets the id of a view that screen readers are requested to visit after this view.
11884      *
11885      * <p>
11886      *
11887      * For example, if view B should be visited before view A, with
11888      * B.setAccessibilityTraversalBefore(A), this requests that screen readers visit and traverse
11889      * view B before visiting view A.
11890      *
11891      * <p>
11892      * <b>Note:</b> Views are visited in the order determined by the screen reader. Avoid
11893      * explicitly manipulating focus order, as this may result in inconsistent user
11894      * experiences between apps. Instead, use other semantics, such as restructuring the view
11895      * hierarchy layout, to communicate order.
11896      *
11897      * <p>
11898      * Setting this view to be after a view that is not important for accessibility,
11899      * or if this view is not important for accessibility, means this method will have no effect if
11900      * the service is not aware of unimportant views.
11901      *
11902      * <p>
11903      * To avoid a risk of loops, set clear relationships between views. For example, if focus order
11904      * should be B -> A, and B.setAccessibilityTraversalBefore(A), then also call
11905      * A.setAccessibilityTraversalAfter(B).
11906      *
11907      * @param beforeId The id of a view this one precedes in accessibility traversal.
11908      *
11909      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
11910      *
11911      * @see #setImportantForAccessibility(int)
11912      * @see #setAccessibilityTraversalAfter(int)
11913      */
11914     @RemotableViewMethod
11915     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
11916         if (mAccessibilityTraversalBeforeId == beforeId) {
11917             return;
11918         }
11919         mAccessibilityTraversalBeforeId = beforeId;
11920         notifyViewAccessibilityStateChangedIfNeeded(
11921                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11922     }
11923 
11924     /**
11925      * Gets the id of a view before which this one is visited in accessibility traversal.
11926      *
11927      * @return The id of a view this one precedes in accessibility traversal if
11928      *         specified, otherwise {@link #NO_ID}.
11929      *
11930      * @see #setAccessibilityTraversalBefore(int)
11931      */
11932     @IdRes
11933     @InspectableProperty
11934     public int getAccessibilityTraversalBefore() {
11935         return mAccessibilityTraversalBeforeId;
11936     }
11937 
11938     /**
11939      * Sets the id of a view that screen readers are requested to visit before this view.
11940      *
11941      * <p>
11942      * For example, if view B should be visited after A, with B.setAccessibilityTraversalAfter(A),
11943      * then this requests that screen readers visit and traverse view A before visiting view B.
11944      *
11945      * <p>
11946      * <b>Note:</b> Views are visited in the order determined by the screen reader. Avoid
11947      * explicitly manipulating focus order, as this may result in inconsistent user
11948      * experiences between apps. Instead, use other semantics, such as restructuring the view
11949      * hierarchy layout, to communicate order.
11950      *
11951      * <p>
11952      * Setting this view to be after a view that is not important for accessibility,
11953      * or if this view is not important for accessibility, means this method will have no effect if
11954      * the service is not aware of unimportant views.
11955      *
11956      * <p>
11957      * To avoid a risk of loops, set clear relationships between views. For example, if focus order
11958      * should be B -> A, and B.setAccessibilityTraversalBefore(A), then also call
11959      * A.setAccessibilityTraversalAfter(B).
11960      *
11961      * @param afterId The id of a view this one succeeds in accessibility traversal.
11962      *
11963      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
11964      *
11965      * @see #setImportantForAccessibility(int)
11966      * @see #setAccessibilityTraversalBefore(int)
11967      */
11968     @RemotableViewMethod
11969     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
11970         if (mAccessibilityTraversalAfterId == afterId) {
11971             return;
11972         }
11973         mAccessibilityTraversalAfterId = afterId;
11974         notifyViewAccessibilityStateChangedIfNeeded(
11975                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11976     }
11977 
11978     /**
11979      * Gets the id of a view after which this one is visited in accessibility traversal.
11980      *
11981      * @return The id of a view this one succeedes in accessibility traversal if
11982      *         specified, otherwise {@link #NO_ID}.
11983      *
11984      * @see #setAccessibilityTraversalAfter(int)
11985      */
11986     @IdRes
11987     @InspectableProperty
11988     public int getAccessibilityTraversalAfter() {
11989         return mAccessibilityTraversalAfterId;
11990     }
11991 
11992     /**
11993      * Gets the id of a view for which this view serves as a label for
11994      * accessibility purposes.
11995      *
11996      * @return The labeled view id.
11997      */
11998     @IdRes
11999     @ViewDebug.ExportedProperty(category = "accessibility")
12000     @InspectableProperty
12001     public int getLabelFor() {
12002         return mLabelForId;
12003     }
12004 
12005     /**
12006      * Sets the id of a view for which this view serves as a label for
12007      * accessibility purposes.
12008      *
12009      * @param id The labeled view id.
12010      */
12011     @RemotableViewMethod
12012     public void setLabelFor(@IdRes int id) {
12013         if (mLabelForId == id) {
12014             return;
12015         }
12016         mLabelForId = id;
12017         if (mLabelForId != View.NO_ID
12018                 && mID == View.NO_ID) {
12019             mID = generateViewId();
12020         }
12021         notifyViewAccessibilityStateChangedIfNeeded(
12022                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12023     }
12024 
12025     /**
12026      * Invoked whenever this view loses focus, either by losing window focus or by losing
12027      * focus within its window. This method can be used to clear any state tied to the
12028      * focus. For instance, if a button is held pressed with the trackball and the window
12029      * loses focus, this method can be used to cancel the press.
12030      *
12031      * Subclasses of View overriding this method should always call super.onFocusLost().
12032      *
12033      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
12034      * @see #onWindowFocusChanged(boolean)
12035      *
12036      * @hide pending API council approval
12037      */
12038     @CallSuper
12039     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
12040     protected void onFocusLost() {
12041         resetPressedState();
12042     }
12043 
12044     private void resetPressedState() {
12045         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12046             return;
12047         }
12048 
12049         if (isPressed()) {
12050             setPressed(false);
12051 
12052             if (!mHasPerformedLongPress) {
12053                 removeLongPressCallback();
12054             }
12055         }
12056     }
12057 
12058     /**
12059      * Returns true if this view has focus
12060      *
12061      * @return True if this view has focus, false otherwise.
12062      */
12063     @ViewDebug.ExportedProperty(category = "focus")
12064     @InspectableProperty(hasAttributeId = false)
12065     public boolean isFocused() {
12066         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
12067     }
12068 
12069     /**
12070      * Find the view in the hierarchy rooted at this view that currently has
12071      * focus.
12072      *
12073      * @return The view that currently has focus, or null if no focused view can
12074      *         be found.
12075      */
12076     public View findFocus() {
12077         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
12078     }
12079 
12080     /**
12081      * Indicates whether this view is one of the set of scrollable containers in
12082      * its window.
12083      *
12084      * @return whether this view is one of the set of scrollable containers in
12085      * its window
12086      *
12087      * @attr ref android.R.styleable#View_isScrollContainer
12088      */
12089     @InspectableProperty(name = "isScrollContainer")
12090     public boolean isScrollContainer() {
12091         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
12092     }
12093 
12094     /**
12095      * Change whether this view is one of the set of scrollable containers in
12096      * its window.  This will be used to determine whether the window can
12097      * resize or must pan when a soft input area is open -- scrollable
12098      * containers allow the window to use resize mode since the container
12099      * will appropriately shrink.
12100      *
12101      * @attr ref android.R.styleable#View_isScrollContainer
12102      */
12103     public void setScrollContainer(boolean isScrollContainer) {
12104         if (isScrollContainer) {
12105             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
12106                 mAttachInfo.mScrollContainers.add(this);
12107                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
12108             }
12109             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
12110         } else {
12111             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
12112                 mAttachInfo.mScrollContainers.remove(this);
12113             }
12114             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
12115         }
12116     }
12117 
12118     /**
12119      * Returns the quality of the drawing cache.
12120      *
12121      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
12122      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
12123      *
12124      * @see #setDrawingCacheQuality(int)
12125      * @see #setDrawingCacheEnabled(boolean)
12126      * @see #isDrawingCacheEnabled()
12127      *
12128      * @attr ref android.R.styleable#View_drawingCacheQuality
12129      *
12130      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12131      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12132      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12133      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12134      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12135      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12136      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12137      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12138      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12139      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12140      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12141      * reports or unit testing the {@link PixelCopy} API is recommended.
12142      */
12143     @Deprecated
12144     @DrawingCacheQuality
12145     @InspectableProperty(enumMapping = {
12146             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
12147             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
12148             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
12149     })
12150     public int getDrawingCacheQuality() {
12151         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
12152     }
12153 
12154     /**
12155      * Set the drawing cache quality of this view. This value is used only when the
12156      * drawing cache is enabled
12157      *
12158      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
12159      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
12160      *
12161      * @see #getDrawingCacheQuality()
12162      * @see #setDrawingCacheEnabled(boolean)
12163      * @see #isDrawingCacheEnabled()
12164      *
12165      * @attr ref android.R.styleable#View_drawingCacheQuality
12166      *
12167      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12168      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12169      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12170      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12171      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12172      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12173      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12174      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12175      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12176      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12177      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12178      * reports or unit testing the {@link PixelCopy} API is recommended.
12179      */
12180     @Deprecated
12181     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
12182         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
12183     }
12184 
12185     /**
12186      * Returns whether the screen should remain on, corresponding to the current
12187      * value of {@link #KEEP_SCREEN_ON}.
12188      *
12189      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
12190      *
12191      * @see #setKeepScreenOn(boolean)
12192      *
12193      * @attr ref android.R.styleable#View_keepScreenOn
12194      */
12195     @InspectableProperty
12196     public boolean getKeepScreenOn() {
12197         return (mViewFlags & KEEP_SCREEN_ON) != 0;
12198     }
12199 
12200     /**
12201      * Controls whether the screen should remain on, modifying the
12202      * value of {@link #KEEP_SCREEN_ON}.
12203      *
12204      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
12205      *
12206      * @see #getKeepScreenOn()
12207      *
12208      * @attr ref android.R.styleable#View_keepScreenOn
12209      */
12210     public void setKeepScreenOn(boolean keepScreenOn) {
12211         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
12212     }
12213 
12214     /**
12215      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
12216      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12217      *
12218      * @attr ref android.R.styleable#View_nextFocusLeft
12219      */
12220     @IdRes
12221     @InspectableProperty(name = "nextFocusLeft")
12222     public int getNextFocusLeftId() {
12223         return mNextFocusLeftId;
12224     }
12225 
12226     /**
12227      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
12228      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
12229      * decide automatically.
12230      *
12231      * @attr ref android.R.styleable#View_nextFocusLeft
12232      */
12233     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
12234         mNextFocusLeftId = nextFocusLeftId;
12235     }
12236 
12237     /**
12238      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
12239      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12240      *
12241      * @attr ref android.R.styleable#View_nextFocusRight
12242      */
12243     @IdRes
12244     @InspectableProperty(name = "nextFocusRight")
12245     public int getNextFocusRightId() {
12246         return mNextFocusRightId;
12247     }
12248 
12249     /**
12250      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
12251      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
12252      * decide automatically.
12253      *
12254      * @attr ref android.R.styleable#View_nextFocusRight
12255      */
12256     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
12257         mNextFocusRightId = nextFocusRightId;
12258     }
12259 
12260     /**
12261      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
12262      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12263      *
12264      * @attr ref android.R.styleable#View_nextFocusUp
12265      */
12266     @IdRes
12267     @InspectableProperty(name = "nextFocusUp")
12268     public int getNextFocusUpId() {
12269         return mNextFocusUpId;
12270     }
12271 
12272     /**
12273      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
12274      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
12275      * decide automatically.
12276      *
12277      * @attr ref android.R.styleable#View_nextFocusUp
12278      */
12279     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
12280         mNextFocusUpId = nextFocusUpId;
12281     }
12282 
12283     /**
12284      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
12285      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12286      *
12287      * @attr ref android.R.styleable#View_nextFocusDown
12288      */
12289     @IdRes
12290     @InspectableProperty(name = "nextFocusDown")
12291     public int getNextFocusDownId() {
12292         return mNextFocusDownId;
12293     }
12294 
12295     /**
12296      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
12297      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
12298      * decide automatically.
12299      *
12300      * @attr ref android.R.styleable#View_nextFocusDown
12301      */
12302     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
12303         mNextFocusDownId = nextFocusDownId;
12304     }
12305 
12306     /**
12307      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
12308      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12309      *
12310      * @attr ref android.R.styleable#View_nextFocusForward
12311      */
12312     @IdRes
12313     @InspectableProperty(name = "nextFocusForward")
12314     public int getNextFocusForwardId() {
12315         return mNextFocusForwardId;
12316     }
12317 
12318     /**
12319      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
12320      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
12321      * decide automatically.
12322      *
12323      * @attr ref android.R.styleable#View_nextFocusForward
12324      */
12325     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
12326         mNextFocusForwardId = nextFocusForwardId;
12327     }
12328 
12329     /**
12330      * Gets the id of the root of the next keyboard navigation cluster.
12331      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
12332      * decide automatically.
12333      *
12334      * @attr ref android.R.styleable#View_nextClusterForward
12335      */
12336     @IdRes
12337     @InspectableProperty(name = "nextClusterForward")
12338     public int getNextClusterForwardId() {
12339         return mNextClusterForwardId;
12340     }
12341 
12342     /**
12343      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
12344      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
12345      * decide automatically.
12346      *
12347      * @attr ref android.R.styleable#View_nextClusterForward
12348      */
12349     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
12350         mNextClusterForwardId = nextClusterForwardId;
12351     }
12352 
12353     /**
12354      * Returns the visibility of this view and all of its ancestors
12355      *
12356      * @return True if this view and all of its ancestors are {@link #VISIBLE}
12357      */
12358     public boolean isShown() {
12359         View current = this;
12360         //noinspection ConstantConditions
12361         do {
12362             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
12363                 return false;
12364             }
12365             ViewParent parent = current.mParent;
12366             if (parent == null) {
12367                 return false; // We are not attached to the view root
12368             }
12369             if (!(parent instanceof View)) {
12370                 return true;
12371             }
12372             current = (View) parent;
12373         } while (current != null);
12374 
12375         return false;
12376     }
12377 
12378     private boolean detached() {
12379         View current = this;
12380         //noinspection ConstantConditions
12381         do {
12382             if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
12383                 return true;
12384             }
12385             ViewParent parent = current.mParent;
12386             if (parent == null) {
12387                 return false;
12388             }
12389             if (!(parent instanceof View)) {
12390                 return false;
12391             }
12392             current = (View) parent;
12393         } while (current != null);
12394 
12395         return false;
12396     }
12397 
12398     /**
12399      * Called by the view hierarchy when the content insets for a window have
12400      * changed, to allow it to adjust its content to fit within those windows.
12401      * The content insets tell you the space that the status bar, input method,
12402      * and other system windows infringe on the application's window.
12403      *
12404      * <p>You do not normally need to deal with this function, since the default
12405      * window decoration given to applications takes care of applying it to the
12406      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
12407      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
12408      * and your content can be placed under those system elements.  You can then
12409      * use this method within your view hierarchy if you have parts of your UI
12410      * which you would like to ensure are not being covered.
12411      *
12412      * <p>The default implementation of this method simply applies the content
12413      * insets to the view's padding, consuming that content (modifying the
12414      * insets to be 0), and returning true.  This behavior is off by default, but can
12415      * be enabled through {@link #setFitsSystemWindows(boolean)}.
12416      *
12417      * <p>This function's traversal down the hierarchy is depth-first.  The same content
12418      * insets object is propagated down the hierarchy, so any changes made to it will
12419      * be seen by all following views (including potentially ones above in
12420      * the hierarchy since this is a depth-first traversal).  The first view
12421      * that returns true will abort the entire traversal.
12422      *
12423      * <p>The default implementation works well for a situation where it is
12424      * used with a container that covers the entire window, allowing it to
12425      * apply the appropriate insets to its content on all edges.  If you need
12426      * a more complicated layout (such as two different views fitting system
12427      * windows, one on the top of the window, and one on the bottom),
12428      * you can override the method and handle the insets however you would like.
12429      * Note that the insets provided by the framework are always relative to the
12430      * far edges of the window, not accounting for the location of the called view
12431      * within that window.  (In fact when this method is called you do not yet know
12432      * where the layout will place the view, as it is done before layout happens.)
12433      *
12434      * <p>Note: unlike many View methods, there is no dispatch phase to this
12435      * call.  If you are overriding it in a ViewGroup and want to allow the
12436      * call to continue to your children, you must be sure to call the super
12437      * implementation.
12438      *
12439      * <p>Here is a sample layout that makes use of fitting system windows
12440      * to have controls for a video view placed inside of the window decorations
12441      * that it hides and shows.  This can be used with code like the second
12442      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
12443      *
12444      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
12445      *
12446      * @param insets Current content insets of the window.  Prior to
12447      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
12448      * the insets or else you and Android will be unhappy.
12449      *
12450      * @return {@code true} if this view applied the insets and it should not
12451      * continue propagating further down the hierarchy, {@code false} otherwise.
12452      * @see #getFitsSystemWindows()
12453      * @see #setFitsSystemWindows(boolean)
12454      * @see #setSystemUiVisibility(int)
12455      *
12456      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
12457      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
12458      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
12459      * to implement handling their own insets.
12460      */
12461     @Deprecated
12462     protected boolean fitSystemWindows(Rect insets) {
12463         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
12464             if (insets == null) {
12465                 // Null insets by definition have already been consumed.
12466                 // This call cannot apply insets since there are none to apply,
12467                 // so return false.
12468                 return false;
12469             }
12470             // If we're not in the process of dispatching the newer apply insets call,
12471             // that means we're not in the compatibility path. Dispatch into the newer
12472             // apply insets path and take things from there.
12473             try {
12474                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
12475                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
12476             } finally {
12477                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
12478             }
12479         } else {
12480             // We're being called from the newer apply insets path.
12481             // Perform the standard fallback behavior.
12482             return fitSystemWindowsInt(insets);
12483         }
12484     }
12485 
12486     private boolean fitSystemWindowsInt(Rect insets) {
12487         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
12488             Rect localInsets = sThreadLocal.get();
12489             boolean res = computeFitSystemWindows(insets, localInsets);
12490             applyInsets(localInsets);
12491             return res;
12492         }
12493         return false;
12494     }
12495 
12496     private void applyInsets(Rect insets) {
12497         mUserPaddingStart = UNDEFINED_PADDING;
12498         mUserPaddingEnd = UNDEFINED_PADDING;
12499         mUserPaddingLeftInitial = insets.left;
12500         mUserPaddingRightInitial = insets.right;
12501         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
12502     }
12503 
12504     /**
12505      * Called when the view should apply {@link WindowInsets} according to its internal policy.
12506      *
12507      * <p>This method should be overridden by views that wish to apply a policy different from or
12508      * in addition to the default behavior. Clients that wish to force a view subtree
12509      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
12510      *
12511      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
12512      * it will be called during dispatch instead of this method. The listener may optionally
12513      * call this method from its own implementation if it wishes to apply the view's default
12514      * insets policy in addition to its own.</p>
12515      *
12516      * <p>Implementations of this method should either return the insets parameter unchanged
12517      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
12518      * that this view applied itself. This allows new inset types added in future platform
12519      * versions to pass through existing implementations unchanged without being erroneously
12520      * consumed.</p>
12521      *
12522      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
12523      * property is set then the view will consume the system window insets and apply them
12524      * as padding for the view.</p>
12525      *
12526      * @param insets Insets to apply
12527      * @return The supplied insets with any applied insets consumed
12528      */
12529     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
12530         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
12531                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
12532             return onApplyFrameworkOptionalFitSystemWindows(insets);
12533         }
12534         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
12535             // We weren't called from within a direct call to fitSystemWindows,
12536             // call into it as a fallback in case we're in a class that overrides it
12537             // and has logic to perform.
12538             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
12539                 return insets.consumeSystemWindowInsets();
12540             }
12541         } else {
12542             // We were called from within a direct call to fitSystemWindows.
12543             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
12544                 return insets.consumeSystemWindowInsets();
12545             }
12546         }
12547         return insets;
12548     }
12549 
12550     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
12551         Rect localInsets = sThreadLocal.get();
12552         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
12553         applyInsets(localInsets);
12554         return result;
12555     }
12556 
12557     /**
12558      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
12559      * window insets to this view. The listener's
12560      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
12561      * method will be called instead of the view's
12562      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
12563      *
12564      * @param listener Listener to set
12565      *
12566      * @see #onApplyWindowInsets(WindowInsets)
12567      */
12568     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
12569         getListenerInfo().mOnApplyWindowInsetsListener = listener;
12570     }
12571 
12572     /**
12573      * Request to apply the given window insets to this view or another view in its subtree.
12574      *
12575      * <p>This method should be called by clients wishing to apply insets corresponding to areas
12576      * obscured by window decorations or overlays. This can include the status and navigation bars,
12577      * action bars, input methods and more. New inset categories may be added in the future.
12578      * The method returns the insets provided minus any that were applied by this view or its
12579      * children.</p>
12580      *
12581      * <p>Clients wishing to provide custom behavior should override the
12582      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
12583      * {@link OnApplyWindowInsetsListener} via the
12584      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
12585      * method.</p>
12586      *
12587      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
12588      * </p>
12589      *
12590      * @param insets Insets to apply
12591      * @return The provided insets minus the insets that were consumed
12592      */
12593     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
12594         try {
12595             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
12596             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
12597                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
12598             } else {
12599                 return onApplyWindowInsets(insets);
12600             }
12601         } finally {
12602             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
12603         }
12604     }
12605 
12606     /**
12607      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
12608      * cause insets.
12609      * <p>
12610      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
12611      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
12612      * this view.
12613      * </p>
12614      * @param callback The callback to set.
12615      */
12616     public void setWindowInsetsAnimationCallback(
12617             @Nullable WindowInsetsAnimation.Callback callback) {
12618         getListenerInfo().mWindowInsetsAnimationCallback = callback;
12619     }
12620 
12621     /**
12622      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
12623      *         or view tree of the sub-hierarchy {@code false} otherwise.
12624      * @hide
12625      */
12626     public boolean hasWindowInsetsAnimationCallback() {
12627         return getListenerInfo().mWindowInsetsAnimationCallback != null;
12628     }
12629 
12630     /**
12631      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
12632      * when Window Insets animation is being prepared.
12633      * @param animation current animation
12634      *
12635      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
12636      */
12637     public void dispatchWindowInsetsAnimationPrepare(
12638             @NonNull WindowInsetsAnimation animation) {
12639         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12640             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
12641         }
12642     }
12643 
12644     /**
12645      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
12646      * when Window Insets animation is started.
12647      * @param animation current animation
12648      * @param bounds the upper and lower {@link Bounds} that provides range of
12649      *  {@link WindowInsetsAnimation}.
12650      * @return the upper and lower {@link Bounds}.
12651      */
12652     @NonNull
12653     public Bounds dispatchWindowInsetsAnimationStart(
12654             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
12655         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12656             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
12657         }
12658         return bounds;
12659     }
12660 
12661     /**
12662      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
12663      * when Window Insets animation makes progress.
12664      * @param insets The current {@link WindowInsets}.
12665      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
12666      * @return current {@link WindowInsets}.
12667      */
12668     @NonNull
12669     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
12670             @NonNull List<WindowInsetsAnimation> runningAnimations) {
12671         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12672             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
12673                     runningAnimations);
12674         } else {
12675             return insets;
12676         }
12677     }
12678 
12679     /**
12680      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
12681      * when Window Insets animation ends.
12682      * @param animation The current ongoing {@link WindowInsetsAnimation}.
12683      */
12684     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
12685         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12686             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
12687         }
12688     }
12689 
12690     /**
12691      * Sets a list of areas within this view's post-layout coordinate space where the system
12692      * should not intercept touch or other pointing device gestures. <em>This method should
12693      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
12694      *
12695      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
12696      * input in order to function correctly in the presence of global system gestures that may
12697      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
12698      * to provide system-level navigation functionality, a view such as a navigation drawer
12699      * container can mark the left (or starting) edge of itself as requiring gesture capture
12700      * priority using this API. The system may then choose to relax its own gesture recognition
12701      * to allow the app to consume the user's gesture. It is not necessary for an app to register
12702      * exclusion rects for broadly spanning regions such as the entirety of a
12703      * <code>ScrollView</code> or for simple press and release click targets such as
12704      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
12705      * a precision touch gesture in a small area in either the X or Y dimension, such as
12706      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
12707      *
12708      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
12709      * exclusions it takes into account. The limit does not apply while the navigation
12710      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
12711      * {@link android.inputmethodservice.InputMethodService input method} and
12712      * {@link Intent#CATEGORY_HOME home activity}.
12713      * </p>
12714      *
12715      * @param rects A list of precision gesture regions that this view needs to function correctly
12716      */
12717     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
12718         if (rects.isEmpty() && mListenerInfo == null) return;
12719 
12720         final ListenerInfo info = getListenerInfo();
12721         if (info.mSystemGestureExclusionRects != null) {
12722             info.mSystemGestureExclusionRects.clear();
12723             info.mSystemGestureExclusionRects.addAll(rects);
12724         } else {
12725             info.mSystemGestureExclusionRects = new ArrayList<>(rects);
12726         }
12727 
12728         updatePositionUpdateListener();
12729         postUpdate(this::updateSystemGestureExclusionRects);
12730     }
12731 
12732     private void updatePositionUpdateListener() {
12733         final ListenerInfo info = getListenerInfo();
12734         if (getSystemGestureExclusionRects().isEmpty()
12735                 && collectPreferKeepClearRects().isEmpty()
12736                 && collectUnrestrictedPreferKeepClearRects().isEmpty()
12737                 && (info.mHandwritingArea == null || !shouldTrackHandwritingArea())) {
12738             if (info.mPositionUpdateListener != null) {
12739                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
12740                 info.mPositionUpdateListener = null;
12741                 info.mPositionChangedUpdate = null;
12742             }
12743         } else {
12744             if (info.mPositionUpdateListener == null) {
12745                 info.mPositionChangedUpdate = () -> {
12746                     updateSystemGestureExclusionRects();
12747                     updateKeepClearRects();
12748                     updateHandwritingArea();
12749                 };
12750                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
12751                     @Override
12752                     public void positionChanged(long n, int l, int t, int r, int b) {
12753                         postUpdate(info.mPositionChangedUpdate);
12754                     }
12755 
12756                     @Override
12757                     public void positionLost(long frameNumber) {
12758                         postUpdate(info.mPositionChangedUpdate);
12759                     }
12760                 };
12761                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
12762             }
12763         }
12764     }
12765 
12766     /**
12767      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
12768      */
12769     private void postUpdate(Runnable r) {
12770         // Potentially racey from a background thread. It's ok if it's not perfect.
12771         final Handler h = getHandler();
12772         if (h != null) {
12773             h.postAtFrontOfQueue(r);
12774         }
12775     }
12776 
12777     void updateSystemGestureExclusionRects() {
12778         final AttachInfo ai = mAttachInfo;
12779         if (ai != null) {
12780             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
12781         }
12782     }
12783 
12784     /**
12785      * Retrieve the list of areas within this view's post-layout coordinate space where the system
12786      * should not intercept touch or other pointing device gestures.
12787      *
12788      * <p>Do not modify the returned list.</p>
12789      *
12790      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
12791      */
12792     @NonNull
12793     public List<Rect> getSystemGestureExclusionRects() {
12794         final ListenerInfo info = mListenerInfo;
12795         if (info != null) {
12796             final List<Rect> list = info.mSystemGestureExclusionRects;
12797             if (list != null) {
12798                 return list;
12799             }
12800         }
12801         return Collections.emptyList();
12802     }
12803 
12804     /**
12805      * Set a preference to keep the bounds of this view clear from floating windows above this
12806      * view's window. This informs the system that the view is considered a vital area for the
12807      * user and that ideally it should not be covered. Setting this is only appropriate for UI
12808      * where the user would likely take action to uncover it.
12809      * <p>
12810      * The system will try to respect this preference, but when not possible will ignore it.
12811      * <p>
12812      * Note: This is independent from {@link #setPreferKeepClearRects}. If both are set, both will
12813      * be taken into account.
12814      * <p>
12815      * @see #setPreferKeepClearRects
12816      * @see #isPreferKeepClear
12817      * @attr ref android.R.styleable#View_preferKeepClear
12818      */
12819     public final void setPreferKeepClear(boolean preferKeepClear) {
12820         getListenerInfo().mPreferKeepClear = preferKeepClear;
12821         updatePositionUpdateListener();
12822         postUpdate(this::updateKeepClearRects);
12823     }
12824 
12825     /**
12826      * Retrieve the preference for this view to be kept clear. This is set either by
12827      * {@link #setPreferKeepClear} or via the attribute android.R.styleable#View_preferKeepClear.
12828      * <p>
12829      * If this is {@code true}, the system will ignore the Rects set by
12830      * {@link #setPreferKeepClearRects} and try to keep the whole view clear.
12831      * <p>
12832      * @see #setPreferKeepClear
12833      * @attr ref android.R.styleable#View_preferKeepClear
12834      */
12835     public final boolean isPreferKeepClear() {
12836         return mListenerInfo != null && mListenerInfo.mPreferKeepClear;
12837     }
12838 
12839     /**
12840      * Set a preference to keep the provided rects clear from floating windows above this
12841      * view's window. This informs the system that these rects are considered vital areas for the
12842      * user and that ideally they should not be covered. Setting this is only appropriate for UI
12843      * where the user would likely take action to uncover it.
12844      * <p>
12845      * The system will try to respect this preference, but when not possible will ignore it.
12846      * <p>
12847      * Note: This is independent from {@link #setPreferKeepClear}. If both are set, both will be
12848      * taken into account.
12849      * <p>
12850      * @see #setPreferKeepClear
12851      * @see #getPreferKeepClearRects
12852      *
12853      * @param rects A list of rects in this view's local coordinate system
12854      */
12855     public final void setPreferKeepClearRects(@NonNull List<Rect> rects) {
12856         final ListenerInfo info = getListenerInfo();
12857         if (info.mKeepClearRects != null) {
12858             info.mKeepClearRects.clear();
12859             info.mKeepClearRects.addAll(rects);
12860         } else {
12861             info.mKeepClearRects = new ArrayList<>(rects);
12862         }
12863         updatePositionUpdateListener();
12864         postUpdate(this::updateKeepClearRects);
12865     }
12866 
12867     /**
12868      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
12869      *
12870      * @see #setPreferKeepClearRects
12871      */
12872     @NonNull
12873     public final List<Rect> getPreferKeepClearRects() {
12874         final ListenerInfo info = mListenerInfo;
12875         if (info != null && info.mKeepClearRects != null) {
12876             return new ArrayList(info.mKeepClearRects);
12877         }
12878 
12879         return Collections.emptyList();
12880     }
12881 
12882     /**
12883      * Set a preference to keep the provided rects clear from floating windows above this
12884      * view's window. This informs the system that these rects are considered vital areas for the
12885      * user and that ideally they should not be covered. Setting this is only appropriate for UI
12886      * where the user would likely take action to uncover it.
12887      * <p>
12888      * Note: The difference with {@link #setPreferKeepClearRects} is that the system won't apply
12889      * restrictions to the rects set here.
12890      * <p>
12891      * @see #setPreferKeepClear
12892      * @see #getPreferKeepClearRects
12893      *
12894      * @param rects A list of rects in this view's local coordinate system
12895      *
12896      * @hide
12897      */
12898     @SystemApi
12899     @RequiresPermission(android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS)
12900     public final void setUnrestrictedPreferKeepClearRects(@NonNull List<Rect> rects) {
12901         final ListenerInfo info = getListenerInfo();
12902         if (info.mUnrestrictedKeepClearRects != null) {
12903             info.mUnrestrictedKeepClearRects.clear();
12904             info.mUnrestrictedKeepClearRects.addAll(rects);
12905         } else {
12906             info.mUnrestrictedKeepClearRects = new ArrayList<>(rects);
12907         }
12908         updatePositionUpdateListener();
12909         postUpdate(this::updateKeepClearRects);
12910     }
12911 
12912     /**
12913      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
12914      *
12915      * @see #setPreferKeepClearRects
12916      *
12917      * @hide
12918      */
12919     @SystemApi
12920     @NonNull
12921     public final List<Rect> getUnrestrictedPreferKeepClearRects() {
12922         final ListenerInfo info = mListenerInfo;
12923         if (info != null && info.mUnrestrictedKeepClearRects != null) {
12924             return new ArrayList(info.mUnrestrictedKeepClearRects);
12925         }
12926 
12927         return Collections.emptyList();
12928     }
12929 
12930     void updateKeepClearRects() {
12931         final AttachInfo ai = mAttachInfo;
12932         if (ai != null) {
12933             ai.mViewRootImpl.updateKeepClearRectsForView(this);
12934         }
12935     }
12936 
12937     /**
12938      * Retrieve the list of areas within this view's post-layout coordinate space which the
12939      * system will try to not cover with other floating elements, like the pip window.
12940      */
12941     @NonNull
12942     List<Rect> collectPreferKeepClearRects() {
12943         ListenerInfo info = mListenerInfo;
12944         boolean keepClearForFocus = isFocused()
12945                 && ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled();
12946         boolean keepBoundsClear = (info != null && info.mPreferKeepClear) || keepClearForFocus;
12947         boolean hasCustomKeepClearRects = info != null && info.mKeepClearRects != null;
12948 
12949         if (!keepBoundsClear && !hasCustomKeepClearRects) {
12950             return Collections.emptyList();
12951         } else if (keepBoundsClear && !hasCustomKeepClearRects) {
12952             return Collections.singletonList(new Rect(0, 0, getWidth(), getHeight()));
12953         }
12954 
12955         final List<Rect> list = new ArrayList<>();
12956         if (keepBoundsClear) {
12957             list.add(new Rect(0, 0, getWidth(), getHeight()));
12958         }
12959 
12960         if (hasCustomKeepClearRects) {
12961             list.addAll(info.mKeepClearRects);
12962         }
12963 
12964         return list;
12965     }
12966 
12967     private void updatePreferKeepClearForFocus() {
12968         if (ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled()) {
12969             updatePositionUpdateListener();
12970             post(this::updateKeepClearRects);
12971         }
12972     }
12973 
12974     /**
12975      * Retrieve the list of unrestricted areas within this view's post-layout coordinate space
12976      * which the system will try to not cover with other floating elements, like the pip window.
12977      */
12978     @NonNull
12979     List<Rect> collectUnrestrictedPreferKeepClearRects() {
12980         final ListenerInfo info = mListenerInfo;
12981         if (info != null && info.mUnrestrictedKeepClearRects != null) {
12982             return info.mUnrestrictedKeepClearRects;
12983         }
12984 
12985         return Collections.emptyList();
12986     }
12987 
12988     /**
12989      * Set the amount of offset applied to this view's stylus handwriting bounds. A positive offset
12990      * will offset the edge outwards.The base handwriting bounds of a view is its visible bounds.
12991      * The handwriting bounds offsets are applied to the base handwriting bounds to determine the
12992      * final handwriting bounds.
12993      * <p> This method is mainly used to enlarge the view's handwriting bounds for a better user
12994      * experience.
12995      * <p> Note that when the view is clipped (e.g. the view is in a
12996      * {@link android.widget.ScrollView}), the offsets are applied after the view's handwriting
12997      * bounds is clipped.
12998      *
12999      * @param offsetLeft the amount of pixel offset applied to the left edge outwards of the view's
13000      *                   handwriting bounds.
13001      * @param offsetTop the amount of pixel offset applied to the top edge outwards of the view's
13002      *                  handwriting bounds.
13003      * @param offsetRight the amount of pixel offset applied to the right edge outwards of the
13004      *                    view's handwriting bounds.
13005      * @param offsetBottom the amount of pixel offset applied to the bottom edge outwards of the
13006      *                     view's handwriting bounds.
13007      *
13008      * @see #setAutoHandwritingEnabled(boolean)
13009      * @see #getHandwritingBoundsOffsetLeft()
13010      * @see #getHandwritingBoundsOffsetTop()
13011      * @see #getHandwritingBoundsOffsetRight()
13012      * @see #getHandwritingBoundsOffsetBottom()
13013      */
13014     public void setHandwritingBoundsOffsets(float offsetLeft, float offsetTop,
13015             float offsetRight, float offsetBottom) {
13016         mHandwritingBoundsOffsetLeft = offsetLeft;
13017         mHandwritingBoundsOffsetTop = offsetTop;
13018         mHandwritingBoundsOffsetRight = offsetRight;
13019         mHandwritingBoundsOffsetBottom = offsetBottom;
13020     }
13021 
13022     /**
13023      * Return the amount of offset applied to the left edge of this view's handwriting bounds,
13024      * in the unit of pixel.
13025      *
13026      * @see #setAutoHandwritingEnabled(boolean)
13027      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13028      */
13029     public float getHandwritingBoundsOffsetLeft() {
13030         return mHandwritingBoundsOffsetLeft;
13031     }
13032 
13033     /**
13034      * Return the amount of offset applied to the top edge of this view's handwriting bounds,
13035      * in the unit of pixel.
13036      *
13037      * @see #setAutoHandwritingEnabled(boolean)
13038      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13039      */
13040     public float getHandwritingBoundsOffsetTop() {
13041         return mHandwritingBoundsOffsetTop;
13042     }
13043 
13044     /**
13045      * Return the amount of offset applied to the right edge of this view's handwriting bounds, in
13046      * the unit of pixel.
13047      *
13048      * @see #setAutoHandwritingEnabled(boolean)
13049      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13050      */
13051     public float getHandwritingBoundsOffsetRight() {
13052         return mHandwritingBoundsOffsetRight;
13053     }
13054 
13055     /**
13056      * Return the amount of offset applied to the bottom edge of this view's handwriting bounds, in
13057      * the unit of pixel.
13058      *
13059      * @see #setAutoHandwritingEnabled(boolean)
13060      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13061      */
13062     public float getHandwritingBoundsOffsetBottom() {
13063         return mHandwritingBoundsOffsetBottom;
13064     }
13065 
13066 
13067     /**
13068      * Set a handwriting area in this view. If there is any stylus {@link MotionEvent}
13069      * occurs within this area, it will trigger stylus handwriting mode. This can be disabled by
13070      * disabling the auto handwriting initiation by calling
13071      * {@link #setAutoHandwritingEnabled(boolean)} with false.
13072      *
13073      * @attr rect the handwriting area in the view's local coordiniates.
13074      *
13075      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
13076      * @see #setAutoHandwritingEnabled(boolean)
13077      *
13078      * @hide
13079      */
13080     public void setHandwritingArea(@Nullable Rect rect) {
13081         final ListenerInfo info = getListenerInfo();
13082         info.mHandwritingArea = rect;
13083         updatePositionUpdateListener();
13084         postUpdate(this::updateHandwritingArea);
13085     }
13086 
13087     /**
13088      * Return the handwriting areas set on this view, in its local coordinates.
13089      * @see #setHandwritingArea(Rect)
13090      *
13091      * @hide
13092      */
13093     @Nullable
13094     public Rect getHandwritingArea() {
13095         final ListenerInfo info = mListenerInfo;
13096         if (info != null && info.mHandwritingArea != null) {
13097             return new Rect(info.mHandwritingArea);
13098         }
13099         return null;
13100     }
13101 
13102     void updateHandwritingArea() {
13103         // If autoHandwritingArea is not enabled, do nothing.
13104         if (!shouldTrackHandwritingArea()) return;
13105         final AttachInfo ai = mAttachInfo;
13106         if (ai != null) {
13107             ai.mViewRootImpl.getHandwritingInitiator().updateHandwritingAreasForView(this);
13108         }
13109     }
13110 
13111     /**
13112      * Returns true if a stylus {@link MotionEvent} within this view's bounds should initiate
13113      * handwriting mode, either for this view ({@link #isAutoHandwritingEnabled()} is {@code true})
13114      * or for a handwriting delegate view ({@link #getHandwritingDelegatorCallback()} is not {@code
13115      * null}).
13116      */
13117     boolean shouldInitiateHandwriting() {
13118         return isAutoHandwritingEnabled() || getHandwritingDelegatorCallback() != null;
13119     }
13120 
13121     /**
13122      * Returns whether the handwriting initiator should track the handwriting area for this view,
13123      * either to initiate handwriting mode, or to prepare handwriting delegation, or to show the
13124      * handwriting unsupported message.
13125      * @hide
13126      */
13127     public boolean shouldTrackHandwritingArea() {
13128         return shouldInitiateHandwriting();
13129     }
13130 
13131     /**
13132      * Sets a callback which should be called when a stylus {@link MotionEvent} occurs within this
13133      * view's bounds. The callback will be called from the UI thread.
13134      *
13135      * <p>Setting a callback allows this view to act as a handwriting delegator, so that handwriting
13136      * mode for a delegate editor view can be initiated by stylus movement on this delegator view.
13137      * The callback implementation is expected to show and focus the delegate editor view. If a view
13138      * which returns {@code true} for {@link #isHandwritingDelegate()} creates an input connection
13139      * while the same stylus {@link MotionEvent} sequence is ongoing, handwriting mode will be
13140      * initiated for that view.
13141      *
13142      * <p>A common use case is a custom view which looks like a text editor but does not actually
13143      * support text editing itself, and clicking on the custom view causes an EditText to be shown.
13144      * To support handwriting initiation in this case, this method can be called on the custom view
13145      * to configure it as a delegator. The EditText should call {@link #setIsHandwritingDelegate} to
13146      * set it as a delegate. The {@code callback} implementation is typically the same as the click
13147      * listener implementation which shows the EditText.
13148      *
13149      * <p>If {@code null} is passed, this view will no longer act as a handwriting initiation
13150      * delegator.
13151      *
13152      * @param callback a callback which should be called when a stylus {@link MotionEvent} occurs
13153      *     within this view's bounds
13154      */
13155     public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
13156         mHandwritingDelegatorCallback = callback;
13157         if (callback != null) {
13158             setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
13159         }
13160     }
13161 
13162     /**
13163      * Returns the callback set by {@link #setHandwritingDelegatorCallback} which should be called
13164      * when a stylus {@link MotionEvent} occurs within this view's bounds. The callback should only
13165      * be called from the UI thread.
13166      */
13167     @Nullable
13168     public Runnable getHandwritingDelegatorCallback() {
13169         return mHandwritingDelegatorCallback;
13170     }
13171 
13172     /**
13173      * Specifies that this view may act as a handwriting initiation delegator for a delegate editor
13174      * view from the specified package. If this method is not called, delegators may only be used to
13175      * initiate handwriting mode for a delegate editor view from the same package as the delegator
13176      * view. This method allows specifying a different trusted package which may contain a delegate
13177      * editor view linked to this delegator view.
13178      *
13179      * <p>This method has no effect unless {@link #setHandwritingDelegatorCallback} is also called
13180      * to configure this view to act as a handwriting delegator.
13181      *
13182      * <p>If this method is called on the delegator view, then {@link
13183      * #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
13184      *
13185      * <p>For example, to configure a delegator view in package 1:
13186      *
13187      * <pre>
13188      * delegatorView.setHandwritingDelegatorCallback(callback);
13189      * delegatorView.setAllowedHandwritingDelegatePackage(package2);</pre>
13190      *
13191      * Then to configure the corresponding delegate editor view in package 2:
13192      *
13193      * <pre>
13194      * delegateEditorView.setIsHandwritingDelegate(true);
13195      * delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
13196      *
13197      * @param allowedPackageName the package name of a delegate editor view linked to this delegator
13198      *     view, or {@code null} to restore the default behavior of only allowing delegate editor
13199      *     views from the same package as this delegator view
13200      */
13201     public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
13202         mAllowedHandwritingDelegatePackageName = allowedPackageName;
13203     }
13204 
13205     /**
13206      * Returns the allowed package for delegate editor views for which this view may act as a
13207      * handwriting delegator, as set by {@link #setAllowedHandwritingDelegatePackage}. If {@link
13208      * #setAllowedHandwritingDelegatePackage} has not been called, or called with {@code null}
13209      * argument, this will return {@code null}, meaning that this delegator view may only be used to
13210      * initiate handwriting mode for a delegate editor view from the same package as this delegator
13211      * view.
13212      */
13213     @Nullable
13214     public String getAllowedHandwritingDelegatePackageName() {
13215         return mAllowedHandwritingDelegatePackageName;
13216     }
13217 
13218     /**
13219      * Sets this view to be a handwriting delegate. If a delegate view creates an input connection
13220      * while a stylus {@link MotionEvent} sequence from a delegator view is ongoing, handwriting
13221      * mode will be initiated for the delegate view.
13222      *
13223      * @param isHandwritingDelegate whether this view is a handwriting initiation delegate
13224      * @see #setHandwritingDelegatorCallback(Runnable)
13225      */
13226     public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
13227         mIsHandwritingDelegate = isHandwritingDelegate;
13228     }
13229 
13230     /**
13231      * Returns whether this view has been set as a handwriting delegate by {@link
13232      * #setIsHandwritingDelegate}.
13233      */
13234     public boolean isHandwritingDelegate() {
13235         return mIsHandwritingDelegate;
13236     }
13237 
13238     /**
13239      * Specifies that a view from the specified package may act as a handwriting delegator for this
13240      * delegate editor view. If this method is not called, only views from the same package as this
13241      * delegate editor view may act as a handwriting delegator. This method allows specifying a
13242      * different trusted package which may contain a delegator view linked to this delegate editor
13243      * view.
13244      *
13245      * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
13246      * configure this view to act as a handwriting delegate.
13247      *
13248      * <p>If this method is called on the delegate editor view, then {@link
13249      * #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
13250      *
13251      * @param allowedPackageName the package name of a delegator view linked to this delegate editor
13252      *     view, or {@code null} to restore the default behavior of only allowing delegator views
13253      *     from the same package as this delegate editor view
13254      */
13255     public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
13256         mAllowedHandwritingDelegatorPackageName = allowedPackageName;
13257     }
13258 
13259     /**
13260      * Returns the allowed package for views which may act as a handwriting delegator for this
13261      * delegate editor view, as set by {@link #setAllowedHandwritingDelegatorPackage}. If {@link
13262      * #setAllowedHandwritingDelegatorPackage} has not been called, or called with {@code null}
13263      * argument, this will return {@code null}, meaning that only views from the same package as
13264      * this delegator editor view may act as a handwriting delegator.
13265      */
13266     @Nullable
13267     public String getAllowedHandwritingDelegatorPackageName() {
13268         return mAllowedHandwritingDelegatorPackageName;
13269     }
13270 
13271     /**
13272      * Sets flags configuring the handwriting delegation behavior for this delegate editor view.
13273      *
13274      * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
13275      * configure this view to act as a handwriting delegate.
13276      *
13277      * @param flags {@link InputMethodManager#HANDWRITING_DELEGATE_FLAG_HOME_DELEGATOR_ALLOWED} or
13278      *     {@code 0}
13279      */
13280     @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR)
13281     public void setHandwritingDelegateFlags(
13282             @InputMethodManager.HandwritingDelegateFlags int flags) {
13283         mHandwritingDelegateFlags = flags;
13284     }
13285 
13286     /**
13287      * Returns flags configuring the handwriting delegation behavior for this delegate editor view,
13288      * as set by {@link #setHandwritingDelegateFlags}.
13289      */
13290     @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR)
13291     public @InputMethodManager.HandwritingDelegateFlags int getHandwritingDelegateFlags() {
13292         return mHandwritingDelegateFlags;
13293     }
13294 
13295     /**
13296      * Gets the coordinates of this view in the coordinate space of the
13297      * {@link Surface} that contains the view.
13298      *
13299      * <p>In multiple-screen scenarios, if the surface spans multiple screens,
13300      * the coordinate space of the surface also spans multiple screens.
13301      *
13302      * <p>After the method returns, the argument array contains the x and y
13303      * coordinates of the view relative to the view's left and top edges,
13304      * respectively.
13305      *
13306      * @param location A two-element integer array in which the view coordinates
13307      *      are stored. The x-coordinate is at index 0; the y-coordinate, at
13308      *      index 1.
13309      */
13310     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
13311         getLocationInWindow(location);
13312         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
13313             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
13314             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
13315         }
13316     }
13317 
13318     /**
13319      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
13320      * only available if the view is attached.
13321      *
13322      * @return WindowInsets from the top of the view hierarchy or null if View is detached
13323      */
13324     public WindowInsets getRootWindowInsets() {
13325         if (mAttachInfo != null) {
13326             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
13327         }
13328         return null;
13329     }
13330 
13331     /**
13332      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
13333      *
13334      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
13335      *         a window nor a view tree with a decor.
13336      * @see Window#getInsetsController()
13337      */
13338     public @Nullable WindowInsetsController getWindowInsetsController() {
13339         if (mAttachInfo != null) {
13340             return mAttachInfo.mViewRootImpl.getInsetsController();
13341         }
13342         ViewParent parent = getParent();
13343         if (parent instanceof View) {
13344             return ((View) parent).getWindowInsetsController();
13345         } else if (parent instanceof ViewRootImpl) {
13346             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
13347             return ((ViewRootImpl) parent).getInsetsController();
13348         }
13349         return null;
13350     }
13351 
13352 
13353     /**
13354      * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}.
13355      *
13356      * @return The {@link OnBackInvokedDispatcher} from this or the nearest
13357      * ancestor, or null if this view is both not attached and have no ancestor providing an
13358      * {@link OnBackInvokedDispatcher}.
13359      */
13360     @Nullable
13361     public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() {
13362         ViewParent parent = getParent();
13363         if (parent != null) {
13364             return parent.findOnBackInvokedDispatcherForChild(this, this);
13365         }
13366         return null;
13367     }
13368 
13369     /**
13370      * @hide Compute the insets that should be consumed by this view and the ones
13371      * that should propagate to those under it.
13372      *
13373      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
13374      *
13375      * @param inoutInsets the insets given to this view
13376      * @param outLocalInsets the insets that should be applied to this view
13377      * @deprecated use {@link #computeSystemWindowInsets}
13378      * @return
13379      */
13380     @Deprecated
13381     @UnsupportedAppUsage
13382     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
13383         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
13384                 outLocalInsets);
13385         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
13386         return innerInsets.isSystemWindowInsetsConsumed();
13387     }
13388 
13389     /**
13390      * Compute insets that should be consumed by this view and the ones that should propagate
13391      * to those under it.
13392      *
13393      * @param in Insets currently being processed by this View, likely received as a parameter
13394      *           to {@link #onApplyWindowInsets(WindowInsets)}.
13395      * @param outLocalInsets A Rect that will receive the insets that should be consumed
13396      *                       by this view
13397      * @return Insets that should be passed along to views under this one
13398      */
13399     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
13400         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
13401                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
13402         if (isOptionalFitSystemWindows && mAttachInfo != null) {
13403             OnContentApplyWindowInsetsListener listener =
13404                     mAttachInfo.mContentOnApplyWindowInsetsListener;
13405             if (listener == null) {
13406                 // The application wants to take care of fitting system window for
13407                 // the content.
13408                 outLocalInsets.setEmpty();
13409                 return in;
13410             }
13411             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
13412             outLocalInsets.set(result.first.toRect());
13413             return result.second;
13414         } else {
13415             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
13416             return in.consumeSystemWindowInsets().inset(outLocalInsets);
13417         }
13418     }
13419 
13420     /**
13421      * @return True if the window has the {@link OnContentApplyWindowInsetsListener}, and this means
13422      *         the framework will apply window insets on the content of the window.
13423      * @hide
13424      */
13425     protected boolean hasContentOnApplyWindowInsetsListener() {
13426         return mAttachInfo != null && mAttachInfo.mContentOnApplyWindowInsetsListener != null;
13427     }
13428 
13429     /**
13430      * Sets whether or not this view should account for system screen decorations
13431      * such as the status bar and inset its content; that is, controlling whether
13432      * the default implementation of {@link #fitSystemWindows(Rect)} will be
13433      * executed.  See that method for more details.
13434      *
13435      * <p>Note that if you are providing your own implementation of
13436      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
13437      * flag to true -- your implementation will be overriding the default
13438      * implementation that checks this flag.
13439      *
13440      * @param fitSystemWindows If true, then the default implementation of
13441      * {@link #fitSystemWindows(Rect)} will be executed.
13442      *
13443      * @attr ref android.R.styleable#View_fitsSystemWindows
13444      * @see #getFitsSystemWindows()
13445      * @see #fitSystemWindows(Rect)
13446      * @see #setSystemUiVisibility(int)
13447      */
13448     public void setFitsSystemWindows(boolean fitSystemWindows) {
13449         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
13450     }
13451 
13452     /**
13453      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
13454      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
13455      * will be executed.
13456      *
13457      * @return {@code true} if the default implementation of
13458      * {@link #fitSystemWindows(Rect)} will be executed.
13459      *
13460      * @attr ref android.R.styleable#View_fitsSystemWindows
13461      * @see #setFitsSystemWindows(boolean)
13462      * @see #fitSystemWindows(Rect)
13463      * @see #setSystemUiVisibility(int)
13464      */
13465     @ViewDebug.ExportedProperty
13466     @InspectableProperty
13467     public boolean getFitsSystemWindows() {
13468         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
13469     }
13470 
13471     /** @hide */
13472     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
13473     public boolean fitsSystemWindows() {
13474         return getFitsSystemWindows();
13475     }
13476 
13477     /**
13478      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
13479      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
13480      */
13481     @Deprecated
13482     public void requestFitSystemWindows() {
13483         if (mParent != null) {
13484             mParent.requestFitSystemWindows();
13485         }
13486     }
13487 
13488     /**
13489      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
13490      */
13491     public void requestApplyInsets() {
13492         requestFitSystemWindows();
13493     }
13494 
13495     /**
13496      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
13497      * @hide
13498      */
13499     @UnsupportedAppUsage
13500     public void makeOptionalFitsSystemWindows() {
13501         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
13502     }
13503 
13504     /**
13505      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
13506      * @hide
13507      */
13508     public void makeFrameworkOptionalFitsSystemWindows() {
13509         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
13510     }
13511 
13512     /**
13513      * @hide
13514      */
13515     public boolean isFrameworkOptionalFitsSystemWindows() {
13516         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
13517     }
13518 
13519     /**
13520      * Returns the visibility status for this view.
13521      *
13522      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
13523      * @attr ref android.R.styleable#View_visibility
13524      */
13525     @ViewDebug.ExportedProperty(mapping = {
13526         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
13527         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
13528         @ViewDebug.IntToString(from = GONE,      to = "GONE")
13529     })
13530     @InspectableProperty(enumMapping = {
13531             @EnumEntry(value = VISIBLE, name = "visible"),
13532             @EnumEntry(value = INVISIBLE, name = "invisible"),
13533             @EnumEntry(value = GONE, name = "gone")
13534     })
13535     @Visibility
13536     public int getVisibility() {
13537         return mViewFlags & VISIBILITY_MASK;
13538     }
13539 
13540     /**
13541      * Set the visibility state of this view.
13542      *
13543      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
13544      * @attr ref android.R.styleable#View_visibility
13545      */
13546     @RemotableViewMethod
13547     public void setVisibility(@Visibility int visibility) {
13548         setFlags(visibility, VISIBILITY_MASK);
13549     }
13550 
13551     /**
13552      * Returns the enabled status for this view. The interpretation of the
13553      * enabled state varies by subclass.
13554      *
13555      * @return True if this view is enabled, false otherwise.
13556      */
13557     @ViewDebug.ExportedProperty
13558     @InspectableProperty
13559     public boolean isEnabled() {
13560         return (mViewFlags & ENABLED_MASK) == ENABLED;
13561     }
13562 
13563     /**
13564      * Set the enabled state of this view. The interpretation of the enabled
13565      * state varies by subclass.
13566      *
13567      * @param enabled True if this view is enabled, false otherwise.
13568      */
13569     @RemotableViewMethod
13570     public void setEnabled(boolean enabled) {
13571         if (enabled == isEnabled()) return;
13572 
13573         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
13574 
13575         /*
13576          * The View most likely has to change its appearance, so refresh
13577          * the drawable state.
13578          */
13579         refreshDrawableState();
13580 
13581         // Invalidate too, since the default behavior for views is to be
13582         // be drawn at 50% alpha rather than to change the drawable.
13583         invalidate(true);
13584 
13585         if (!enabled) {
13586             cancelPendingInputEvents();
13587         }
13588         notifyViewAccessibilityStateChangedIfNeeded(
13589                 AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED);
13590     }
13591 
13592     /**
13593      * Set whether this view can receive the focus.
13594      * <p>
13595      * Setting this to false will also ensure that this view is not focusable
13596      * in touch mode.
13597      *
13598      * @param focusable If true, this view can receive the focus.
13599      *
13600      * @see #setFocusableInTouchMode(boolean)
13601      * @see #setFocusable(int)
13602      * @attr ref android.R.styleable#View_focusable
13603      */
13604     @RemotableViewMethod
13605     public void setFocusable(boolean focusable) {
13606         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
13607     }
13608 
13609     /**
13610      * Sets whether this view can receive focus.
13611      * <p>
13612      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
13613      * automatically based on the view's interactivity. This is the default.
13614      * <p>
13615      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
13616      * in touch mode.
13617      *
13618      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
13619      *                  or {@link #FOCUSABLE_AUTO}.
13620      * @see #setFocusableInTouchMode(boolean)
13621      * @attr ref android.R.styleable#View_focusable
13622      */
13623     @RemotableViewMethod
13624     public void setFocusable(@Focusable int focusable) {
13625         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
13626             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
13627         }
13628         setFlags(focusable, FOCUSABLE_MASK);
13629     }
13630 
13631     /**
13632      * Set whether this view can receive focus while in touch mode.
13633      *
13634      * Setting this to true will also ensure that this view is focusable.
13635      *
13636      * @param focusableInTouchMode If true, this view can receive the focus while
13637      *   in touch mode.
13638      *
13639      * @see #setFocusable(boolean)
13640      * @attr ref android.R.styleable#View_focusableInTouchMode
13641      */
13642     @RemotableViewMethod
13643     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
13644         // Focusable in touch mode should always be set before the focusable flag
13645         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
13646         // which, in touch mode, will not successfully request focus on this view
13647         // because the focusable in touch mode flag is not set
13648         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
13649 
13650         // Clear FOCUSABLE_AUTO if set.
13651         if (focusableInTouchMode) {
13652             // Clears FOCUSABLE_AUTO if set.
13653             setFlags(FOCUSABLE, FOCUSABLE_MASK);
13654         }
13655     }
13656 
13657     /**
13658      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
13659      * to autofill the view with the user's data.
13660      *
13661      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
13662      * For example, if the application accepts either an username or email address to identify
13663      * an user.
13664      *
13665      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
13666      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
13667      * constants such as:
13668      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
13669      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
13670      * {@link #AUTOFILL_HINT_NAME},
13671      * {@link #AUTOFILL_HINT_PHONE},
13672      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
13673      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
13674      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
13675      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
13676      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
13677      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
13678      *
13679      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
13680      * @attr ref android.R.styleable#View_autofillHints
13681      */
13682     public void setAutofillHints(@Nullable String... autofillHints) {
13683         if (autofillHints == null || autofillHints.length == 0) {
13684             mAutofillHints = null;
13685         } else {
13686             mAutofillHints = autofillHints;
13687         }
13688         if (sensitiveContentAppProtection()) {
13689             if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) {
13690                 updateSensitiveViewsCountIfNeeded(isAggregatedVisible());
13691             }
13692         }
13693     }
13694 
13695     /**
13696      * @hide
13697      */
13698     @TestApi
13699     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
13700         boolean wasChanged = isAutofilled != isAutofilled();
13701 
13702         if (wasChanged) {
13703             if (isAutofilled) {
13704                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
13705             } else {
13706                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
13707             }
13708 
13709             if (hideHighlight) {
13710                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
13711             } else {
13712                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
13713             }
13714 
13715             invalidate();
13716         }
13717     }
13718 
13719     /**
13720      * Set whether this view should have sound effects enabled for events such as
13721      * clicking and touching.
13722      *
13723      * <p>You may wish to disable sound effects for a view if you already play sounds,
13724      * for instance, a dial key that plays dtmf tones.
13725      *
13726      * @param soundEffectsEnabled whether sound effects are enabled for this view.
13727      * @see #isSoundEffectsEnabled()
13728      * @see #playSoundEffect(int)
13729      * @attr ref android.R.styleable#View_soundEffectsEnabled
13730      */
13731     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
13732         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
13733     }
13734 
13735     /**
13736      * @return whether this view should have sound effects enabled for events such as
13737      *     clicking and touching.
13738      *
13739      * @see #setSoundEffectsEnabled(boolean)
13740      * @see #playSoundEffect(int)
13741      * @attr ref android.R.styleable#View_soundEffectsEnabled
13742      */
13743     @ViewDebug.ExportedProperty
13744     @InspectableProperty
13745     public boolean isSoundEffectsEnabled() {
13746         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
13747     }
13748 
13749     /**
13750      * Set whether this view should have haptic feedback for events such as
13751      * long presses.
13752      *
13753      * <p>You may wish to disable haptic feedback if your view already controls
13754      * its own haptic feedback.
13755      *
13756      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
13757      * @see #isHapticFeedbackEnabled()
13758      * @see #performHapticFeedback(int)
13759      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
13760      */
13761     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
13762         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
13763     }
13764 
13765     /**
13766      * @return whether this view should have haptic feedback enabled for events
13767      * such as long presses.
13768      *
13769      * @see #setHapticFeedbackEnabled(boolean)
13770      * @see #performHapticFeedback(int)
13771      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
13772      */
13773     @ViewDebug.ExportedProperty
13774     @InspectableProperty
13775     public boolean isHapticFeedbackEnabled() {
13776         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
13777     }
13778 
13779     /**
13780      * Returns the layout direction for this view.
13781      *
13782      * @return One of {@link #LAYOUT_DIRECTION_LTR},
13783      *   {@link #LAYOUT_DIRECTION_RTL},
13784      *   {@link #LAYOUT_DIRECTION_INHERIT} or
13785      *   {@link #LAYOUT_DIRECTION_LOCALE}.
13786      *
13787      * @attr ref android.R.styleable#View_layoutDirection
13788      *
13789      * @hide
13790      */
13791     @ViewDebug.ExportedProperty(category = "layout", mapping = {
13792         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
13793         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
13794         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
13795         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
13796     })
13797     @InspectableProperty(hasAttributeId = false, enumMapping = {
13798             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
13799             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
13800             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
13801             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
13802     })
13803     @LayoutDir
13804     public int getRawLayoutDirection() {
13805         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
13806     }
13807 
13808     /**
13809      * Set the layout direction for this view. This will propagate a reset of layout direction
13810      * resolution to the view's children and resolve layout direction for this view.
13811      *
13812      * @param layoutDirection the layout direction to set. Should be one of:
13813      *
13814      * {@link #LAYOUT_DIRECTION_LTR},
13815      * {@link #LAYOUT_DIRECTION_RTL},
13816      * {@link #LAYOUT_DIRECTION_INHERIT},
13817      * {@link #LAYOUT_DIRECTION_LOCALE}.
13818      *
13819      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
13820      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
13821      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
13822      *
13823      * @attr ref android.R.styleable#View_layoutDirection
13824      */
13825     @RemotableViewMethod
13826     public void setLayoutDirection(@LayoutDir int layoutDirection) {
13827         if (getRawLayoutDirection() != layoutDirection) {
13828             // Reset the current layout direction and the resolved one
13829             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
13830             resetRtlProperties();
13831             // Set the new layout direction (filtered)
13832             mPrivateFlags2 |=
13833                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
13834             // We need to resolve all RTL properties as they all depend on layout direction
13835             resolveRtlPropertiesIfNeeded();
13836             requestLayout();
13837             invalidate(true);
13838         }
13839     }
13840 
13841     /**
13842      * Returns the resolved layout direction for this view.
13843      *
13844      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
13845      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
13846      *
13847      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
13848      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
13849      *
13850      * @attr ref android.R.styleable#View_layoutDirection
13851      */
13852     @ViewDebug.ExportedProperty(category = "layout", mapping = {
13853         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
13854         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
13855     })
13856     @InspectableProperty(enumMapping = {
13857             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
13858             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
13859     })
13860     @ResolvedLayoutDir
13861     public int getLayoutDirection() {
13862         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
13863                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
13864     }
13865 
13866     /**
13867      * Indicates whether or not this view's layout is right-to-left. This is resolved from
13868      * layout attribute and/or the inherited value from the parent
13869      *
13870      * @return true if the layout is right-to-left.
13871      *
13872      * @hide
13873      */
13874     @ViewDebug.ExportedProperty(category = "layout")
13875     @UnsupportedAppUsage
13876     public boolean isLayoutRtl() {
13877         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
13878     }
13879 
13880     /**
13881      * Indicates whether the view is currently tracking transient state that the
13882      * app should not need to concern itself with saving and restoring, but that
13883      * the framework should take special note to preserve when possible.
13884      *
13885      * <p>A view with transient state cannot be trivially rebound from an external
13886      * data source, such as an adapter binding item views in a list. This may be
13887      * because the view is performing an animation, tracking user selection
13888      * of content, or similar.</p>
13889      *
13890      * @return true if the view has transient state
13891      */
13892     @ViewDebug.ExportedProperty(category = "layout")
13893     public boolean hasTransientState() {
13894         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
13895     }
13896 
13897     /**
13898      * Set whether this view is currently tracking transient state that the
13899      * framework should attempt to preserve when possible. This flag is reference counted,
13900      * so every call to setHasTransientState(true) should be paired with a later call
13901      * to setHasTransientState(false).
13902      *
13903      * <p>A view with transient state cannot be trivially rebound from an external
13904      * data source, such as an adapter binding item views in a list. This may be
13905      * because the view is performing an animation, tracking user selection
13906      * of content, or similar.</p>
13907      *
13908      * @param hasTransientState true if this view has transient state
13909      */
13910     public void setHasTransientState(boolean hasTransientState) {
13911         final boolean oldHasTransientState = hasTransientState();
13912         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
13913                 mTransientStateCount - 1;
13914         if (mTransientStateCount < 0) {
13915             mTransientStateCount = 0;
13916             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
13917                     "unmatched pair of setHasTransientState calls");
13918         } else if ((hasTransientState && mTransientStateCount == 1) ||
13919                 (!hasTransientState && mTransientStateCount == 0)) {
13920             // update flag if we've just incremented up from 0 or decremented down to 0
13921             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
13922                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
13923             final boolean newHasTransientState = hasTransientState();
13924             if (mParent != null && newHasTransientState != oldHasTransientState) {
13925                 try {
13926                     mParent.childHasTransientStateChanged(this, newHasTransientState);
13927                 } catch (AbstractMethodError e) {
13928                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13929                             " does not fully implement ViewParent", e);
13930                 }
13931             }
13932         }
13933     }
13934 
13935     /**
13936      * Set the view is tracking translation transient state. This flag is used to check if the view
13937      * need to call setHasTransientState(false) to reset transient state that set when starting
13938      * translation.
13939      *
13940      * @param hasTranslationTransientState true if this view has translation transient state
13941      * @hide
13942      */
13943     public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
13944         if (hasTranslationTransientState) {
13945             mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
13946         } else {
13947             mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
13948         }
13949     }
13950 
13951     /**
13952      * @hide
13953      */
13954     public boolean hasTranslationTransientState() {
13955         return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
13956                 == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
13957     }
13958 
13959     /**
13960      * @hide
13961      */
13962     public void clearTranslationState() {
13963         if (mViewTranslationCallback != null) {
13964             mViewTranslationCallback.onClearTranslation(this);
13965         }
13966         clearViewTranslationResponse();
13967         if (hasTranslationTransientState()) {
13968             setHasTransientState(false);
13969             setHasTranslationTransientState(false);
13970         }
13971     }
13972 
13973     /**
13974      * Returns true if this view is currently attached to a window.
13975      */
13976     public boolean isAttachedToWindow() {
13977         return mAttachInfo != null;
13978     }
13979 
13980     /**
13981      * Returns true if this view has been through at least one layout since it
13982      * was last attached to or detached from a window.
13983      */
13984     public boolean isLaidOut() {
13985         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
13986     }
13987 
13988     /**
13989      * @return {@code true} if laid-out and not about to do another layout.
13990      */
13991     boolean isLayoutValid() {
13992         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
13993     }
13994 
13995     /**
13996      * If this view doesn't do any drawing on its own, set this flag to
13997      * allow further optimizations. By default, this flag is not set on
13998      * View, but could be set on some View subclasses such as ViewGroup.
13999      *
14000      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
14001      * you should clear this flag.
14002      *
14003      * @param willNotDraw whether or not this View draw on its own
14004      */
14005     public void setWillNotDraw(boolean willNotDraw) {
14006         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
14007     }
14008 
14009     /**
14010      * Returns whether or not this View draws on its own.
14011      *
14012      * @return true if this view has nothing to draw, false otherwise
14013      */
14014     @ViewDebug.ExportedProperty(category = "drawing")
14015     public boolean willNotDraw() {
14016         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
14017     }
14018 
14019     /**
14020      * When a View's drawing cache is enabled, drawing is redirected to an
14021      * offscreen bitmap. Some views, like an ImageView, must be able to
14022      * bypass this mechanism if they already draw a single bitmap, to avoid
14023      * unnecessary usage of the memory.
14024      *
14025      * @param willNotCacheDrawing true if this view does not cache its
14026      *        drawing, false otherwise
14027      *
14028      * @deprecated The view drawing cache was largely made obsolete with the introduction of
14029      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
14030      * layers are largely unnecessary and can easily result in a net loss in performance due to the
14031      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
14032      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
14033      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
14034      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
14035      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
14036      * software-rendered usages are discouraged and have compatibility issues with hardware-only
14037      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
14038      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
14039      * reports or unit testing the {@link PixelCopy} API is recommended.
14040      */
14041     @Deprecated
14042     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
14043         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
14044     }
14045 
14046     /**
14047      * Returns whether or not this View can cache its drawing or not.
14048      *
14049      * @return true if this view does not cache its drawing, false otherwise
14050      *
14051      * @deprecated The view drawing cache was largely made obsolete with the introduction of
14052      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
14053      * layers are largely unnecessary and can easily result in a net loss in performance due to the
14054      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
14055      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
14056      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
14057      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
14058      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
14059      * software-rendered usages are discouraged and have compatibility issues with hardware-only
14060      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
14061      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
14062      * reports or unit testing the {@link PixelCopy} API is recommended.
14063      */
14064     @ViewDebug.ExportedProperty(category = "drawing")
14065     @Deprecated
14066     public boolean willNotCacheDrawing() {
14067         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
14068     }
14069 
14070     /**
14071      * Indicates whether this view reacts to click events or not.
14072      *
14073      * @return true if the view is clickable, false otherwise
14074      *
14075      * @see #setClickable(boolean)
14076      * @attr ref android.R.styleable#View_clickable
14077      */
14078     @ViewDebug.ExportedProperty
14079     @InspectableProperty
14080     public boolean isClickable() {
14081         return (mViewFlags & CLICKABLE) == CLICKABLE;
14082     }
14083 
14084     /**
14085      * Enables or disables click events for this view. When a view
14086      * is clickable it will change its state to "pressed" on every click.
14087      * Subclasses should set the view clickable to visually react to
14088      * user's clicks.
14089      *
14090      * @param clickable true to make the view clickable, false otherwise
14091      *
14092      * @see #isClickable()
14093      * @attr ref android.R.styleable#View_clickable
14094      */
14095     public void setClickable(boolean clickable) {
14096         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
14097     }
14098 
14099     /**
14100      * Enables or disables click events for this view when disabled.
14101      *
14102      * @param clickableWhenDisabled true to make the view clickable, false otherwise
14103      *
14104      * @attr ref android.R.styleable#View_allowClickWhenDisabled
14105      */
14106     public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
14107         if (clickableWhenDisabled) {
14108             mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
14109         } else {
14110             mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
14111         }
14112     }
14113 
14114     /**
14115      * Indicates whether this view reacts to long click events or not.
14116      *
14117      * @return true if the view is long clickable, false otherwise
14118      *
14119      * @see #setLongClickable(boolean)
14120      * @attr ref android.R.styleable#View_longClickable
14121      */
14122     @InspectableProperty
14123     public boolean isLongClickable() {
14124         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
14125     }
14126 
14127     /**
14128      * Enables or disables long click events for this view. When a view is long
14129      * clickable it reacts to the user holding down the button for a longer
14130      * duration than a tap. This event can either launch the listener or a
14131      * context menu.
14132      *
14133      * @param longClickable true to make the view long clickable, false otherwise
14134      * @see #isLongClickable()
14135      * @attr ref android.R.styleable#View_longClickable
14136      */
14137     public void setLongClickable(boolean longClickable) {
14138         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
14139     }
14140 
14141     /**
14142      * Indicates whether this view reacts to context clicks or not.
14143      *
14144      * @return true if the view is context clickable, false otherwise
14145      * @see #setContextClickable(boolean)
14146      * @attr ref android.R.styleable#View_contextClickable
14147      */
14148     @InspectableProperty
14149     public boolean isContextClickable() {
14150         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
14151     }
14152 
14153     /**
14154      * Enables or disables context clicking for this view. This event can launch the listener.
14155      *
14156      * @param contextClickable true to make the view react to a context click, false otherwise
14157      * @see #isContextClickable()
14158      * @attr ref android.R.styleable#View_contextClickable
14159      */
14160     public void setContextClickable(boolean contextClickable) {
14161         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
14162     }
14163 
14164     /**
14165      * Sets the pressed state for this view and provides a touch coordinate for
14166      * animation hinting.
14167      *
14168      * @param pressed Pass true to set the View's internal state to "pressed",
14169      *            or false to reverts the View's internal state from a
14170      *            previously set "pressed" state.
14171      * @param x The x coordinate of the touch that caused the press
14172      * @param y The y coordinate of the touch that caused the press
14173      */
14174     private void setPressed(boolean pressed, float x, float y) {
14175         if (pressed) {
14176             drawableHotspotChanged(x, y);
14177         }
14178 
14179         setPressed(pressed);
14180     }
14181 
14182     /**
14183      * Sets the pressed state for this view.
14184      *
14185      * @see #isClickable()
14186      * @see #setClickable(boolean)
14187      *
14188      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
14189      *        the View's internal state from a previously set "pressed" state.
14190      */
14191     public void setPressed(boolean pressed) {
14192         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
14193 
14194         if (pressed) {
14195             mPrivateFlags |= PFLAG_PRESSED;
14196         } else {
14197             mPrivateFlags &= ~PFLAG_PRESSED;
14198         }
14199 
14200         if (needsRefresh) {
14201             refreshDrawableState();
14202         }
14203         dispatchSetPressed(pressed);
14204     }
14205 
14206     /**
14207      * Dispatch setPressed to all of this View's children.
14208      *
14209      * @see #setPressed(boolean)
14210      *
14211      * @param pressed The new pressed state
14212      */
14213     protected void dispatchSetPressed(boolean pressed) {
14214     }
14215 
14216     /**
14217      * Indicates whether the view is currently in pressed state. Unless
14218      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
14219      * the pressed state.
14220      *
14221      * @see #setPressed(boolean)
14222      * @see #isClickable()
14223      * @see #setClickable(boolean)
14224      *
14225      * @return true if the view is currently pressed, false otherwise
14226      */
14227     @ViewDebug.ExportedProperty
14228     @InspectableProperty(hasAttributeId = false)
14229     public boolean isPressed() {
14230         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
14231     }
14232 
14233     /**
14234      * @hide
14235      * Indicates whether this view will participate in data collection through
14236      * {@link ViewStructure}.  If true, it will not provide any data
14237      * for itself or its children.  If false, the normal data collection will be allowed.
14238      *
14239      * @return Returns false if assist data collection is not blocked, else true.
14240      *
14241      * @see #setAssistBlocked(boolean)
14242      * @attr ref android.R.styleable#View_assistBlocked
14243      */
14244     public boolean isAssistBlocked() {
14245         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
14246     }
14247 
14248     /**
14249      * @hide
14250      * Controls whether assist data collection from this view and its children is enabled
14251      * (that is, whether {@link #onProvideStructure} and
14252      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
14253      * allowing normal assist collection.  Setting this to false will disable assist collection.
14254      *
14255      * @param enabled Set to true to <em>disable</em> assist data collection, or false
14256      * (the default) to allow it.
14257      *
14258      * @see #isAssistBlocked()
14259      * @see #onProvideStructure
14260      * @see #onProvideVirtualStructure
14261      * @attr ref android.R.styleable#View_assistBlocked
14262      */
14263     @UnsupportedAppUsage
14264     public void setAssistBlocked(boolean enabled) {
14265         if (enabled) {
14266             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
14267         } else {
14268             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
14269         }
14270     }
14271 
14272     /**
14273      * Indicates whether this view will save its state (that is,
14274      * whether its {@link #onSaveInstanceState} method will be called).
14275      *
14276      * @return Returns true if the view state saving is enabled, else false.
14277      *
14278      * @see #setSaveEnabled(boolean)
14279      * @attr ref android.R.styleable#View_saveEnabled
14280      */
14281     @InspectableProperty
14282     public boolean isSaveEnabled() {
14283         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
14284     }
14285 
14286     /**
14287      * Controls whether the saving of this view's state is
14288      * enabled (that is, whether its {@link #onSaveInstanceState} method
14289      * will be called).  Note that even if freezing is enabled, the
14290      * view still must have an id assigned to it (via {@link #setId(int)})
14291      * for its state to be saved.  This flag can only disable the
14292      * saving of this view; any child views may still have their state saved.
14293      *
14294      * @param enabled Set to false to <em>disable</em> state saving, or true
14295      * (the default) to allow it.
14296      *
14297      * @see #isSaveEnabled()
14298      * @see #setId(int)
14299      * @see #onSaveInstanceState()
14300      * @attr ref android.R.styleable#View_saveEnabled
14301      */
14302     public void setSaveEnabled(boolean enabled) {
14303         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
14304     }
14305 
14306     /**
14307      * Gets whether the framework should discard touches when the view's
14308      * window is obscured by another visible window at the touched location.
14309      * Refer to the {@link View} security documentation for more details.
14310      *
14311      * @return True if touch filtering is enabled.
14312      *
14313      * @see #setFilterTouchesWhenObscured(boolean)
14314      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
14315      */
14316     @ViewDebug.ExportedProperty
14317     @InspectableProperty
14318     public boolean getFilterTouchesWhenObscured() {
14319         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
14320     }
14321 
14322     /**
14323      * Sets whether the framework should discard touches when the view's
14324      * window is obscured by another visible window at the touched location.
14325      * Refer to the {@link View} security documentation for more details.
14326      *
14327      * @param enabled True if touch filtering should be enabled.
14328      *
14329      * @see #getFilterTouchesWhenObscured
14330      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
14331      */
14332     public void setFilterTouchesWhenObscured(boolean enabled) {
14333         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
14334                 FILTER_TOUCHES_WHEN_OBSCURED);
14335         calculateAccessibilityDataSensitive();
14336     }
14337 
14338     /**
14339      * Indicates whether the entire hierarchy under this view will save its
14340      * state when a state saving traversal occurs from its parent.  The default
14341      * is true; if false, these views will not be saved unless
14342      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
14343      *
14344      * @return Returns true if the view state saving from parent is enabled, else false.
14345      *
14346      * @see #setSaveFromParentEnabled(boolean)
14347      */
14348     public boolean isSaveFromParentEnabled() {
14349         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
14350     }
14351 
14352     /**
14353      * Controls whether the entire hierarchy under this view will save its
14354      * state when a state saving traversal occurs from its parent.  The default
14355      * is true; if false, these views will not be saved unless
14356      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
14357      *
14358      * @param enabled Set to false to <em>disable</em> state saving, or true
14359      * (the default) to allow it.
14360      *
14361      * @see #isSaveFromParentEnabled()
14362      * @see #setId(int)
14363      * @see #onSaveInstanceState()
14364      */
14365     public void setSaveFromParentEnabled(boolean enabled) {
14366         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
14367     }
14368 
14369 
14370     /**
14371      * Returns whether this View is currently able to take focus.
14372      *
14373      * @return True if this view can take focus, or false otherwise.
14374      */
14375     @ViewDebug.ExportedProperty(category = "focus")
14376     public final boolean isFocusable() {
14377         return FOCUSABLE == (mViewFlags & FOCUSABLE);
14378     }
14379 
14380     /**
14381      * Returns the focusable setting for this view.
14382      *
14383      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
14384      * @attr ref android.R.styleable#View_focusable
14385      */
14386     @ViewDebug.ExportedProperty(mapping = {
14387             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
14388             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
14389             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
14390             }, category = "focus")
14391     @InspectableProperty(enumMapping = {
14392             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
14393             @EnumEntry(value = FOCUSABLE, name = "true"),
14394             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
14395     })
14396     @Focusable
14397     public int getFocusable() {
14398         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
14399     }
14400 
14401     /**
14402      * When a view is focusable, it may not want to take focus when in touch mode.
14403      * For example, a button would like focus when the user is navigating via a D-pad
14404      * so that the user can click on it, but once the user starts touching the screen,
14405      * the button shouldn't take focus
14406      * @return Whether the view is focusable in touch mode.
14407      * @attr ref android.R.styleable#View_focusableInTouchMode
14408      */
14409     @ViewDebug.ExportedProperty(category = "focus")
14410     @InspectableProperty
14411     public final boolean isFocusableInTouchMode() {
14412         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
14413     }
14414 
14415     /**
14416      * Returns whether the view should be treated as a focusable unit by screen reader
14417      * accessibility tools.
14418      * <p>
14419      * <b>Note:</b> Use
14420      * {@link androidx.core.view.ViewCompat#setScreenReaderFocusable(View, boolean)}
14421      * for backwards-compatibility. </aside>
14422      * @see #setScreenReaderFocusable(boolean)
14423      *
14424      * @return Whether the view should be treated as a focusable unit by screen reader.
14425      *
14426      * @attr ref android.R.styleable#View_screenReaderFocusable
14427      */
14428     @InspectableProperty
14429     public boolean isScreenReaderFocusable() {
14430         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
14431     }
14432 
14433     /**
14434      * Sets whether this View should be a focusable element for screen readers
14435      * and include non-focusable Views from its subtree when providing feedback.
14436      * <p>
14437      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
14438      * but does not impact input focus behavior.
14439      *
14440      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
14441      *                              accessibility tools.
14442      *
14443      * @attr ref android.R.styleable#View_screenReaderFocusable
14444      */
14445     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
14446         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
14447     }
14448 
14449     /**
14450      * Gets whether this view is a heading for accessibility purposes.
14451      *
14452      * @return {@code true} if the view is a heading, {@code false} otherwise.
14453      *
14454      * @attr ref android.R.styleable#View_accessibilityHeading
14455      */
14456     @InspectableProperty
14457     public boolean isAccessibilityHeading() {
14458         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
14459     }
14460 
14461     /**
14462      * Set if view is a heading for a section of content for accessibility purposes.
14463      * <p>
14464      * Users of some accessibility services can choose to navigate between headings
14465      * instead of between paragraphs, words, etc. Apps that provide headings on
14466      * sections of text can help the text navigation experience.
14467      * <p>
14468      * <b>Note:</b> Use {@link androidx.core.view.ViewCompat#setAccessibilityHeading(View, boolean)}
14469      * for backwards-compatibility. </aside>
14470      *
14471      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
14472      *
14473      * @attr ref android.R.styleable#View_accessibilityHeading
14474      */
14475     public void setAccessibilityHeading(boolean isHeading) {
14476         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
14477     }
14478 
14479     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
14480         int pflags3 = mPrivateFlags3;
14481         if (newValue) {
14482             pflags3 |= mask;
14483         } else {
14484             pflags3 &= ~mask;
14485         }
14486 
14487         if (pflags3 != mPrivateFlags3) {
14488             mPrivateFlags3 = pflags3;
14489             notifyViewAccessibilityStateChangedIfNeeded(
14490                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14491         }
14492     }
14493 
14494     /**
14495      * Find the nearest view in the specified direction that can take focus.
14496      * This does not actually give focus to that view.
14497      *
14498      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
14499      *
14500      * @return The nearest focusable in the specified direction, or null if none
14501      *         can be found.
14502      */
14503     public View focusSearch(@FocusRealDirection int direction) {
14504         if (mParent != null) {
14505             return mParent.focusSearch(this, direction);
14506         } else {
14507             return null;
14508         }
14509     }
14510 
14511     /**
14512      * Returns whether this View is a root of a keyboard navigation cluster.
14513      *
14514      * @return True if this view is a root of a cluster, or false otherwise.
14515      * @attr ref android.R.styleable#View_keyboardNavigationCluster
14516      */
14517     @ViewDebug.ExportedProperty(category = "focus")
14518     @InspectableProperty
14519     public final boolean isKeyboardNavigationCluster() {
14520         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
14521     }
14522 
14523     /**
14524      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
14525      * will be ignored.
14526      *
14527      * @return the keyboard navigation cluster that this view is in (can be this view)
14528      *         or {@code null} if not in one
14529      */
14530     View findKeyboardNavigationCluster() {
14531         if (mParent instanceof View) {
14532             View cluster = ((View) mParent).findKeyboardNavigationCluster();
14533             if (cluster != null) {
14534                 return cluster;
14535             } else if (isKeyboardNavigationCluster()) {
14536                 return this;
14537             }
14538         }
14539         return null;
14540     }
14541 
14542     /**
14543      * Set whether this view is a root of a keyboard navigation cluster.
14544      *
14545      * @param isCluster If true, this view is a root of a cluster.
14546      *
14547      * @attr ref android.R.styleable#View_keyboardNavigationCluster
14548      */
14549     public void setKeyboardNavigationCluster(boolean isCluster) {
14550         if (isCluster) {
14551             mPrivateFlags3 |= PFLAG3_CLUSTER;
14552         } else {
14553             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
14554         }
14555     }
14556 
14557     /**
14558      * Sets this View as the one which receives focus the next time cluster navigation jumps
14559      * to the cluster containing this View. This does NOT change focus even if the cluster
14560      * containing this view is current.
14561      *
14562      * @hide
14563      */
14564     @TestApi
14565     public final void setFocusedInCluster() {
14566         setFocusedInCluster(findKeyboardNavigationCluster());
14567     }
14568 
14569     private void setFocusedInCluster(View cluster) {
14570         if (this instanceof ViewGroup) {
14571             ((ViewGroup) this).mFocusedInCluster = null;
14572         }
14573         if (cluster == this) {
14574             return;
14575         }
14576         ViewParent parent = mParent;
14577         View child = this;
14578         while (parent instanceof ViewGroup) {
14579             ((ViewGroup) parent).mFocusedInCluster = child;
14580             if (parent == cluster) {
14581                 break;
14582             }
14583             child = (View) parent;
14584             parent = parent.getParent();
14585         }
14586     }
14587 
14588     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
14589         if (oldFocus != null) {
14590             View oldCluster = oldFocus.findKeyboardNavigationCluster();
14591             View cluster = findKeyboardNavigationCluster();
14592             if (oldCluster != cluster) {
14593                 // Going from one cluster to another, so save last-focused.
14594                 // This covers cluster jumps because they are always FOCUS_DOWN
14595                 oldFocus.setFocusedInCluster(oldCluster);
14596                 if (!(oldFocus.mParent instanceof ViewGroup)) {
14597                     return;
14598                 }
14599                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
14600                     // This is a result of ordered navigation so consider navigation through
14601                     // the previous cluster "complete" and clear its last-focused memory.
14602                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
14603                 } else if (oldFocus instanceof ViewGroup
14604                         && ((ViewGroup) oldFocus).getDescendantFocusability()
14605                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
14606                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
14607                     // This means oldFocus is not focusable since it obviously has a focusable
14608                     // child (this). Don't restore focus to it in the future.
14609                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
14610                 }
14611             }
14612         }
14613     }
14614 
14615     /**
14616      * Returns whether this View should receive focus when the focus is restored for the view
14617      * hierarchy containing this view.
14618      * <p>
14619      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
14620      * window or serves as a target of cluster navigation.
14621      *
14622      * @see #restoreDefaultFocus()
14623      *
14624      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
14625      * @attr ref android.R.styleable#View_focusedByDefault
14626      */
14627     @ViewDebug.ExportedProperty(category = "focus")
14628     @InspectableProperty
14629     public final boolean isFocusedByDefault() {
14630         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
14631     }
14632 
14633     /**
14634      * Sets whether this View should receive focus when the focus is restored for the view
14635      * hierarchy containing this view.
14636      * <p>
14637      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
14638      * window or serves as a target of cluster navigation.
14639      *
14640      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
14641      *                           {@code false} otherwise.
14642      *
14643      * @see #restoreDefaultFocus()
14644      *
14645      * @attr ref android.R.styleable#View_focusedByDefault
14646      */
14647     @RemotableViewMethod
14648     public void setFocusedByDefault(boolean isFocusedByDefault) {
14649         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
14650             return;
14651         }
14652 
14653         if (isFocusedByDefault) {
14654             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
14655         } else {
14656             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
14657         }
14658 
14659         if (mParent instanceof ViewGroup) {
14660             if (isFocusedByDefault) {
14661                 ((ViewGroup) mParent).setDefaultFocus(this);
14662             } else {
14663                 ((ViewGroup) mParent).clearDefaultFocus(this);
14664             }
14665         }
14666     }
14667 
14668     /**
14669      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
14670      *
14671      * @return {@code true} if this view has default focus, {@code false} otherwise
14672      */
14673     boolean hasDefaultFocus() {
14674         return isFocusedByDefault();
14675     }
14676 
14677     /**
14678      * Find the nearest keyboard navigation cluster in the specified direction.
14679      * This does not actually give focus to that cluster.
14680      *
14681      * @param currentCluster The starting point of the search. Null means the current cluster is not
14682      *                       found yet
14683      * @param direction Direction to look
14684      *
14685      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
14686      *         can be found
14687      */
14688     public View keyboardNavigationClusterSearch(View currentCluster,
14689             @FocusDirection int direction) {
14690         if (isKeyboardNavigationCluster()) {
14691             currentCluster = this;
14692         }
14693         if (isRootNamespace()) {
14694             // Root namespace means we should consider ourselves the top of the
14695             // tree for group searching; otherwise we could be group searching
14696             // into other tabs.  see LocalActivityManager and TabHost for more info.
14697             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
14698                     this, currentCluster, direction);
14699         } else if (mParent != null) {
14700             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
14701         }
14702         return null;
14703     }
14704 
14705     /**
14706      * This method is the last chance for the focused view and its ancestors to
14707      * respond to an arrow key. This is called when the focused view did not
14708      * consume the key internally, nor could the view system find a new view in
14709      * the requested direction to give focus to.
14710      *
14711      * @param focused The currently focused view.
14712      * @param direction The direction focus wants to move. One of FOCUS_UP,
14713      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
14714      * @return True if the this view consumed this unhandled move.
14715      */
14716     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
14717         return false;
14718     }
14719 
14720     /**
14721      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
14722      * have {@link android.R.attr#state_focused} defined in its background.
14723      *
14724      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
14725      *                                      highlight, {@code false} otherwise.
14726      *
14727      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
14728      */
14729     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
14730         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
14731     }
14732 
14733     /**
14734      * Returns whether this View should use a default focus highlight when it gets focused but
14735      * doesn't have {@link android.R.attr#state_focused} defined in its background.
14736      *
14737      * @return True if this View should use a default focus highlight.
14738      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
14739      */
14740     @ViewDebug.ExportedProperty(category = "focus")
14741     @InspectableProperty
14742     public final boolean getDefaultFocusHighlightEnabled() {
14743         return mDefaultFocusHighlightEnabled;
14744     }
14745 
14746     /**
14747      * If a user manually specified the next view id for a particular direction,
14748      * use the root to look up the view.
14749      * @param root The root view of the hierarchy containing this view.
14750      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
14751      * or FOCUS_BACKWARD.
14752      * @return The user specified next view, or null if there is none.
14753      */
14754     View findUserSetNextFocus(View root, @FocusDirection int direction) {
14755         switch (direction) {
14756             case FOCUS_LEFT:
14757                 if (mNextFocusLeftId == View.NO_ID) return null;
14758                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
14759             case FOCUS_RIGHT:
14760                 if (mNextFocusRightId == View.NO_ID) return null;
14761                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
14762             case FOCUS_UP:
14763                 if (mNextFocusUpId == View.NO_ID) return null;
14764                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
14765             case FOCUS_DOWN:
14766                 if (mNextFocusDownId == View.NO_ID) return null;
14767                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
14768             case FOCUS_FORWARD:
14769                 if (mNextFocusForwardId == View.NO_ID) return null;
14770                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
14771             case FOCUS_BACKWARD: {
14772                 if (mID == View.NO_ID) return null;
14773                 final View rootView = root;
14774                 final View startView = this;
14775                 // Since we have forward links but no backward links, we need to find the view that
14776                 // forward links to this view. We can't just find the view with the specified ID
14777                 // because view IDs need not be unique throughout the tree.
14778                 return root.findViewByPredicateInsideOut(startView,
14779                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
14780                             == startView);
14781             }
14782         }
14783         return null;
14784     }
14785 
14786     /**
14787      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
14788      * use the root to look up the view.
14789      *
14790      * @param root the root view of the hierarchy containing this view
14791      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
14792      * @return the user-specified next cluster, or {@code null} if there is none
14793      */
14794     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
14795         switch (direction) {
14796             case FOCUS_FORWARD:
14797                 if (mNextClusterForwardId == View.NO_ID) return null;
14798                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
14799             case FOCUS_BACKWARD: {
14800                 if (mID == View.NO_ID) return null;
14801                 final int id = mID;
14802                 return root.findViewByPredicateInsideOut(this,
14803                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
14804             }
14805         }
14806         return null;
14807     }
14808 
14809     private View findViewInsideOutShouldExist(View root, int id) {
14810         return findViewInsideOutShouldExist(root, this, id);
14811     }
14812 
14813     private View findViewInsideOutShouldExist(View root, View start, int id) {
14814         if (mMatchIdPredicate == null) {
14815             mMatchIdPredicate = new MatchIdPredicate();
14816         }
14817         mMatchIdPredicate.mId = id;
14818         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
14819         if (result == null) {
14820             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
14821         }
14822         return result;
14823     }
14824 
14825     /**
14826      * Find and return all focusable views that are descendants of this view,
14827      * possibly including this view if it is focusable itself.
14828      *
14829      * @param direction The direction of the focus
14830      * @return A list of focusable views
14831      */
14832     public ArrayList<View> getFocusables(@FocusDirection int direction) {
14833         ArrayList<View> result = new ArrayList<View>(24);
14834         addFocusables(result, direction);
14835         return result;
14836     }
14837 
14838     /**
14839      * Add any focusable views that are descendants of this view (possibly
14840      * including this view if it is focusable itself) to views.  If we are in touch mode,
14841      * only add views that are also focusable in touch mode.
14842      *
14843      * @param views Focusable views found so far
14844      * @param direction The direction of the focus
14845      */
14846     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
14847         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
14848     }
14849 
14850     /**
14851      * Adds any focusable views that are descendants of this view (possibly
14852      * including this view if it is focusable itself) to views. This method
14853      * adds all focusable views regardless if we are in touch mode or
14854      * only views focusable in touch mode if we are in touch mode or
14855      * only views that can take accessibility focus if accessibility is enabled
14856      * depending on the focusable mode parameter.
14857      *
14858      * @param views Focusable views found so far or null if all we are interested is
14859      *        the number of focusables.
14860      * @param direction The direction of the focus.
14861      * @param focusableMode The type of focusables to be added.
14862      *
14863      * @see #FOCUSABLES_ALL
14864      * @see #FOCUSABLES_TOUCH_MODE
14865      */
14866     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
14867             @FocusableMode int focusableMode) {
14868         if (views == null) {
14869             return;
14870         }
14871         if (!canTakeFocus()) {
14872             return;
14873         }
14874         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
14875                 && !isFocusableInTouchMode()) {
14876             return;
14877         }
14878         views.add(this);
14879     }
14880 
14881     /**
14882      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
14883      * including this view if it is a cluster root itself) to views.
14884      *
14885      * @param views Keyboard navigation cluster roots found so far
14886      * @param direction Direction to look
14887      */
14888     public void addKeyboardNavigationClusters(
14889             @NonNull Collection<View> views,
14890             int direction) {
14891         if (!isKeyboardNavigationCluster()) {
14892             return;
14893         }
14894         if (!hasFocusable()) {
14895             return;
14896         }
14897         views.add(this);
14898     }
14899 
14900     /**
14901      * Finds the Views that contain given text. The containment is case insensitive.
14902      * The search is performed by either the text that the View renders or the content
14903      * description that describes the view for accessibility purposes and the view does
14904      * not render or both. Clients can specify how the search is to be performed via
14905      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
14906      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
14907      *
14908      * @param outViews The output list of matching Views.
14909      * @param searched The text to match against.
14910      *
14911      * @see #FIND_VIEWS_WITH_TEXT
14912      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
14913      * @see #setContentDescription(CharSequence)
14914      */
14915     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
14916             @FindViewFlags int flags) {
14917         if (getAccessibilityNodeProvider() != null) {
14918             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
14919                 outViews.add(this);
14920             }
14921         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
14922                 && (searched != null && searched.length() > 0)
14923                 && (mContentDescription != null && mContentDescription.length() > 0)) {
14924             String searchedLowerCase = searched.toString().toLowerCase();
14925             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
14926             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
14927                 outViews.add(this);
14928             }
14929         }
14930     }
14931 
14932     /**
14933      * Find and return all touchable views that are descendants of this view,
14934      * possibly including this view if it is touchable itself.
14935      *
14936      * @return A list of touchable views
14937      */
14938     public ArrayList<View> getTouchables() {
14939         ArrayList<View> result = new ArrayList<View>();
14940         addTouchables(result);
14941         return result;
14942     }
14943 
14944     /**
14945      * Add any touchable views that are descendants of this view (possibly
14946      * including this view if it is touchable itself) to views.
14947      *
14948      * @param views Touchable views found so far
14949      */
14950     public void addTouchables(ArrayList<View> views) {
14951         final int viewFlags = mViewFlags;
14952 
14953         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
14954                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
14955                 && (viewFlags & ENABLED_MASK) == ENABLED) {
14956             views.add(this);
14957         }
14958     }
14959 
14960     /**
14961      * Returns whether this View is accessibility focused.
14962      *
14963      * @return True if this View is accessibility focused.
14964      */
14965     @InspectableProperty(hasAttributeId = false)
14966     public boolean isAccessibilityFocused() {
14967         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
14968     }
14969 
14970     /**
14971      * Call this to try to give accessibility focus to this view.
14972      *
14973      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
14974      * returns false or the view is no visible or the view already has accessibility
14975      * focus.
14976      *
14977      * See also {@link #focusSearch(int)}, which is what you call to say that you
14978      * have focus, and you want your parent to look for the next one.
14979      *
14980      * <p>
14981      * <b>Note:</b> Avoid setting accessibility focus. This is intended to be controlled by screen
14982      * readers. Apps changing focus can confuse screen readers, so the resulting behavior can vary
14983      * by device and screen reader version.
14984      *
14985      * @return Whether this view actually took accessibility focus.
14986      *
14987      * @hide
14988      */
14989     @UnsupportedAppUsage
14990     public boolean requestAccessibilityFocus() {
14991         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
14992         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
14993             return false;
14994         }
14995         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
14996             return false;
14997         }
14998         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
14999             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
15000             ViewRootImpl viewRootImpl = getViewRootImpl();
15001             if (viewRootImpl != null) {
15002                 viewRootImpl.setAccessibilityFocus(this, null);
15003             }
15004             invalidate();
15005             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
15006             return true;
15007         }
15008         return false;
15009     }
15010 
15011     /**
15012      * Call this to try to clear accessibility focus of this view.
15013      *
15014      * See also {@link #focusSearch(int)}, which is what you call to say that you
15015      * have focus, and you want your parent to look for the next one.
15016      *
15017      * @hide
15018      */
15019     @UnsupportedAppUsage
15020     public void clearAccessibilityFocus() {
15021         clearAccessibilityFocusNoCallbacks(0);
15022 
15023         // Clear the global reference of accessibility focus if this view or
15024         // any of its descendants had accessibility focus. This will NOT send
15025         // an event or update internal state if focus is cleared from a
15026         // descendant view, which may leave views in inconsistent states.
15027         final ViewRootImpl viewRootImpl = getViewRootImpl();
15028         if (viewRootImpl != null) {
15029             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
15030             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
15031                 viewRootImpl.setAccessibilityFocus(null, null);
15032             }
15033         }
15034     }
15035 
15036     private void sendAccessibilityHoverEvent(int eventType) {
15037         // Since we are not delivering to a client accessibility events from not
15038         // important views (unless the clinet request that) we need to fire the
15039         // event from the deepest view exposed to the client. As a consequence if
15040         // the user crosses a not exposed view the client will see enter and exit
15041         // of the exposed predecessor followed by and enter and exit of that same
15042         // predecessor when entering and exiting the not exposed descendant. This
15043         // is fine since the client has a clear idea which view is hovered at the
15044         // price of a couple more events being sent. This is a simple and
15045         // working solution.
15046         View source = this;
15047         while (true) {
15048             if (source.includeForAccessibility(false)) {
15049                 source.sendAccessibilityEvent(eventType);
15050                 return;
15051             }
15052             ViewParent parent = source.getParent();
15053             if (parent instanceof View) {
15054                 source = (View) parent;
15055             } else {
15056                 return;
15057             }
15058         }
15059     }
15060 
15061     /**
15062      * Clears accessibility focus without calling any callback methods
15063      * normally invoked in {@link #clearAccessibilityFocus()}. This method
15064      * is used separately from that one for clearing accessibility focus when
15065      * giving this focus to another view.
15066      *
15067      * @param action The action, if any, that led to focus being cleared. Set to
15068      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
15069      * the window.
15070      */
15071     void clearAccessibilityFocusNoCallbacks(int action) {
15072         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
15073             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
15074             invalidate();
15075             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
15076                 AccessibilityEvent event = AccessibilityEvent.obtain(
15077                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
15078                 event.setAction(action);
15079                 if (mAccessibilityDelegate != null) {
15080                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
15081                 } else {
15082                     sendAccessibilityEventUnchecked(event);
15083                 }
15084             }
15085 
15086             updatePreferKeepClearForFocus();
15087         }
15088     }
15089 
15090     /**
15091      * Call this to try to give focus to a specific view or to one of its
15092      * descendants.
15093      *
15094      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
15095      * false), or if it can't be focused due to other conditions (not focusable in touch mode
15096      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
15097      * enabled, or has no size).
15098      *
15099      * See also {@link #focusSearch(int)}, which is what you call to say that you
15100      * have focus, and you want your parent to look for the next one.
15101      *
15102      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
15103      * {@link #FOCUS_DOWN} and <code>null</code>.
15104      *
15105      * @return Whether this view or one of its descendants actually took focus.
15106      */
15107     public final boolean requestFocus() {
15108         return requestFocus(View.FOCUS_DOWN);
15109     }
15110 
15111     /**
15112      * This will request focus for whichever View was last focused within this
15113      * cluster before a focus-jump out of it.
15114      *
15115      * @hide
15116      */
15117     @TestApi
15118     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
15119         // Prioritize focusableByDefault over algorithmic focus selection.
15120         if (restoreDefaultFocus()) {
15121             return true;
15122         }
15123         return requestFocus(direction);
15124     }
15125 
15126     /**
15127      * This will request focus for whichever View not in a cluster was last focused before a
15128      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
15129      * the "first" focusable view it finds.
15130      *
15131      * @hide
15132      */
15133     @TestApi
15134     public boolean restoreFocusNotInCluster() {
15135         return requestFocus(View.FOCUS_DOWN);
15136     }
15137 
15138     /**
15139      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
15140      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
15141      *
15142      * @return Whether this view or one of its descendants actually took focus
15143      */
15144     public boolean restoreDefaultFocus() {
15145         return requestFocus(View.FOCUS_DOWN);
15146     }
15147 
15148     /**
15149      * Call this to try to give focus to a specific view or to one of its
15150      * descendants and give it a hint about what direction focus is heading.
15151      *
15152      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
15153      * false), or if it is focusable and it is not focusable in touch mode
15154      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
15155      *
15156      * See also {@link #focusSearch(int)}, which is what you call to say that you
15157      * have focus, and you want your parent to look for the next one.
15158      *
15159      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
15160      * <code>null</code> set for the previously focused rectangle.
15161      *
15162      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
15163      * @return Whether this view or one of its descendants actually took focus.
15164      */
15165     public final boolean requestFocus(int direction) {
15166         return requestFocus(direction, null);
15167     }
15168 
15169     /**
15170      * Call this to try to give focus to a specific view or to one of its descendants
15171      * and give it hints about the direction and a specific rectangle that the focus
15172      * is coming from.  The rectangle can help give larger views a finer grained hint
15173      * about where focus is coming from, and therefore, where to show selection, or
15174      * forward focus change internally.
15175      *
15176      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
15177      * false), or if it is focusable and it is not focusable in touch mode
15178      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
15179      *
15180      * A View will not take focus if it is not visible.
15181      *
15182      * A View will not take focus if one of its parents has
15183      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
15184      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
15185      *
15186      * See also {@link #focusSearch(int)}, which is what you call to say that you
15187      * have focus, and you want your parent to look for the next one.
15188      *
15189      * You may wish to override this method if your custom {@link View} has an internal
15190      * {@link View} that it wishes to forward the request to.
15191      *
15192      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
15193      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
15194      *        to give a finer grained hint about where focus is coming from.  May be null
15195      *        if there is no hint.
15196      * @return Whether this view or one of its descendants actually took focus.
15197      */
15198     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
15199         return requestFocusNoSearch(direction, previouslyFocusedRect);
15200     }
15201 
15202     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
15203         // need to be focusable
15204         if (!canTakeFocus()) {
15205             return false;
15206         }
15207 
15208         // need to be focusable in touch mode if in touch mode
15209         if (isInTouchMode() &&
15210             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
15211                return false;
15212         }
15213 
15214         // need to not have any parents blocking us
15215         if (hasAncestorThatBlocksDescendantFocus()) {
15216             return false;
15217         }
15218 
15219         if (!isLayoutValid()) {
15220             mPrivateFlags |= PFLAG_WANTS_FOCUS;
15221         } else {
15222             clearParentsWantFocus();
15223         }
15224 
15225         handleFocusGainInternal(direction, previouslyFocusedRect);
15226         return true;
15227     }
15228 
15229     void clearParentsWantFocus() {
15230         if (mParent instanceof View) {
15231             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
15232             ((View) mParent).clearParentsWantFocus();
15233         }
15234     }
15235 
15236     /**
15237      * Call this to try to give focus to a specific view or to one of its descendants. This is a
15238      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
15239      * touch mode to request focus when they are touched.
15240      *
15241      * @return Whether this view or one of its descendants actually took focus.
15242      *
15243      * @see #isInTouchMode()
15244      *
15245      */
15246     public final boolean requestFocusFromTouch() {
15247         // Leave touch mode if we need to
15248         if (isInTouchMode()) {
15249             ViewRootImpl viewRoot = getViewRootImpl();
15250             if (viewRoot != null) {
15251                 viewRoot.ensureTouchMode(false);
15252             }
15253         }
15254         return requestFocus(View.FOCUS_DOWN);
15255     }
15256 
15257     /**
15258      * @return Whether any ancestor of this view blocks descendant focus.
15259      */
15260     private boolean hasAncestorThatBlocksDescendantFocus() {
15261         final boolean focusableInTouchMode = isFocusableInTouchMode();
15262         ViewParent ancestor = mParent;
15263         while (ancestor instanceof ViewGroup) {
15264             final ViewGroup vgAncestor = (ViewGroup) ancestor;
15265             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
15266                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
15267                 return true;
15268             } else {
15269                 ancestor = vgAncestor.getParent();
15270             }
15271         }
15272         return false;
15273     }
15274 
15275     /**
15276      * Gets the mode for determining whether this View is important for accessibility.
15277      * A view is important for accessibility if it fires accessibility events and if it
15278      * is reported to accessibility services that query the screen.
15279      *
15280      * @return The mode for determining whether a view is important for accessibility, one
15281      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
15282      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
15283      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
15284      *
15285      * @attr ref android.R.styleable#View_importantForAccessibility
15286      *
15287      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
15288      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
15289      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
15290      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
15291      */
15292     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
15293             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
15294             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
15295             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
15296             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
15297                     to = "noHideDescendants")
15298         })
15299     @InspectableProperty(enumMapping = {
15300             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
15301             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
15302             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
15303             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
15304                     name = "noHideDescendants"),
15305     })
15306     public int getImportantForAccessibility() {
15307         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
15308                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
15309     }
15310 
15311     /**
15312      * Sets the live region mode for this view. This indicates to accessibility
15313      * services whether they should automatically notify the user about changes
15314      * to the view's content description or text, or to the content descriptions
15315      * or text of the view's children (where applicable).
15316      * <p>
15317      * Different priority levels are available:
15318      * <ul>
15319      *   <li>
15320      *       {@link #ACCESSIBILITY_LIVE_REGION_POLITE}:
15321      *       Indicates that updates to the region should be presented to the user. Suitable in most
15322      *       cases for prominent updates within app content that don't require the user's immediate
15323      *       attention.
15324      *   </li>
15325      *   <li>
15326      *       {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}: Indicates that updates to the region have
15327      *       the highest priority and should be presented to the user immediately. This may result
15328      *       in disruptive notifications from an accessibility service, which may potentially
15329      *       interrupt other feedback or user actions, so it should generally be used only for
15330      *       critical, time-sensitive information.
15331      *   </li>
15332      *   <li>
15333      *       {@link #ACCESSIBILITY_LIVE_REGION_NONE}: Disables change announcements (the default for
15334      *       most views).
15335      *   </li>
15336      * </ul>
15337      * <p>
15338      * Examples:
15339      * <ul>
15340      *     <li>
15341      *         Selecting an option in a dropdown menu updates a panel below with the updated
15342      *         content. This panel may be marked as a live region with
15343      *         {@link #ACCESSIBILITY_LIVE_REGION_POLITE} to notify users of the change. A screen
15344      *         reader may queue changes as announcements that don't disrupt ongoing speech.
15345      *      </li>
15346      *      <li>
15347      *          An emergency alert may be marked with {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
15348      *          to immediately inform users of the emergency.
15349      *      </li>
15350      * </ul>
15351      * <p>
15352      * For error notifications, like an "incorrect password" warning in a login screen, views
15353      * should send a {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
15354      * {@code AccessibilityEvent} with a content change type
15355      * {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR} and set
15356      * {@link AccessibilityNodeInfo#setError(CharSequence)}. Custom widgets should provide
15357      * error-setting methods that support accessibility. For example, use
15358      * {@link android.widget.TextView#setError(CharSequence)} instead of explicitly sending events.
15359      * <p>
15360      * Don't use live regions for frequently-updating UI elements (e.g., progress bars), as this can
15361      * overwhelm the user with feedback from accessibility services. If necessary, use
15362      * {@link AccessibilityNodeInfo#setMinDurationBetweenContentChanges(Duration)} to throttle
15363      * feedback and reduce disruptions.
15364      * <p>
15365      * <aside><b>Note:</b> Use
15366      * {@link androidx.core.view.ViewCompat#setAccessibilityLiveRegion(View, int)}
15367      * for backwards-compatibility. </aside>
15368      *
15369      * @param mode The live region mode for this view, one of:
15370      *        <ul>
15371      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
15372      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
15373      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
15374      *        </ul>
15375      * @attr ref android.R.styleable#View_accessibilityLiveRegion
15376      */
setAccessibilityLiveRegion(int mode)15377     public void setAccessibilityLiveRegion(int mode) {
15378         if (mode != getAccessibilityLiveRegion()) {
15379             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
15380             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
15381                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
15382             notifyViewAccessibilityStateChangedIfNeeded(
15383                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15384         }
15385     }
15386 
15387     /**
15388      * Gets the live region mode for this View.
15389      *
15390      * @return The live region mode for the view.
15391      *
15392      * @attr ref android.R.styleable#View_accessibilityLiveRegion
15393      *
15394      * @see #setAccessibilityLiveRegion(int)
15395      */
15396     @InspectableProperty(enumMapping = {
15397             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
15398             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
15399             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
15400     })
getAccessibilityLiveRegion()15401     public int getAccessibilityLiveRegion() {
15402         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
15403                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
15404     }
15405 
15406     /**
15407      * Sets how to determine whether this view is important for accessibility
15408      * which is if it fires accessibility events and if it is reported to
15409      * accessibility services that query the screen.
15410      *
15411      * @param mode How to determine whether this view is important for accessibility.
15412      *
15413      * @attr ref android.R.styleable#View_importantForAccessibility
15414      *
15415      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
15416      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
15417      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
15418      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
15419      */
setImportantForAccessibility(int mode)15420     public void setImportantForAccessibility(int mode) {
15421         final int oldMode = getImportantForAccessibility();
15422         if (mode != oldMode) {
15423             final boolean hideDescendants =
15424                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
15425 
15426             // If this node or its descendants are no longer important, try to
15427             // clear accessibility focus.
15428             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
15429                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
15430                 if (focusHost != null) {
15431                     focusHost.clearAccessibilityFocus();
15432                 }
15433             }
15434 
15435             // If we're moving between AUTO and another state, we might not need
15436             // to send a subtree changed notification. We'll store the computed
15437             // importance, since we'll need to check it later to make sure.
15438             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
15439                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
15440             final boolean oldIncludeForAccessibility =
15441                     maySkipNotify && includeForAccessibility(false);
15442             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
15443             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
15444                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
15445             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility(false)) {
15446                 notifySubtreeAccessibilityStateChangedIfNeeded();
15447             } else {
15448                 notifyViewAccessibilityStateChangedIfNeeded(
15449                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15450             }
15451         }
15452     }
15453 
15454     /**
15455      * Returns the view within this view's hierarchy that is hosting
15456      * accessibility focus.
15457      *
15458      * @param searchDescendants whether to search for focus in descendant views
15459      * @return the view hosting accessibility focus, or {@code null}
15460      */
findAccessibilityFocusHost(boolean searchDescendants)15461     private View findAccessibilityFocusHost(boolean searchDescendants) {
15462         if (isAccessibilityFocusedViewOrHost()) {
15463             return this;
15464         }
15465 
15466         if (searchDescendants) {
15467             final ViewRootImpl viewRoot = getViewRootImpl();
15468             if (viewRoot != null) {
15469                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
15470                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
15471                     return focusHost;
15472                 }
15473             }
15474         }
15475 
15476         return null;
15477     }
15478 
15479     /**
15480      * Computes whether this view should be exposed for accessibility. In
15481      * general, views that are interactive or provide information are exposed
15482      * while views that serve only as containers are hidden.
15483      * <p>
15484      * If an ancestor of this view has importance
15485      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
15486      * returns <code>false</code>.
15487      * <p>
15488      * Otherwise, the value is computed according to the view's
15489      * {@link #getImportantForAccessibility()} value:
15490      * <ol>
15491      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
15492      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
15493      * </code>
15494      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
15495      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
15496      * view satisfies any of the following:
15497      * <ul>
15498      * <li>Is actionable, e.g. {@link #isClickable()},
15499      * {@link #isLongClickable()}, {@link #isContextClickable()},
15500      * {@link #isScreenReaderFocusable()}, or {@link #isFocusable()}
15501      * <li>Has an {@link AccessibilityDelegate}
15502      * <li>Has an {@link AccessibilityNodeProvider}
15503      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
15504      * {@link OnKeyListener}, etc.
15505      * <li>Is an accessibility live region, e.g.
15506      * {@link #getAccessibilityLiveRegion()} is not
15507      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
15508      * </ul>
15509      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
15510      * <li>Is an accessibility heading, see {@link #setAccessibilityHeading(boolean)}.</li>
15511      * </ol>
15512      *
15513      * @return Whether the view is exposed for accessibility.
15514      * @see #setImportantForAccessibility(int)
15515      * @see #getImportantForAccessibility()
15516      */
isImportantForAccessibility()15517     public boolean isImportantForAccessibility() {
15518         final int mode = getImportantForAccessibility();
15519         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
15520                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
15521             return false;
15522         }
15523 
15524         // Check parent mode to ensure we're not hidden.
15525         ViewParent parent = mParent;
15526         while (parent instanceof View) {
15527             if (((View) parent).getImportantForAccessibility()
15528                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
15529                 return false;
15530             }
15531             parent = parent.getParent();
15532         }
15533 
15534         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
15535                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
15536                 || getAccessibilityDelegate() != null
15537                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
15538                 || isAccessibilityPane() || isAccessibilityHeading();
15539     }
15540 
15541     /**
15542      * Gets the parent for accessibility purposes. Note that the parent for
15543      * accessibility is not necessary the immediate parent. It is the first
15544      * predecessor that is important for accessibility.
15545      *
15546      * @return The parent for accessibility purposes.
15547      */
getParentForAccessibility()15548     public ViewParent getParentForAccessibility() {
15549         if (mParent instanceof View) {
15550             View parentView = (View) mParent;
15551             if (parentView.includeForAccessibility()) {
15552                 return mParent;
15553             } else {
15554                 return mParent.getParentForAccessibility();
15555             }
15556         }
15557         return null;
15558     }
15559 
15560     /** @hide */
15561     @Nullable
getSelfOrParentImportantForA11y()15562     View getSelfOrParentImportantForA11y() {
15563         if (isImportantForAccessibility()) return this;
15564         ViewParent parent = getParentForAccessibility();
15565         if (parent instanceof View) return (View) parent;
15566         return null;
15567     }
15568 
15569     /**
15570      * Adds the children of this View relevant for accessibility to the given list
15571      * as output. Since some Views are not important for accessibility the added
15572      * child views are not necessarily direct children of this view, rather they are
15573      * the first level of descendants important for accessibility.
15574      *
15575      * @param outChildren The output list that will receive children for accessibility.
15576      */
addChildrenForAccessibility(ArrayList<View> outChildren)15577     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
15578 
15579     }
15580 
15581     /**
15582      * @see #includeForAccessibility(boolean)
15583      * @hide
15584      */
15585     @UnsupportedAppUsage
includeForAccessibility()15586     public boolean includeForAccessibility() {
15587         return includeForAccessibility(true);
15588     }
15589 
15590     /**
15591      * Whether to regard this view for accessibility.
15592      *
15593      * <p>
15594      * If this decision is used for generating the accessibility node tree then this returns false
15595      * for {@link #isAccessibilityDataPrivate()} views queried by non-accessibility tools.
15596      * </p>
15597      * <p>
15598      * Otherwise, a view is regarded for accessibility if:
15599      * <li>the view returns true for {@link #isImportantForAccessibility()}, or</li>
15600      * <li>the querying accessibility service has explicitly requested that views not important for
15601      * accessibility are regarded by setting
15602      * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}</li>
15603      * </p>
15604      *
15605      * @param forNodeTree True if the result of this function will be used for generating a node
15606      *                    tree, otherwise false (like when sending {@link AccessibilityEvent}s).
15607      * @return Whether to regard the view for accessibility.
15608      * @hide
15609      */
includeForAccessibility(boolean forNodeTree)15610     public boolean includeForAccessibility(boolean forNodeTree) {
15611         if (mAttachInfo == null) {
15612             return false;
15613         }
15614 
15615         if (forNodeTree) {
15616             // The AccessibilityDataPrivate property should not effect whether this View is
15617             // included for consideration when sending AccessibilityEvents. Events copy their
15618             // source View's AccessibilityDataPrivate value, and then filtering is done when
15619             // AccessibilityManagerService propagates events to each recipient AccessibilityService.
15620             if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
15621                     && isAccessibilityDataSensitive()) {
15622                 return false;
15623             }
15624         }
15625 
15626         return (mAttachInfo.mAccessibilityFetchFlags
15627                 & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
15628                 || isImportantForAccessibility();
15629     }
15630 
15631     /**
15632      * Whether this view should restrict accessibility service access only to services that have the
15633      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
15634      * set to true.
15635      *
15636      * <p>
15637      * See default behavior provided by {@link #ACCESSIBILITY_DATA_SENSITIVE_AUTO}. Otherwise,
15638      * returns true for {@link #ACCESSIBILITY_DATA_SENSITIVE_YES} or false for {@link
15639      * #ACCESSIBILITY_DATA_SENSITIVE_NO}.
15640      * </p>
15641      *
15642      * @return True if this view should restrict accessibility service access to services that have
15643      * the isAccessibilityTool property.
15644      */
15645     @ViewDebug.ExportedProperty(category = "accessibility")
isAccessibilityDataSensitive()15646     public boolean isAccessibilityDataSensitive() {
15647         if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
15648             calculateAccessibilityDataSensitive();
15649         }
15650         return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
15651     }
15652 
15653     /**
15654      * Calculate and cache the inferred value for {@link #isAccessibilityDataSensitive()}.
15655      *
15656      * <p>
15657      * <strong>Note:</strong> This method needs to be called any time one of the below conditions
15658      * changes, to recalculate the new value.
15659      * </p>
15660      */
calculateAccessibilityDataSensitive()15661     void calculateAccessibilityDataSensitive() {
15662         // Use the explicit value if set.
15663         if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
15664             mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
15665         } else if (getFilterTouchesWhenObscured()) {
15666             // Views that set filterTouchesWhenObscured default to accessibilityDataSensitive.
15667             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
15668         } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
15669             // Descendants of accessibilityDataSensitive Views are also accessibilityDataSensitive.
15670             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
15671         } else {
15672             // Otherwise, default to not accessibilityDataSensitive.
15673             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
15674         }
15675     }
15676 
15677     /**
15678      * Specifies whether this view should only allow interactions from
15679      * {@link android.accessibilityservice.AccessibilityService}s with the
15680      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
15681      * set to true.
15682      */
setAccessibilityDataSensitive( @ccessibilityDataSensitive int accessibilityDataSensitive)15683     public void setAccessibilityDataSensitive(
15684             @AccessibilityDataSensitive int accessibilityDataSensitive) {
15685         mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
15686         calculateAccessibilityDataSensitive();
15687     }
15688 
15689     /**
15690      * Returns whether the View is considered actionable from
15691      * accessibility perspective. Such view are important for
15692      * accessibility.
15693      *
15694      * @return True if the view is actionable for accessibility.
15695      *
15696      * @hide
15697      */
isActionableForAccessibility()15698     public boolean isActionableForAccessibility() {
15699         return (isClickable() || isLongClickable() || isFocusable() || isContextClickable()
15700                 || isScreenReaderFocusable());
15701     }
15702 
15703     /**
15704      * Returns whether the View has registered callbacks which makes it
15705      * important for accessibility.
15706      *
15707      * @return True if the view is actionable for accessibility.
15708      */
hasListenersForAccessibility()15709     private boolean hasListenersForAccessibility() {
15710         ListenerInfo info = getListenerInfo();
15711         return mTouchDelegate != null || info.mOnKeyListener != null
15712                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
15713                 || info.mOnHoverListener != null || info.mOnDragListener != null;
15714     }
15715 
15716     /**
15717      * Notifies that the accessibility state of this view changed. The change
15718      * is local to this view and does not represent structural changes such
15719      * as children and parent. For example, the view became focusable. Some of
15720      * the notification is at at most once every
15721      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
15722      * to avoid unnecessary load to the system. Also once a view has a pending
15723      * notification this method is a NOP until the notification has been sent.
15724      *
15725      * @hide
15726      */
15727     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyViewAccessibilityStateChangedIfNeeded(int changeType)15728     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
15729         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
15730             return;
15731         }
15732 
15733         // Changes to views with a pane title count as window state changes, as the pane title
15734         // marks them as significant parts of the UI. A visible view with a nulled title may send
15735         // a disappeared event.
15736         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
15737                 && (isAccessibilityPane()
15738                 || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)
15739                 && isAggregatedVisible())) {
15740             // If the pane isn't visible, content changed events are sufficient unless we're
15741             // reporting that the view just disappeared
15742             if ((isAggregatedVisible())
15743                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
15744                 final AccessibilityEvent event = AccessibilityEvent.obtain();
15745                 onInitializeAccessibilityEvent(event);
15746                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
15747                 event.setContentChangeTypes(changeType);
15748                 event.setSource(this);
15749                 onPopulateAccessibilityEvent(event);
15750                 if (mParent != null) {
15751                     try {
15752                         mParent.requestSendAccessibilityEvent(this, event);
15753                     } catch (AbstractMethodError e) {
15754                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
15755                                 + " does not fully implement ViewParent", e);
15756                     }
15757                 }
15758                 return;
15759             }
15760         }
15761 
15762         // If this is a live region, we should send a subtree change event
15763         // from this view immediately. Otherwise, we can let it propagate up.
15764         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
15765             final AccessibilityEvent event = AccessibilityEvent.obtain();
15766             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
15767             event.setContentChangeTypes(changeType);
15768             sendAccessibilityEventUnchecked(event);
15769         } else if (mParent != null) {
15770             try {
15771                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
15772             } catch (AbstractMethodError e) {
15773                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15774                         " does not fully implement ViewParent", e);
15775             }
15776         }
15777     }
15778 
15779     /**
15780      * Notifies that the accessibility state of this view changed. The change
15781      * is *not* local to this view and does represent structural changes such
15782      * as children and parent. For example, the view size changed. Some of the
15783      * notification is at at most once every
15784      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
15785      * to avoid unnecessary load to the system. Also once a view has a pending
15786      * notification this method is a NOP until the notification has been sent.
15787      *
15788      * @hide
15789      */
15790     @UnsupportedAppUsage
notifySubtreeAccessibilityStateChangedIfNeeded()15791     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
15792         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
15793             return;
15794         }
15795 
15796         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
15797             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
15798             if (mParent != null) {
15799                 try {
15800                     mParent.notifySubtreeAccessibilityStateChanged(
15801                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
15802                 } catch (AbstractMethodError e) {
15803                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15804                             " does not fully implement ViewParent", e);
15805                 }
15806             }
15807         }
15808     }
15809 
notifySubtreeAccessibilityStateChangedByParentIfNeeded()15810     private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
15811         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
15812             return;
15813         }
15814 
15815         final View sendA11yEventView = (View) getParentForAccessibility();
15816         if (sendA11yEventView != null && sendA11yEventView.isShown()) {
15817             sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
15818         }
15819     }
15820 
15821     /**
15822      * Changes the visibility of this View without triggering any other changes. This should only
15823      * be used by animation frameworks, such as {@link android.transition.Transition}, where
15824      * visibility changes should not adjust focus or trigger a new layout. Application developers
15825      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
15826      *
15827      * <p>Only call this method when a temporary visibility must be applied during an
15828      * animation and the original visibility value is guaranteed to be reset after the
15829      * animation completes. Use {@link #setVisibility} in all other cases.</p>
15830      *
15831      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
15832      * @see #setVisibility(int)
15833      */
setTransitionVisibility(@isibility int visibility)15834     public void setTransitionVisibility(@Visibility int visibility) {
15835         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
15836     }
15837 
15838     /**
15839      * Reset the flag indicating the accessibility state of the subtree rooted
15840      * at this view changed.
15841      */
resetSubtreeAccessibilityStateChanged()15842     void resetSubtreeAccessibilityStateChanged() {
15843         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
15844     }
15845 
15846     /**
15847      * Report an accessibility action to this view's parents for delegated processing.
15848      *
15849      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
15850      * call this method to delegate an accessibility action to a supporting parent. If the parent
15851      * returns true from its
15852      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
15853      * method this method will return true to signify that the action was consumed.</p>
15854      *
15855      * <p>This method is useful for implementing nested scrolling child views. If
15856      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
15857      * a custom view implementation may invoke this method to allow a parent to consume the
15858      * scroll first. If this method returns true the custom view should skip its own scrolling
15859      * behavior.</p>
15860      *
15861      * @param action Accessibility action to delegate
15862      * @param arguments Optional action arguments
15863      * @return true if the action was consumed by a parent
15864      */
dispatchNestedPrePerformAccessibilityAction(int action, @Nullable Bundle arguments)15865     public boolean dispatchNestedPrePerformAccessibilityAction(int action,
15866             @Nullable Bundle arguments) {
15867         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
15868             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
15869                 return true;
15870             }
15871         }
15872         return false;
15873     }
15874 
15875     /**
15876      * Performs the specified accessibility action on the view. For
15877      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
15878      * <p>
15879      * If an {@link AccessibilityDelegate} has been specified via calling
15880      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
15881      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
15882      * is responsible for handling this call.
15883      * </p>
15884      *
15885      * <p>The default implementation will delegate
15886      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
15887      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
15888      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
15889      *
15890      * <p>
15891      * <b>Note:</b> Avoid setting accessibility focus with
15892      * {@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}. This is intended to be controlled
15893      * by screen readers. Apps changing focus can confuse screen readers, so the resulting behavior
15894      * can vary by device and screen reader version.
15895      *
15896      * @param action The action to perform.
15897      * @param arguments Optional action arguments.
15898      * @return Whether the action was performed.
15899      */
performAccessibilityAction(int action, @Nullable Bundle arguments)15900     public boolean performAccessibilityAction(int action, @Nullable Bundle arguments) {
15901       if (mAccessibilityDelegate != null) {
15902           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
15903       } else {
15904           return performAccessibilityActionInternal(action, arguments);
15905       }
15906     }
15907 
15908     /**
15909      * @see #performAccessibilityAction(int, Bundle)
15910      *
15911      * Note: Called from the default {@link AccessibilityDelegate}.
15912      *
15913      * @hide
15914      */
15915     @UnsupportedAppUsage
performAccessibilityActionInternal(int action, @Nullable Bundle arguments)15916     public boolean performAccessibilityActionInternal(int action, @Nullable Bundle arguments) {
15917         if (isNestedScrollingEnabled()
15918                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
15919                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
15920                 || action == R.id.accessibilityActionScrollUp
15921                 || action == R.id.accessibilityActionScrollLeft
15922                 || action == R.id.accessibilityActionScrollDown
15923                 || action == R.id.accessibilityActionScrollRight)) {
15924             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
15925                 return true;
15926             }
15927         }
15928 
15929         switch (action) {
15930             case AccessibilityNodeInfo.ACTION_CLICK: {
15931                 if (isClickable()) {
15932                     performClickInternal();
15933                     return true;
15934                 }
15935             } break;
15936             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
15937                 if (isLongClickable()) {
15938                     performLongClick();
15939                     return true;
15940                 }
15941             } break;
15942             case AccessibilityNodeInfo.ACTION_FOCUS: {
15943                 if (!hasFocus()) {
15944                     // Get out of touch mode since accessibility
15945                     // wants to move focus around.
15946                     getViewRootImpl().ensureTouchMode(false);
15947                     return requestFocus();
15948                 }
15949             } break;
15950             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
15951                 if (hasFocus()) {
15952                     clearFocus();
15953                     return !isFocused();
15954                 }
15955             } break;
15956             case AccessibilityNodeInfo.ACTION_SELECT: {
15957                 if (!isSelected()) {
15958                     setSelected(true);
15959                     return isSelected();
15960                 }
15961             } break;
15962             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
15963                 if (isSelected()) {
15964                     setSelected(false);
15965                     return !isSelected();
15966                 }
15967             } break;
15968             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
15969                 if (!isAccessibilityFocused()) {
15970                     return requestAccessibilityFocus();
15971                 }
15972             } break;
15973             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
15974                 if (isAccessibilityFocused()) {
15975                     clearAccessibilityFocus();
15976                     return true;
15977                 }
15978             } break;
15979             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
15980                 if (arguments != null) {
15981                     final int granularity = arguments.getInt(
15982                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
15983                     final boolean extendSelection = arguments.getBoolean(
15984                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
15985                     return traverseAtGranularity(granularity, true, extendSelection);
15986                 }
15987             } break;
15988             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
15989                 if (arguments != null) {
15990                     final int granularity = arguments.getInt(
15991                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
15992                     final boolean extendSelection = arguments.getBoolean(
15993                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
15994                     return traverseAtGranularity(granularity, false, extendSelection);
15995                 }
15996             } break;
15997             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
15998                 CharSequence text = getIterableTextForAccessibility();
15999                 if (text == null) {
16000                     return false;
16001                 }
16002                 final int start = (arguments != null) ? arguments.getInt(
16003                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
16004                 final int end = (arguments != null) ? arguments.getInt(
16005                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
16006                 // Only cursor position can be specified (selection length == 0)
16007                 if ((getAccessibilitySelectionStart() != start
16008                         || getAccessibilitySelectionEnd() != end)
16009                         && (start == end)) {
16010                     setAccessibilitySelection(start, end);
16011                     notifyViewAccessibilityStateChangedIfNeeded(
16012                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16013                     return true;
16014                 }
16015             } break;
16016             case R.id.accessibilityActionShowOnScreen: {
16017                 if (mAttachInfo != null) {
16018                     final Rect r = mAttachInfo.mTmpInvalRect;
16019                     getDrawingRect(r);
16020                     return requestRectangleOnScreen(r, true);
16021                 }
16022             } break;
16023             case R.id.accessibilityActionContextClick: {
16024                 if (isContextClickable()) {
16025                     performContextClick();
16026                     return true;
16027                 }
16028             } break;
16029             case R.id.accessibilityActionShowTooltip: {
16030                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
16031                     // Tooltip already showing
16032                     return false;
16033                 }
16034                 return showLongClickTooltip(0, 0);
16035             }
16036             case R.id.accessibilityActionHideTooltip: {
16037                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
16038                     // No tooltip showing
16039                     return false;
16040                 }
16041                 hideTooltip();
16042                 return true;
16043             }
16044             case R.id.accessibilityActionDragDrop: {
16045                 if (!canAcceptAccessibilityDrop()) {
16046                     return false;
16047                 }
16048                 try {
16049                     if (mAttachInfo != null && mAttachInfo.mSession != null) {
16050                         final int[] location = new int[2];
16051                         getLocationInWindow(location);
16052                         final int centerX = location[0] + getWidth() / 2;
16053                         final int centerY = location[1] + getHeight() / 2;
16054                         return mAttachInfo.mSession.dropForAccessibility(mAttachInfo.mWindow,
16055                                 centerX, centerY);
16056                     }
16057                 } catch (RemoteException e) {
16058                     Log.e(VIEW_LOG_TAG, "Unable to drop for accessibility", e);
16059                 }
16060                 return false;
16061             }
16062             case R.id.accessibilityActionDragCancel: {
16063                 if (!startedSystemDragForAccessibility()) {
16064                     return false;
16065                 }
16066                 if (mAttachInfo != null && mAttachInfo.mDragToken != null) {
16067                     cancelDragAndDrop();
16068                     return true;
16069                 }
16070                 return false;
16071             }
16072         }
16073         return false;
16074     }
16075 
canAcceptAccessibilityDrop()16076     private boolean canAcceptAccessibilityDrop() {
16077         if (!canAcceptDrag()) {
16078             return false;
16079         }
16080         ListenerInfo li = mListenerInfo;
16081         return (li != null) && (li.mOnDragListener != null || li.mOnReceiveContentListener != null);
16082     }
16083 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)16084     private boolean traverseAtGranularity(int granularity, boolean forward,
16085             boolean extendSelection) {
16086         CharSequence text = getIterableTextForAccessibility();
16087         if (text == null || text.length() == 0) {
16088             return false;
16089         }
16090         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
16091         if (iterator == null) {
16092             return false;
16093         }
16094         int current = getAccessibilitySelectionEnd();
16095         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
16096             current = forward ? 0 : text.length();
16097         }
16098         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
16099         if (range == null) {
16100             return false;
16101         }
16102         final int segmentStart = range[0];
16103         final int segmentEnd = range[1];
16104         int selectionStart;
16105         int selectionEnd;
16106         if (extendSelection && isAccessibilitySelectionExtendable()) {
16107             prepareForExtendedAccessibilitySelection();
16108             selectionStart = getAccessibilitySelectionStart();
16109             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
16110                 selectionStart = forward ? segmentStart : segmentEnd;
16111             }
16112             selectionEnd = forward ? segmentEnd : segmentStart;
16113         } else {
16114             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
16115         }
16116         setAccessibilitySelection(selectionStart, selectionEnd);
16117         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
16118                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
16119         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
16120         return true;
16121     }
16122 
16123     /**
16124      * Gets the text reported for accessibility purposes.
16125      *
16126      * @return The accessibility text.
16127      *
16128      * @hide
16129      */
16130     @UnsupportedAppUsage
getIterableTextForAccessibility()16131     public CharSequence getIterableTextForAccessibility() {
16132         return getContentDescription();
16133     }
16134 
16135     /**
16136      * Gets whether accessibility selection can be extended.
16137      *
16138      * @return If selection is extensible.
16139      *
16140      * @hide
16141      */
isAccessibilitySelectionExtendable()16142     public boolean isAccessibilitySelectionExtendable() {
16143         return false;
16144     }
16145 
16146     /**
16147      * Prepare for extended selection.
16148      * @hide
16149      */
prepareForExtendedAccessibilitySelection()16150     public void prepareForExtendedAccessibilitySelection() {
16151         return;
16152     }
16153 
16154     /**
16155      * @hide
16156      */
getAccessibilitySelectionStart()16157     public int getAccessibilitySelectionStart() {
16158         return mAccessibilityCursorPosition;
16159     }
16160 
16161     /**
16162      * @hide
16163      */
getAccessibilitySelectionEnd()16164     public int getAccessibilitySelectionEnd() {
16165         return getAccessibilitySelectionStart();
16166     }
16167 
16168     /**
16169      * @hide
16170      */
setAccessibilitySelection(int start, int end)16171     public void setAccessibilitySelection(int start, int end) {
16172         if (start ==  end && end == mAccessibilityCursorPosition) {
16173             return;
16174         }
16175         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
16176             mAccessibilityCursorPosition = start;
16177         } else {
16178             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
16179         }
16180         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
16181     }
16182 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)16183     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
16184             int fromIndex, int toIndex) {
16185         if (mParent == null) {
16186             return;
16187         }
16188         AccessibilityEvent event = AccessibilityEvent.obtain(
16189                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
16190         onInitializeAccessibilityEvent(event);
16191         onPopulateAccessibilityEvent(event);
16192         event.setFromIndex(fromIndex);
16193         event.setToIndex(toIndex);
16194         event.setAction(action);
16195         event.setMovementGranularity(granularity);
16196         mParent.requestSendAccessibilityEvent(this, event);
16197     }
16198 
16199     /**
16200      * @hide
16201      */
16202     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getIteratorForGranularity(int granularity)16203     public TextSegmentIterator getIteratorForGranularity(int granularity) {
16204         switch (granularity) {
16205             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
16206                 CharSequence text = getIterableTextForAccessibility();
16207                 if (text != null && text.length() > 0) {
16208                     CharacterTextSegmentIterator iterator =
16209                         CharacterTextSegmentIterator.getInstance(
16210                                 mContext.getResources().getConfiguration().locale);
16211                     iterator.initialize(text.toString());
16212                     return iterator;
16213                 }
16214             } break;
16215             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
16216                 CharSequence text = getIterableTextForAccessibility();
16217                 if (text != null && text.length() > 0) {
16218                     WordTextSegmentIterator iterator =
16219                         WordTextSegmentIterator.getInstance(
16220                                 mContext.getResources().getConfiguration().locale);
16221                     iterator.initialize(text.toString());
16222                     return iterator;
16223                 }
16224             } break;
16225             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
16226                 CharSequence text = getIterableTextForAccessibility();
16227                 if (text != null && text.length() > 0) {
16228                     ParagraphTextSegmentIterator iterator =
16229                         ParagraphTextSegmentIterator.getInstance();
16230                     iterator.initialize(text.toString());
16231                     return iterator;
16232                 }
16233             } break;
16234         }
16235         return null;
16236     }
16237 
16238     /**
16239      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
16240      * and {@link #onFinishTemporaryDetach()}.
16241      *
16242      * <p>This method always returns {@code true} when called directly or indirectly from
16243      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
16244      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
16245      * <ul>
16246      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
16247      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
16248      * </ul>
16249      * </p>
16250      *
16251      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
16252      * and {@link #onFinishTemporaryDetach()}.
16253      */
isTemporarilyDetached()16254     public final boolean isTemporarilyDetached() {
16255         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
16256     }
16257 
16258     /**
16259      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
16260      * a container View.
16261      */
16262     @CallSuper
dispatchStartTemporaryDetach()16263     public void dispatchStartTemporaryDetach() {
16264         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
16265         notifyEnterOrExitForAutoFillIfNeeded(false);
16266         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
16267         onStartTemporaryDetach();
16268     }
16269 
16270     /**
16271      * This is called when a container is going to temporarily detach a child, with
16272      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
16273      * It will either be followed by {@link #onFinishTemporaryDetach()} or
16274      * {@link #onDetachedFromWindow()} when the container is done.
16275      */
onStartTemporaryDetach()16276     public void onStartTemporaryDetach() {
16277         removeUnsetPressCallback();
16278         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
16279     }
16280 
16281     /**
16282      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
16283      * a container View.
16284      */
16285     @CallSuper
dispatchFinishTemporaryDetach()16286     public void dispatchFinishTemporaryDetach() {
16287         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16288         onFinishTemporaryDetach();
16289         if (hasWindowFocus() && hasFocus()) {
16290             notifyFocusChangeToImeFocusController(true /* hasFocus */);
16291         }
16292         notifyEnterOrExitForAutoFillIfNeeded(true);
16293         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
16294     }
16295 
16296     /**
16297      * Called after {@link #onStartTemporaryDetach} when the container is done
16298      * changing the view.
16299      */
onFinishTemporaryDetach()16300     public void onFinishTemporaryDetach() {
16301     }
16302 
16303     /**
16304      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
16305      * for this view's window.  Returns null if the view is not currently attached
16306      * to the window.  Normally you will not need to use this directly, but
16307      * just use the standard high-level event callbacks like
16308      * {@link #onKeyDown(int, KeyEvent)}.
16309      */
getKeyDispatcherState()16310     public KeyEvent.DispatcherState getKeyDispatcherState() {
16311         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
16312     }
16313 
16314     /**
16315      * Dispatch a key event before it is processed by any input method
16316      * associated with the view hierarchy.  This can be used to intercept
16317      * key events in special situations before the IME consumes them; a
16318      * typical example would be handling the BACK key to update the application's
16319      * UI instead of allowing the IME to see it and close itself.
16320      *
16321      * @param event The key event to be dispatched.
16322      * @return True if the event was handled, false otherwise.
16323      */
dispatchKeyEventPreIme(KeyEvent event)16324     public boolean dispatchKeyEventPreIme(KeyEvent event) {
16325         return onKeyPreIme(event.getKeyCode(), event);
16326     }
16327 
16328     /**
16329      * Dispatch a key event to the next view on the focus path. This path runs
16330      * from the top of the view tree down to the currently focused view. If this
16331      * view has focus, it will dispatch to itself. Otherwise it will dispatch
16332      * the next node down the focus path. This method also fires any key
16333      * listeners.
16334      *
16335      * @param event The key event to be dispatched.
16336      * @return True if the event was handled, false otherwise.
16337      */
dispatchKeyEvent(KeyEvent event)16338     public boolean dispatchKeyEvent(KeyEvent event) {
16339         if (mInputEventConsistencyVerifier != null) {
16340             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
16341         }
16342 
16343         // Give any attached key listener a first crack at the event.
16344         //noinspection SimplifiableIfStatement
16345         ListenerInfo li = mListenerInfo;
16346         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16347                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
16348             return true;
16349         }
16350 
16351         if (event.dispatch(this, mAttachInfo != null
16352                 ? mAttachInfo.mKeyDispatchState : null, this)) {
16353             return true;
16354         }
16355 
16356         if (mInputEventConsistencyVerifier != null) {
16357             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16358         }
16359         return false;
16360     }
16361 
16362     /**
16363      * Dispatches a key shortcut event.
16364      *
16365      * @param event The key event to be dispatched.
16366      * @return True if the event was handled by the view, false otherwise.
16367      */
dispatchKeyShortcutEvent(KeyEvent event)16368     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
16369         return onKeyShortcut(event.getKeyCode(), event);
16370     }
16371 
16372     /**
16373      * Pass the touch screen motion event down to the target view, or this
16374      * view if it is the target.
16375      *
16376      * @param event The motion event to be dispatched.
16377      * @return True if the event was handled by the view, false otherwise.
16378      *
16379      * @see #onTouchEvent(MotionEvent)
16380      */
dispatchTouchEvent(MotionEvent event)16381     public boolean dispatchTouchEvent(MotionEvent event) {
16382         // If the event should be handled by accessibility focus first.
16383         if (event.isTargetAccessibilityFocus()) {
16384             // We don't have focus or no virtual descendant has it, do not handle the event.
16385             if (!isAccessibilityFocusedViewOrHost()) {
16386                 return false;
16387             }
16388             // We have focus and got the event, then use normal event dispatch.
16389             event.setTargetAccessibilityFocus(false);
16390         }
16391         boolean result = false;
16392 
16393         if (mInputEventConsistencyVerifier != null) {
16394             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
16395         }
16396 
16397         final int actionMasked = event.getActionMasked();
16398         if (actionMasked == MotionEvent.ACTION_DOWN) {
16399             // Defensive cleanup for new gesture
16400             stopNestedScroll();
16401         }
16402 
16403         if (onFilterTouchEventForSecurity(event)) {
16404             result = performOnTouchCallback(event);
16405         }
16406 
16407         if (!result && mInputEventConsistencyVerifier != null) {
16408             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16409         }
16410 
16411         // Clean up after nested scrolls if this is the end of a gesture;
16412         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
16413         // of the gesture.
16414         if (actionMasked == MotionEvent.ACTION_UP ||
16415                 actionMasked == MotionEvent.ACTION_CANCEL ||
16416                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
16417             stopNestedScroll();
16418         }
16419 
16420         return result;
16421     }
16422 
16423     /**
16424      * Returns {@code true} if the {@link MotionEvent} from {@link #dispatchTouchEvent} was
16425      * handled by this view.
16426      */
performOnTouchCallback(MotionEvent event)16427     private boolean performOnTouchCallback(MotionEvent event) {
16428         boolean handled = false;
16429         if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
16430             handled = true;
16431         }
16432         //noinspection SimplifiableIfStatement
16433         ListenerInfo li = mListenerInfo;
16434         if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED) {
16435             try {
16436                 Trace.traceBegin(TRACE_TAG_VIEW, "View.onTouchListener#onTouch");
16437                 handled = li.mOnTouchListener.onTouch(this, event);
16438             } finally {
16439                 Trace.traceEnd(TRACE_TAG_VIEW);
16440             }
16441         }
16442         if (handled) {
16443             return true;
16444         }
16445         try {
16446             Trace.traceBegin(TRACE_TAG_VIEW, "View#onTouchEvent");
16447             return onTouchEvent(event);
16448         } finally {
16449             Trace.traceEnd(TRACE_TAG_VIEW);
16450         }
16451     }
16452 
isAccessibilityFocusedViewOrHost()16453     boolean isAccessibilityFocusedViewOrHost() {
16454         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
16455                 .getAccessibilityFocusedHost() == this);
16456     }
16457 
16458     /**
16459      * Returns whether this view can receive pointer events.
16460      *
16461      * @return {@code true} if this view can receive pointer events.
16462      * @hide
16463      */
canReceivePointerEvents()16464     protected boolean canReceivePointerEvents() {
16465         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
16466     }
16467 
16468     /**
16469      * Filter the touch event to apply security policies.
16470      *
16471      * @param event The motion event to be filtered.
16472      * @return True if the event should be dispatched, false if the event should be dropped.
16473      *
16474      * @see #getFilterTouchesWhenObscured
16475      */
onFilterTouchEventForSecurity(MotionEvent event)16476     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
16477         //noinspection RedundantIfStatement
16478         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
16479                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
16480             // Window is obscured, drop this touch.
16481             return false;
16482         }
16483         return true;
16484     }
16485 
16486     /**
16487      * Pass a trackball motion event down to the focused view.
16488      *
16489      * @param event The motion event to be dispatched.
16490      * @return True if the event was handled by the view, false otherwise.
16491      *
16492      * @see #onTrackballEvent(MotionEvent)
16493      */
dispatchTrackballEvent(MotionEvent event)16494     public boolean dispatchTrackballEvent(MotionEvent event) {
16495         if (mInputEventConsistencyVerifier != null) {
16496             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
16497         }
16498 
16499         return onTrackballEvent(event);
16500     }
16501 
16502     /**
16503      * Pass a captured pointer event down to the focused view.
16504      *
16505      * @param event The motion event to be dispatched.
16506      * @return True if the event was handled by the view, false otherwise.
16507      */
dispatchCapturedPointerEvent(MotionEvent event)16508     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
16509         if (!hasPointerCapture()) {
16510             return false;
16511         }
16512         //noinspection SimplifiableIfStatement
16513         ListenerInfo li = mListenerInfo;
16514         if (li != null && li.mOnCapturedPointerListener != null
16515                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
16516             return true;
16517         }
16518         return onCapturedPointerEvent(event);
16519     }
16520 
16521     /**
16522      * Dispatch a generic motion event.
16523      * <p>
16524      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
16525      * are delivered to the view under the pointer.  All other generic motion events are
16526      * delivered to the focused view.  Hover events are handled specially and are delivered
16527      * to {@link #onHoverEvent(MotionEvent)} first.
16528      * </p>
16529      *
16530      * @param event The motion event to be dispatched.
16531      * @return True if the event was handled by the view, false otherwise.
16532      *
16533      * @see #onHoverEvent(MotionEvent)
16534      * @see #onGenericMotionEvent(MotionEvent)
16535      */
dispatchGenericMotionEvent(MotionEvent event)16536     public boolean dispatchGenericMotionEvent(MotionEvent event) {
16537         if (mInputEventConsistencyVerifier != null) {
16538             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
16539         }
16540 
16541         final int source = event.getSource();
16542         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
16543             final int action = event.getAction();
16544             if (action == MotionEvent.ACTION_HOVER_ENTER
16545                     || action == MotionEvent.ACTION_HOVER_MOVE
16546                     || action == MotionEvent.ACTION_HOVER_EXIT) {
16547                 if (dispatchHoverEvent(event)) {
16548                     return true;
16549                 }
16550             } else if (dispatchGenericPointerEvent(event)) {
16551                 return true;
16552             }
16553         } else if (dispatchGenericFocusedEvent(event)) {
16554             return true;
16555         }
16556 
16557         if (dispatchGenericMotionEventInternal(event)) {
16558             return true;
16559         }
16560 
16561         if (mInputEventConsistencyVerifier != null) {
16562             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16563         }
16564         return false;
16565     }
16566 
dispatchGenericMotionEventInternal(MotionEvent event)16567     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
16568         final boolean isRotaryEncoderEvent = event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER);
16569         if (isRotaryEncoderEvent) {
16570             // Determine and cache rotary scroll haptics support if it's not yet determined.
16571             // Caching the support is important for two reasons:
16572             // 1) Limits call to `ViewConfiguration#get`, which we should avoid if possible.
16573             // 2) Limits latency from the `ViewConfiguration` API, which may be slow due to feature
16574             //    flag querying.
16575             if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_DETERMINED) == 0) {
16576                 if (ViewConfiguration.get(mContext)
16577                         .isViewBasedRotaryEncoderHapticScrollFeedbackEnabled()) {
16578                     mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_ENABLED;
16579                 }
16580                 mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_DETERMINED;
16581             }
16582         }
16583         final boolean processForRotaryScrollHaptics =
16584                 isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0);
16585         if (processForRotaryScrollHaptics) {
16586             mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
16587             mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
16588         }
16589 
16590         //noinspection SimplifiableIfStatement
16591         ListenerInfo li = mListenerInfo;
16592         if (li != null && li.mOnGenericMotionListener != null
16593                 && (mViewFlags & ENABLED_MASK) == ENABLED
16594                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
16595             return true;
16596         }
16597 
16598         final boolean onGenericMotionEventResult = onGenericMotionEvent(event);
16599         // Process scroll haptics after `onGenericMotionEvent`, since that's where scrolling usually
16600         // happens. Some views may return false from `onGenericMotionEvent` even if they have done
16601         // scrolling, so disregard the return value when processing for scroll haptics.
16602         if (processForRotaryScrollHaptics) {
16603             if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT) != 0) {
16604                 doRotaryProgressForScrollHaptics(event);
16605             } else {
16606                 doRotaryLimitForScrollHaptics(event);
16607             }
16608         }
16609         if (onGenericMotionEventResult) {
16610             return true;
16611         }
16612 
16613         final int actionButton = event.getActionButton();
16614         switch (event.getActionMasked()) {
16615             case MotionEvent.ACTION_BUTTON_PRESS:
16616                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
16617                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
16618                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
16619                     if (performContextClick(event.getX(), event.getY())) {
16620                         mInContextButtonPress = true;
16621                         setPressed(true, event.getX(), event.getY());
16622                         removeTapCallback();
16623                         removeLongPressCallback();
16624                         return true;
16625                     }
16626                 }
16627                 break;
16628 
16629             case MotionEvent.ACTION_BUTTON_RELEASE:
16630                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
16631                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
16632                     mInContextButtonPress = false;
16633                     mIgnoreNextUpEvent = true;
16634                 }
16635                 break;
16636         }
16637 
16638         if (mInputEventConsistencyVerifier != null) {
16639             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16640         }
16641         return false;
16642     }
16643 
16644     /**
16645      * Dispatch a hover event.
16646      * <p>
16647      * Do not call this method directly.
16648      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
16649      * </p>
16650      *
16651      * @param event The motion event to be dispatched.
16652      * @return True if the event was handled by the view, false otherwise.
16653      */
dispatchHoverEvent(MotionEvent event)16654     protected boolean dispatchHoverEvent(MotionEvent event) {
16655         ListenerInfo li = mListenerInfo;
16656         //noinspection SimplifiableIfStatement
16657         if (li != null && li.mOnHoverListener != null
16658                 && (mViewFlags & ENABLED_MASK) == ENABLED
16659                 && li.mOnHoverListener.onHover(this, event)) {
16660             return true;
16661         }
16662 
16663         return onHoverEvent(event);
16664     }
16665 
16666     /**
16667      * Returns true if the view has a child to which it has recently sent
16668      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
16669      * it does not have a hovered child, then it must be the innermost hovered view.
16670      * @hide
16671      */
hasHoveredChild()16672     protected boolean hasHoveredChild() {
16673         return false;
16674     }
16675 
16676     /**
16677      * Returns true if the given point, in local coordinates, is inside the hovered child.
16678      *
16679      * @hide
16680      */
pointInHoveredChild(MotionEvent event)16681     protected boolean pointInHoveredChild(MotionEvent event) {
16682         return false;
16683     }
16684 
16685     /**
16686      * Dispatch a generic motion event to the view under the first pointer.
16687      * <p>
16688      * Do not call this method directly.
16689      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
16690      * </p>
16691      *
16692      * @param event The motion event to be dispatched.
16693      * @return True if the event was handled by the view, false otherwise.
16694      */
dispatchGenericPointerEvent(MotionEvent event)16695     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
16696         return false;
16697     }
16698 
16699     /**
16700      * Dispatch a generic motion event to the currently focused view.
16701      * <p>
16702      * Do not call this method directly.
16703      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
16704      * </p>
16705      *
16706      * @param event The motion event to be dispatched.
16707      * @return True if the event was handled by the view, false otherwise.
16708      */
dispatchGenericFocusedEvent(MotionEvent event)16709     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
16710         return false;
16711     }
16712 
16713     /**
16714      * Dispatch a pointer event.
16715      * <p>
16716      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
16717      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
16718      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
16719      * and should not be expected to handle other pointing device features.
16720      * </p>
16721      *
16722      * @param event The motion event to be dispatched.
16723      * @return True if the event was handled by the view, false otherwise.
16724      * @hide
16725      */
16726     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchPointerEvent(MotionEvent event)16727     public final boolean dispatchPointerEvent(MotionEvent event) {
16728         if (event.isTouchEvent()) {
16729             return dispatchTouchEvent(event);
16730         } else {
16731             return dispatchGenericMotionEvent(event);
16732         }
16733     }
16734 
16735     /**
16736      * Called when the window containing this view gains or loses window focus.
16737      * ViewGroups should override to route to their children.
16738      *
16739      * @param hasFocus True if the window containing this view now has focus,
16740      *        false otherwise.
16741      */
dispatchWindowFocusChanged(boolean hasFocus)16742     public void dispatchWindowFocusChanged(boolean hasFocus) {
16743         onWindowFocusChanged(hasFocus);
16744     }
16745 
16746     /**
16747      * Called when the window containing this view gains or loses focus.  Note
16748      * that this is separate from view focus: to receive key events, both
16749      * your view and its window must have focus.  If a window is displayed
16750      * on top of yours that takes input focus, then your own window will lose
16751      * focus but the view focus will remain unchanged.
16752      *
16753      * @param hasWindowFocus True if the window containing this view now has
16754      *        focus, false otherwise.
16755      */
onWindowFocusChanged(boolean hasWindowFocus)16756     public void onWindowFocusChanged(boolean hasWindowFocus) {
16757         if (!hasWindowFocus) {
16758             if (isPressed()) {
16759                 setPressed(false);
16760             }
16761             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16762             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
16763                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
16764             }
16765             removeLongPressCallback();
16766             removeTapCallback();
16767             onFocusLost();
16768         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
16769             notifyFocusChangeToImeFocusController(true /* hasFocus */);
16770             ViewRootImpl viewRoot = getViewRootImpl();
16771             if (viewRoot != null && initiationWithoutInputConnection() && onCheckIsTextEditor()) {
16772                 viewRoot.getHandwritingInitiator().onEditorFocused(this);
16773             }
16774         }
16775 
16776         refreshDrawableState();
16777     }
16778 
16779     /**
16780      * Returns true if this view is in a window that currently has window focus.
16781      * Note that this is not the same as the view itself having focus.
16782      *
16783      * @return True if this view is in a window that currently has window focus.
16784      */
hasWindowFocus()16785     public boolean hasWindowFocus() {
16786         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
16787     }
16788 
16789     /**
16790      * @return {@code true} if this view is in a window that currently has IME focusable state.
16791      * @hide
16792      */
hasImeFocus()16793     public boolean hasImeFocus() {
16794         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
16795     }
16796 
16797     /**
16798      * Dispatch a view visibility change down the view hierarchy.
16799      * ViewGroups should override to route to their children.
16800      * @param changedView The view whose visibility changed. Could be 'this' or
16801      * an ancestor view.
16802      * @param visibility The new visibility of changedView: {@link #VISIBLE},
16803      * {@link #INVISIBLE} or {@link #GONE}.
16804      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)16805     protected void dispatchVisibilityChanged(@NonNull View changedView,
16806             @Visibility int visibility) {
16807         onVisibilityChanged(changedView, visibility);
16808     }
16809 
16810     /**
16811      * Called when the visibility of the view or an ancestor of the view has
16812      * changed.
16813      *
16814      * @param changedView The view whose visibility changed. May be
16815      *                    {@code this} or an ancestor view.
16816      * @param visibility The new visibility, one of {@link #VISIBLE},
16817      *                   {@link #INVISIBLE} or {@link #GONE}.
16818      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)16819     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
16820     }
16821 
16822     /**
16823      * Dispatch a hint about whether this view is displayed. For instance, when
16824      * a View moves out of the screen, it might receives a display hint indicating
16825      * the view is not displayed. Applications should not <em>rely</em> on this hint
16826      * as there is no guarantee that they will receive one.
16827      *
16828      * @param hint A hint about whether or not this view is displayed:
16829      * {@link #VISIBLE} or {@link #INVISIBLE}.
16830      */
dispatchDisplayHint(@isibility int hint)16831     public void dispatchDisplayHint(@Visibility int hint) {
16832         onDisplayHint(hint);
16833     }
16834 
16835     /**
16836      * Gives this view a hint about whether is displayed or not. For instance, when
16837      * a View moves out of the screen, it might receives a display hint indicating
16838      * the view is not displayed. Applications should not <em>rely</em> on this hint
16839      * as there is no guarantee that they will receive one.
16840      *
16841      * @param hint A hint about whether or not this view is displayed:
16842      * {@link #VISIBLE} or {@link #INVISIBLE}.
16843      */
onDisplayHint(@isibility int hint)16844     protected void onDisplayHint(@Visibility int hint) {
16845     }
16846 
16847     /**
16848      * Dispatch a window visibility change down the view hierarchy.
16849      * ViewGroups should override to route to their children.
16850      *
16851      * @param visibility The new visibility of the window.
16852      *
16853      * @see #onWindowVisibilityChanged(int)
16854      */
dispatchWindowVisibilityChanged(@isibility int visibility)16855     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
16856         onWindowVisibilityChanged(visibility);
16857     }
16858 
16859     /**
16860      * Called when the window containing has change its visibility
16861      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
16862      * that this tells you whether or not your window is being made visible
16863      * to the window manager; this does <em>not</em> tell you whether or not
16864      * your window is obscured by other windows on the screen, even if it
16865      * is itself visible.
16866      *
16867      * @param visibility The new visibility of the window.
16868      */
onWindowVisibilityChanged(@isibility int visibility)16869     protected void onWindowVisibilityChanged(@Visibility int visibility) {
16870         if (visibility == VISIBLE) {
16871             initialAwakenScrollBars();
16872         }
16873     }
16874 
16875     /**
16876      * @return true if this view and all ancestors are visible as of the last
16877      * {@link #onVisibilityAggregated(boolean)} call.
16878      *
16879      * @hide
16880      */
isAggregatedVisible()16881     public boolean isAggregatedVisible() {
16882         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
16883     }
16884 
16885     /**
16886      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
16887      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
16888      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
16889      *
16890      * @param isVisible true if this view's visibility to the user is uninterrupted by its
16891      *                  ancestors or by window visibility
16892      * @return true if this view is visible to the user, not counting clipping or overlapping
16893      */
dispatchVisibilityAggregated(boolean isVisible)16894     boolean dispatchVisibilityAggregated(boolean isVisible) {
16895         final boolean thisVisible = getVisibility() == VISIBLE;
16896         // If we're not visible but something is telling us we are, ignore it.
16897         if (thisVisible || !isVisible) {
16898             onVisibilityAggregated(isVisible);
16899         }
16900         return thisVisible && isVisible;
16901     }
16902 
16903     /**
16904      * Called when the user-visibility of this View is potentially affected by a change
16905      * to this view itself, an ancestor view or the window this view is attached to.
16906      *
16907      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
16908      *                  and this view's window is also visible
16909      */
16910     @CallSuper
onVisibilityAggregated(boolean isVisible)16911     public void onVisibilityAggregated(boolean isVisible) {
16912         // Update our internal visibility tracking so we can detect changes
16913         boolean oldVisible = isAggregatedVisible();
16914         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
16915                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
16916         if (isVisible && mAttachInfo != null) {
16917             initialAwakenScrollBars();
16918         }
16919 
16920         final Drawable dr = mBackground;
16921         if (dr != null && isVisible != dr.isVisible()) {
16922             dr.setVisible(isVisible, false);
16923         }
16924         final Drawable hl = mDefaultFocusHighlight;
16925         if (hl != null && isVisible != hl.isVisible()) {
16926             hl.setVisible(isVisible, false);
16927         }
16928         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16929         if (fg != null && isVisible != fg.isVisible()) {
16930             fg.setVisible(isVisible, false);
16931         }
16932         notifyAutofillManagerViewVisibilityChanged(isVisible);
16933         if (isVisible != oldVisible) {
16934             if (isAccessibilityPane()) {
16935                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
16936                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
16937                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
16938             }
16939 
16940             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
16941             updateSensitiveViewsCountIfNeeded(isVisible);
16942 
16943             if (!getSystemGestureExclusionRects().isEmpty()) {
16944                 postUpdate(this::updateSystemGestureExclusionRects);
16945             }
16946 
16947             if (!collectPreferKeepClearRects().isEmpty()) {
16948                 postUpdate(this::updateKeepClearRects);
16949             }
16950         }
16951     }
16952 
notifyAutofillManagerViewVisibilityChanged(boolean isVisible)16953     private void notifyAutofillManagerViewVisibilityChanged(boolean isVisible) {
16954         if (isAutofillable()) {
16955             AutofillManager afm = getAutofillManager();
16956 
16957             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
16958                 if (mVisibilityChangeForAutofillHandler != null) {
16959                     mVisibilityChangeForAutofillHandler.removeMessages(0);
16960                 }
16961 
16962                 // If the view is in the background but still part of the hierarchy this is called
16963                 // with isVisible=false. Hence visibility==false requires further checks
16964                 if (isVisible) {
16965                     afm.notifyViewVisibilityChanged(this, true);
16966                 } else {
16967                     if (mVisibilityChangeForAutofillHandler == null) {
16968                         mVisibilityChangeForAutofillHandler =
16969                                 new VisibilityChangeForAutofillHandler(afm, this);
16970                     }
16971                     // Let current operation (e.g. removal of the view from the hierarchy)
16972                     // finish before checking state
16973                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
16974                 }
16975             }
16976         }
16977     }
16978 
16979     /**
16980      * Returns the current visibility of the window this view is attached to
16981      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
16982      *
16983      * @return Returns the current visibility of the view's window.
16984      */
16985     @Visibility
getWindowVisibility()16986     public int getWindowVisibility() {
16987         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
16988     }
16989 
16990     /**
16991      * Retrieve the overall visible display size in which the window this view is
16992      * attached to has been positioned in.  This takes into account screen
16993      * decorations above the window, for both cases where the window itself
16994      * is being position inside of them or the window is being placed under
16995      * then and covered insets are used for the window to position its content
16996      * inside.  In effect, this tells you the available area where content can
16997      * be placed and remain visible to users.
16998      *
16999      * @param outRect Filled in with the visible display frame.  If the view
17000      * is not attached to a window, this is simply the raw display size.
17001      */
getWindowVisibleDisplayFrame(Rect outRect)17002     public void getWindowVisibleDisplayFrame(Rect outRect) {
17003         if (mAttachInfo != null) {
17004             mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
17005             return;
17006         }
17007         // TODO (b/327559224): Refine the behavior to better reflect the window environment with API
17008         //  doc updates.
17009         final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
17010         final WindowMetrics metrics = windowManager.getMaximumWindowMetrics();
17011         final Insets insets = metrics.getWindowInsets().getInsets(
17012                 WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout());
17013         outRect.set(metrics.getBounds());
17014         outRect.inset(insets);
17015         outRect.offsetTo(0, 0);
17016     }
17017 
17018     /**
17019      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
17020      * is currently in without any insets.
17021      *
17022      * @hide
17023      */
17024     @UnsupportedAppUsage
17025     @TestApi
getWindowDisplayFrame(@onNull Rect outRect)17026     public void getWindowDisplayFrame(@NonNull Rect outRect) {
17027         if (mAttachInfo != null) {
17028             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
17029             return;
17030         }
17031         // The view is not attached to a display so we don't have a context.
17032         // Make a best guess about the display size.
17033         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
17034         d.getRectSize(outRect);
17035     }
17036 
17037     /**
17038      * Dispatch a notification about a resource configuration change down
17039      * the view hierarchy.
17040      * ViewGroups should override to route to their children.
17041      *
17042      * @param newConfig The new resource configuration.
17043      *
17044      * @see #onConfigurationChanged(android.content.res.Configuration)
17045      */
dispatchConfigurationChanged(Configuration newConfig)17046     public void dispatchConfigurationChanged(Configuration newConfig) {
17047         onConfigurationChanged(newConfig);
17048     }
17049 
17050     /**
17051      * Called when the current configuration of the resources being used
17052      * by the application have changed.  You can use this to decide when
17053      * to reload resources that can changed based on orientation and other
17054      * configuration characteristics.  You only need to use this if you are
17055      * not relying on the normal {@link android.app.Activity} mechanism of
17056      * recreating the activity instance upon a configuration change.
17057      *
17058      * @param newConfig The new resource configuration.
17059      */
onConfigurationChanged(Configuration newConfig)17060     protected void onConfigurationChanged(Configuration newConfig) {
17061     }
17062 
17063     /**
17064      * Private function to aggregate all per-view attributes in to the view
17065      * root.
17066      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)17067     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
17068         performCollectViewAttributes(attachInfo, visibility);
17069     }
17070 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)17071     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
17072         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
17073             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
17074                 attachInfo.mKeepScreenOn = true;
17075             }
17076             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
17077             ListenerInfo li = mListenerInfo;
17078             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
17079                 attachInfo.mHasSystemUiListeners = true;
17080             }
17081         }
17082     }
17083 
needGlobalAttributesUpdate(boolean force)17084     void needGlobalAttributesUpdate(boolean force) {
17085         final AttachInfo ai = mAttachInfo;
17086         if (ai != null && !ai.mRecomputeGlobalAttributes) {
17087             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
17088                     || ai.mHasSystemUiListeners) {
17089                 ai.mRecomputeGlobalAttributes = true;
17090             }
17091         }
17092     }
17093 
17094     /**
17095      * Returns the touch mode state associated with this view.
17096      *
17097      * Attached views return the touch mode state from the associated window's display.
17098      * Detached views just return the default touch mode value defined in
17099      * {@code com.android.internal.R.bool.config_defaultInTouchMode}.
17100      *
17101      * Touch mode is entered once the user begins interacting with the device by touch, and
17102      * affects various things like whether focus highlight is always visible to the user.
17103      *
17104      * @return the touch mode state associated with this view
17105      */
17106     @ViewDebug.ExportedProperty
isInTouchMode()17107     public boolean isInTouchMode() {
17108         if (mAttachInfo != null) {
17109             return mAttachInfo.mInTouchMode;
17110         }
17111         return mResources.getBoolean(com.android.internal.R.bool.config_defaultInTouchMode);
17112     }
17113 
17114     /**
17115      * Returns the context the view is running in, through which it can
17116      * access the current theme, resources, etc.
17117      *
17118      * @return The view's Context.
17119      */
17120     @ViewDebug.CapturedViewProperty
17121     @UiContext
getContext()17122     public final Context getContext() {
17123         return mContext;
17124     }
17125 
17126     /**
17127      * Handle a key event before it is processed by any input method
17128      * associated with the view hierarchy. This can be used to intercept
17129      * key events in special situations before the IME consumes them; a
17130      * typical example would be handling the BACK key to update the application's
17131      * UI instead of allowing the IME to see it and close itself. Due to a bug,
17132      * this function is not called for BACK key events on Android T and U, when
17133      * the IME is shown.
17134      *
17135      * @param keyCode The value in event.getKeyCode().
17136      * @param event Description of the key event.
17137      * @return If you handled the event, return true. If you want to allow the
17138      *         event to be handled by the next receiver, return false.
17139      */
onKeyPreIme(int keyCode, KeyEvent event)17140     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
17141         return false;
17142     }
17143 
17144     /**
17145      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
17146      * KeyEvent.Callback.onKeyDown()}: perform press of the view
17147      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
17148      * is released, if the view is enabled and clickable.
17149      * <p>
17150      * Key presses in software keyboards will generally NOT trigger this
17151      * listener, although some may elect to do so in some situations. Do not
17152      * rely on this to catch software key presses.
17153      *
17154      * @param keyCode a key code that represents the button pressed, from
17155      *                {@link android.view.KeyEvent}
17156      * @param event the KeyEvent object that defines the button action
17157      */
onKeyDown(int keyCode, KeyEvent event)17158     public boolean onKeyDown(int keyCode, KeyEvent event) {
17159         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
17160             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
17161                 return true;
17162             }
17163 
17164             if (event.getRepeatCount() == 0) {
17165                 // Long clickable items don't necessarily have to be clickable.
17166                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
17167                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
17168                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
17169                     // For the purposes of menu anchoring and drawable hotspots,
17170                     // key events are considered to be at the center of the view.
17171                     final float x = getWidth() / 2f;
17172                     final float y = getHeight() / 2f;
17173                     if (clickable) {
17174                         setPressed(true, x, y);
17175                     }
17176                     checkForLongClick(
17177                             ViewConfiguration.getLongPressTimeout(),
17178                             x,
17179                             y,
17180                             // This is not a touch gesture -- do not classify it as one.
17181                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
17182                     return true;
17183                 }
17184             }
17185         }
17186 
17187         return false;
17188     }
17189 
17190     /**
17191      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
17192      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
17193      * the event).
17194      * <p>Key presses in software keyboards will generally NOT trigger this listener,
17195      * although some may elect to do so in some situations. Do not rely on this to
17196      * catch software key presses.
17197      */
onKeyLongPress(int keyCode, KeyEvent event)17198     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
17199         return false;
17200     }
17201 
17202     /**
17203      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
17204      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
17205      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
17206      * or {@link KeyEvent#KEYCODE_SPACE} is released.
17207      * <p>Key presses in software keyboards will generally NOT trigger this listener,
17208      * although some may elect to do so in some situations. Do not rely on this to
17209      * catch software key presses.
17210      *
17211      * @param keyCode A key code that represents the button pressed, from
17212      *                {@link android.view.KeyEvent}.
17213      * @param event   The KeyEvent object that defines the button action.
17214      */
onKeyUp(int keyCode, KeyEvent event)17215     public boolean onKeyUp(int keyCode, KeyEvent event) {
17216         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
17217             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
17218                 return true;
17219             }
17220             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
17221                 setPressed(false);
17222 
17223                 if (!mHasPerformedLongPress) {
17224                     // This is a tap, so remove the longpress check
17225                     removeLongPressCallback();
17226                     if (!event.isCanceled()) {
17227                         return performClickInternal();
17228                     }
17229                 }
17230             }
17231         }
17232         return false;
17233     }
17234 
17235     /**
17236      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
17237      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
17238      * the event).
17239      * <p>Key presses in software keyboards will generally NOT trigger this listener,
17240      * although some may elect to do so in some situations. Do not rely on this to
17241      * catch software key presses.
17242      *
17243      * @param keyCode     A key code that represents the button pressed, from
17244      *                    {@link android.view.KeyEvent}.
17245      * @param repeatCount The number of times the action was made.
17246      * @param event       The KeyEvent object that defines the button action.
17247      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)17248     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
17249         return false;
17250     }
17251 
17252     /**
17253      * Called on the focused view when a key shortcut event is not handled.
17254      * Override this method to implement local key shortcuts for the View.
17255      * Key shortcuts can also be implemented by setting the
17256      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
17257      *
17258      * @param keyCode The value in event.getKeyCode().
17259      * @param event Description of the key event.
17260      * @return If you handled the event, return true. If you want to allow the
17261      *         event to be handled by the next receiver, return false.
17262      */
onKeyShortcut(int keyCode, KeyEvent event)17263     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
17264         return false;
17265     }
17266 
17267     /**
17268      * Check whether the called view is a text editor, in which case it
17269      * would make sense to automatically display a soft input window for
17270      * it.  Subclasses should override this if they implement
17271      * {@link #onCreateInputConnection(EditorInfo)} to return true if
17272      * a call on that method would return a non-null InputConnection, and
17273      * they are really a first-class editor that the user would normally
17274      * start typing on when the go into a window containing your view.
17275      *
17276      * <p>The default implementation always returns false.  This does
17277      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
17278      * will not be called or the user can not otherwise perform edits on your
17279      * view; it is just a hint to the system that this is not the primary
17280      * purpose of this view.
17281      *
17282      * @return Returns true if this view is a text editor, else false.
17283      */
onCheckIsTextEditor()17284     public boolean onCheckIsTextEditor() {
17285         return false;
17286     }
17287 
17288     /**
17289      * Create a new InputConnection for an InputMethod to interact
17290      * with the view.  The default implementation returns null, since it doesn't
17291      * support input methods.  You can override this to implement such support.
17292      * This is only needed for views that take focus and text input.
17293      *
17294      * <p>When implementing this, you probably also want to implement
17295      * {@link #onCheckIsTextEditor()} to indicate you will return a
17296      * non-null InputConnection.</p>
17297      *
17298      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
17299      * object correctly and in its entirety, so that the connected IME can rely
17300      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
17301      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
17302      * must be filled in with the correct cursor position for IMEs to work correctly
17303      * with your application.</p>
17304      *
17305      * @param outAttrs Fill in with attribute information about the connection.
17306      */
onCreateInputConnection(EditorInfo outAttrs)17307     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
17308         return null;
17309     }
17310 
17311     /**
17312      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
17313      * that the system has successfully initialized an {@link InputConnection} and it is ready for
17314      * use.
17315      *
17316      * <p>The default implementation does nothing, since a view doesn't support input methods by
17317      * default (see {@link #onCreateInputConnection}).
17318      *
17319      * @param inputConnection The {@link InputConnection} from {@link #onCreateInputConnection},
17320      * after it's been fully initialized by the system.
17321      * @param editorInfo The {@link EditorInfo} that was used to create the {@link InputConnection}.
17322      * @param handler The dedicated {@link Handler} on which IPC method calls from input methods
17323      * will be dispatched. This is the handler returned by {@link InputConnection#getHandler()}. If
17324      * that method returns null, this parameter will be null also.
17325      *
17326      * @hide
17327      */
onInputConnectionOpenedInternal(@onNull InputConnection inputConnection, @NonNull EditorInfo editorInfo, @Nullable Handler handler)17328     public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
17329             @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
17330 
17331     /**
17332      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
17333      * that the {@link InputConnection} has been closed.
17334      *
17335      * <p>The default implementation does nothing, since a view doesn't support input methods by
17336      * default (see {@link #onCreateInputConnection}).
17337      *
17338      * <p><strong>Note:</strong> This callback is not invoked if the view is already detached when
17339      * the {@link InputConnection} is closed or the connection is not valid and managed by
17340      * {@link com.android.server.inputmethod.InputMethodManagerService}.
17341      * TODO(b/170645312): Before un-hiding this API, handle the detached view scenario.
17342      *
17343      * @hide
17344      */
onInputConnectionClosedInternal()17345     public void onInputConnectionClosedInternal() {}
17346 
17347     /**
17348      * Called by the {@link android.view.inputmethod.InputMethodManager}
17349      * when a view who is not the current
17350      * input connection target is trying to make a call on the manager.  The
17351      * default implementation returns false; you can override this to return
17352      * true for certain views if you are performing InputConnection proxying
17353      * to them.
17354      * @param view The View that is making the InputMethodManager call.
17355      * @return Return true to allow the call, false to reject.
17356      */
checkInputConnectionProxy(View view)17357     public boolean checkInputConnectionProxy(View view) {
17358         return false;
17359     }
17360 
17361     /**
17362      * Show the context menu for this view. It is not safe to hold on to the
17363      * menu after returning from this method.
17364      *
17365      * You should normally not overload this method. Overload
17366      * {@link #onCreateContextMenu(ContextMenu)} or define an
17367      * {@link OnCreateContextMenuListener} to add items to the context menu.
17368      *
17369      * @param menu The context menu to populate
17370      */
createContextMenu(ContextMenu menu)17371     public void createContextMenu(ContextMenu menu) {
17372         ContextMenuInfo menuInfo = getContextMenuInfo();
17373 
17374         // Sets the current menu info so all items added to menu will have
17375         // my extra info set.
17376         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
17377 
17378         onCreateContextMenu(menu);
17379         ListenerInfo li = mListenerInfo;
17380         if (li != null && li.mOnCreateContextMenuListener != null) {
17381             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
17382         }
17383 
17384         // Clear the extra information so subsequent items that aren't mine don't
17385         // have my extra info.
17386         ((MenuBuilder)menu).setCurrentMenuInfo(null);
17387 
17388         if (mParent != null) {
17389             mParent.createContextMenu(menu);
17390         }
17391     }
17392 
17393     /**
17394      * Views should implement this if they have extra information to associate
17395      * with the context menu. The return result is supplied as a parameter to
17396      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
17397      * callback.
17398      *
17399      * @return Extra information about the item for which the context menu
17400      *         should be shown. This information will vary across different
17401      *         subclasses of View.
17402      */
getContextMenuInfo()17403     protected ContextMenuInfo getContextMenuInfo() {
17404         return null;
17405     }
17406 
17407     /**
17408      * Views should implement this if the view itself is going to add items to
17409      * the context menu.
17410      *
17411      * @param menu the context menu to populate
17412      */
onCreateContextMenu(ContextMenu menu)17413     protected void onCreateContextMenu(ContextMenu menu) {
17414     }
17415 
17416     /**
17417      * Implement this method to handle trackball motion events.
17418      * <p>
17419      * The <em>relative</em> movement of the trackball since the last event
17420      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
17421      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
17422      * that a movement of 1 corresponds to the user pressing one DPAD key (so
17423      * they will often be fractional values, representing the more fine-grained
17424      * movement information available from a trackball).
17425      * </p>
17426      *
17427      * @param event The motion event.
17428      * @return True if the event was handled, false otherwise.
17429      */
onTrackballEvent(MotionEvent event)17430     public boolean onTrackballEvent(MotionEvent event) {
17431         return false;
17432     }
17433 
17434     /**
17435      * Implement this method to handle generic motion events.
17436      * <p>
17437      * Generic motion events describe joystick movements, hover events from mouse or stylus
17438      * devices, trackpad touches, scroll wheel movements and other motion events not handled
17439      * by {@link #onTouchEvent(MotionEvent)} or {@link #onTrackballEvent(MotionEvent)}.
17440      * The {@link MotionEvent#getSource() source} of the motion event specifies
17441      * the class of input that was received.  Implementations of this method
17442      * must examine the bits in the source before processing the event.
17443      * The following code example shows how this is done.
17444      * </p><p>
17445      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
17446      * are delivered to the view under the pointer.  All other generic motion events are
17447      * delivered to the focused view.
17448      * </p>
17449      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
17450      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
17451      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
17452      *             // process the joystick movement...
17453      *             return true;
17454      *         }
17455      *     }
17456      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
17457      *         switch (event.getAction()) {
17458      *             case MotionEvent.ACTION_HOVER_MOVE:
17459      *                 // process the hover movement...
17460      *                 return true;
17461      *             case MotionEvent.ACTION_SCROLL:
17462      *                 // process the scroll wheel movement...
17463      *                 return true;
17464      *         }
17465      *     }
17466      *     return super.onGenericMotionEvent(event);
17467      * }</pre>
17468      *
17469      * @param event The generic motion event being processed.
17470      * @return True if the event was handled, false otherwise.
17471      */
onGenericMotionEvent(MotionEvent event)17472     public boolean onGenericMotionEvent(MotionEvent event) {
17473         return false;
17474     }
17475 
17476     /**
17477      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
17478      * <p>
17479      * This method is dispatching hover events to the delegate target to support explore by touch.
17480      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
17481      * the delegate target according to the pointer and the touch area of the delegate while touch
17482      * exploration enabled.
17483      * </p>
17484      *
17485      * @param event The motion event dispatch to the delegate target.
17486      * @return True if the event was handled, false otherwise.
17487      *
17488      * @see #onHoverEvent
17489      */
dispatchTouchExplorationHoverEvent(MotionEvent event)17490     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
17491         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
17492         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
17493             return false;
17494         }
17495 
17496         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
17497         final int action = event.getActionMasked();
17498         boolean pointInDelegateRegion = false;
17499         boolean handled = false;
17500 
17501         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
17502         for (int i = 0; i < info.getRegionCount(); i++) {
17503             Region r = info.getRegionAt(i);
17504             if (r.contains((int) event.getX(), (int) event.getY())) {
17505                 pointInDelegateRegion = true;
17506             }
17507         }
17508 
17509         // Explore by touch should dispatch events to children under the pointer first if any
17510         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
17511         // hover events but receive accessibility focus, it should also not delegate to these
17512         // views when hovered.
17513         if (!oldHoveringTouchDelegate) {
17514             if ((action == MotionEvent.ACTION_HOVER_ENTER
17515                     || action == MotionEvent.ACTION_HOVER_MOVE)
17516                     && !pointInHoveredChild(event)
17517                     && pointInDelegateRegion) {
17518                 mHoveringTouchDelegate = true;
17519             }
17520         } else {
17521             if (action == MotionEvent.ACTION_HOVER_EXIT
17522                     || (action == MotionEvent.ACTION_HOVER_MOVE
17523                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
17524                 mHoveringTouchDelegate = false;
17525             }
17526         }
17527         switch (action) {
17528             case MotionEvent.ACTION_HOVER_MOVE:
17529                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
17530                     // Inside bounds, dispatch as is.
17531                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
17532                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
17533                     // Moving inbound, synthesize hover enter.
17534                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
17535                             ? event : MotionEvent.obtainNoHistory(event);
17536                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
17537                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
17538                     eventNoHistory.setAction(action);
17539                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
17540                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
17541                     // Moving outbound, synthesize hover exit.
17542                     final boolean hoverExitPending = event.isHoverExitPending();
17543                     event.setHoverExitPending(true);
17544                     mTouchDelegate.onTouchExplorationHoverEvent(event);
17545                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
17546                             ? event : MotionEvent.obtainNoHistory(event);
17547                     eventNoHistory.setHoverExitPending(hoverExitPending);
17548                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
17549                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
17550                 }  // else: outside bounds, do nothing.
17551                 break;
17552             case MotionEvent.ACTION_HOVER_ENTER:
17553                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
17554                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
17555                 }
17556                 break;
17557             case MotionEvent.ACTION_HOVER_EXIT:
17558                 if (oldHoveringTouchDelegate) {
17559                     mTouchDelegate.onTouchExplorationHoverEvent(event);
17560                 }
17561                 break;
17562         }
17563         return handled;
17564     }
17565 
17566     /**
17567      * Implement this method to handle hover events.
17568      * <p>
17569      * This method is called whenever a pointer is hovering into, over, or out of the
17570      * bounds of a view and the view is not currently being touched.
17571      * Hover events are represented as pointer events with action
17572      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
17573      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
17574      * </p>
17575      * <ul>
17576      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
17577      * when the pointer enters the bounds of the view.</li>
17578      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
17579      * when the pointer has already entered the bounds of the view and has moved.</li>
17580      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
17581      * when the pointer has exited the bounds of the view or when the pointer is
17582      * about to go down due to a button click, tap, or similar user action that
17583      * causes the view to be touched.</li>
17584      * </ul>
17585      * <p>
17586      * The view should implement this method to return true to indicate that it is
17587      * handling the hover event, such as by changing its drawable state.
17588      * </p><p>
17589      * The default implementation calls {@link #setHovered} to update the hovered state
17590      * of the view when a hover enter or hover exit event is received, if the view
17591      * is enabled and is clickable.  The default implementation also sends hover
17592      * accessibility events.
17593      * </p>
17594      *
17595      * @param event The motion event that describes the hover.
17596      * @return True if the view handled the hover event.
17597      *
17598      * @see #isHovered
17599      * @see #setHovered
17600      * @see #onHoverChanged
17601      */
onHoverEvent(MotionEvent event)17602     public boolean onHoverEvent(MotionEvent event) {
17603         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
17604             return true;
17605         }
17606 
17607         // The root view may receive hover (or touch) events that are outside the bounds of
17608         // the window.  This code ensures that we only send accessibility events for
17609         // hovers that are actually within the bounds of the root view.
17610         final int action = event.getActionMasked();
17611         if (!mSendingHoverAccessibilityEvents) {
17612             if ((action == MotionEvent.ACTION_HOVER_ENTER
17613                     || action == MotionEvent.ACTION_HOVER_MOVE)
17614                     && !hasHoveredChild()
17615                     && pointInView(event.getX(), event.getY())) {
17616                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
17617                 mSendingHoverAccessibilityEvents = true;
17618             }
17619         } else {
17620             if (action == MotionEvent.ACTION_HOVER_EXIT
17621                     || (action == MotionEvent.ACTION_HOVER_MOVE
17622                             && !pointInView(event.getX(), event.getY()))) {
17623                 mSendingHoverAccessibilityEvents = false;
17624                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
17625             }
17626         }
17627 
17628         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
17629                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
17630                 && isOnScrollbar(event.getX(), event.getY())) {
17631             awakenScrollBars();
17632         }
17633 
17634         // If we consider ourself hoverable, or if we we're already hovered,
17635         // handle changing state in response to ENTER and EXIT events.
17636         if (isHoverable() || isHovered()) {
17637             switch (action) {
17638                 case MotionEvent.ACTION_HOVER_ENTER:
17639                     setHovered(true);
17640                     break;
17641                 case MotionEvent.ACTION_HOVER_EXIT:
17642                     setHovered(false);
17643                     break;
17644             }
17645 
17646             // Dispatch the event to onGenericMotionEvent before returning true.
17647             // This is to provide compatibility with existing applications that
17648             // handled HOVER_MOVE events in onGenericMotionEvent and that would
17649             // break because of the new default handling for hoverable views
17650             // in onHoverEvent.
17651             // Note that onGenericMotionEvent will be called by default when
17652             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
17653             dispatchGenericMotionEventInternal(event);
17654             // The event was already handled by calling setHovered(), so always
17655             // return true.
17656             return true;
17657         }
17658 
17659         return false;
17660     }
17661 
17662     /**
17663      * Returns true if the view should handle {@link #onHoverEvent}
17664      * by calling {@link #setHovered} to change its hovered state.
17665      *
17666      * @return True if the view is hoverable.
17667      */
isHoverable()17668     private boolean isHoverable() {
17669         final int viewFlags = mViewFlags;
17670         if ((viewFlags & ENABLED_MASK) == DISABLED) {
17671             return false;
17672         }
17673 
17674         return (viewFlags & CLICKABLE) == CLICKABLE
17675                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
17676                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
17677     }
17678 
17679     /**
17680      * Returns true if the view is currently hovered.
17681      *
17682      * @return True if the view is currently hovered.
17683      *
17684      * @see #setHovered
17685      * @see #onHoverChanged
17686      */
17687     @ViewDebug.ExportedProperty
isHovered()17688     public boolean isHovered() {
17689         return (mPrivateFlags & PFLAG_HOVERED) != 0;
17690     }
17691 
17692     /**
17693      * Sets whether the view is currently hovered.
17694      * <p>
17695      * Calling this method also changes the drawable state of the view.  This
17696      * enables the view to react to hover by using different drawable resources
17697      * to change its appearance.
17698      * </p><p>
17699      * The {@link #onHoverChanged} method is called when the hovered state changes.
17700      * </p>
17701      *
17702      * @param hovered True if the view is hovered.
17703      *
17704      * @see #isHovered
17705      * @see #onHoverChanged
17706      */
setHovered(boolean hovered)17707     public void setHovered(boolean hovered) {
17708         if (hovered) {
17709             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
17710                 mPrivateFlags |= PFLAG_HOVERED;
17711                 refreshDrawableState();
17712                 onHoverChanged(true);
17713             }
17714         } else {
17715             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
17716                 mPrivateFlags &= ~PFLAG_HOVERED;
17717                 refreshDrawableState();
17718                 onHoverChanged(false);
17719             }
17720         }
17721     }
17722 
17723     /**
17724      * Implement this method to handle hover state changes.
17725      * <p>
17726      * This method is called whenever the hover state changes as a result of a
17727      * call to {@link #setHovered}.
17728      * </p>
17729      *
17730      * @param hovered The current hover state, as returned by {@link #isHovered}.
17731      *
17732      * @see #isHovered
17733      * @see #setHovered
17734      */
onHoverChanged(boolean hovered)17735     public void onHoverChanged(boolean hovered) {
17736     }
17737 
17738     /**
17739      * Handles scroll bar dragging by mouse input.
17740      *
17741      * @hide
17742      * @param event The motion event.
17743      *
17744      * @return true if the event was handled as a scroll bar dragging, false otherwise.
17745      */
handleScrollBarDragging(MotionEvent event)17746     protected boolean handleScrollBarDragging(MotionEvent event) {
17747         if (mScrollCache == null) {
17748             return false;
17749         }
17750         final float x = event.getX();
17751         final float y = event.getY();
17752         final int action = event.getAction();
17753         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
17754                 && action != MotionEvent.ACTION_DOWN)
17755                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
17756                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
17757             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
17758             return false;
17759         }
17760 
17761         switch (action) {
17762             case MotionEvent.ACTION_MOVE:
17763                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
17764                     return false;
17765                 }
17766                 if (mScrollCache.mScrollBarDraggingState
17767                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
17768                     final Rect bounds = mScrollCache.mScrollBarBounds;
17769                     getVerticalScrollBarBounds(bounds, null);
17770                     final int range = computeVerticalScrollRange();
17771                     final int offset = computeVerticalScrollOffset();
17772                     final int extent = computeVerticalScrollExtent();
17773 
17774                     final int thumbLength = ScrollBarUtils.getThumbLength(
17775                             bounds.height(), bounds.width(), extent, range);
17776                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
17777                             bounds.height(), thumbLength, extent, range, offset);
17778 
17779                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
17780                     final float maxThumbOffset = bounds.height() - thumbLength;
17781                     final float newThumbOffset =
17782                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
17783                     final int height = getHeight();
17784                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
17785                             && height > 0 && extent > 0) {
17786                         final int newY = Math.round((range - extent)
17787                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
17788                         if (newY != getScrollY()) {
17789                             mScrollCache.mScrollBarDraggingPos = y;
17790                             setScrollY(newY);
17791                         }
17792                     }
17793                     return true;
17794                 }
17795                 if (mScrollCache.mScrollBarDraggingState
17796                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
17797                     final Rect bounds = mScrollCache.mScrollBarBounds;
17798                     getHorizontalScrollBarBounds(bounds, null);
17799                     final int range = computeHorizontalScrollRange();
17800                     final int offset = computeHorizontalScrollOffset();
17801                     final int extent = computeHorizontalScrollExtent();
17802 
17803                     final int thumbLength = ScrollBarUtils.getThumbLength(
17804                             bounds.width(), bounds.height(), extent, range);
17805                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
17806                             bounds.width(), thumbLength, extent, range, offset);
17807 
17808                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
17809                     final float maxThumbOffset = bounds.width() - thumbLength;
17810                     final float newThumbOffset =
17811                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
17812                     final int width = getWidth();
17813                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
17814                             && width > 0 && extent > 0) {
17815                         final int newX = Math.round((range - extent)
17816                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
17817                         if (newX != getScrollX()) {
17818                             mScrollCache.mScrollBarDraggingPos = x;
17819                             setScrollX(newX);
17820                         }
17821                     }
17822                     return true;
17823                 }
17824             case MotionEvent.ACTION_DOWN:
17825                 if (mScrollCache.state == ScrollabilityCache.OFF) {
17826                     return false;
17827                 }
17828                 if (isOnVerticalScrollbarThumb(x, y)) {
17829                     mScrollCache.mScrollBarDraggingState =
17830                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
17831                     mScrollCache.mScrollBarDraggingPos = y;
17832                     return true;
17833                 }
17834                 if (isOnHorizontalScrollbarThumb(x, y)) {
17835                     mScrollCache.mScrollBarDraggingState =
17836                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
17837                     mScrollCache.mScrollBarDraggingPos = x;
17838                     return true;
17839                 }
17840         }
17841         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
17842         return false;
17843     }
17844 
17845     /**
17846      * Implement this method to handle touch screen motion events.
17847      * <p>
17848      * If this method is used to detect click actions, it is recommended that
17849      * the actions be performed by implementing and calling
17850      * {@link #performClick()}. This will ensure consistent system behavior,
17851      * including:
17852      * <ul>
17853      * <li>obeying click sound preferences
17854      * <li>dispatching OnClickListener calls
17855      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
17856      * accessibility features are enabled
17857      * </ul>
17858      *
17859      * @param event The motion event.
17860      * @return True if the event was handled, false otherwise.
17861      */
onTouchEvent(MotionEvent event)17862     public boolean onTouchEvent(MotionEvent event) {
17863         final float x = event.getX();
17864         final float y = event.getY();
17865         final int viewFlags = mViewFlags;
17866         final int action = event.getAction();
17867 
17868         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
17869                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
17870                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
17871 
17872         if ((viewFlags & ENABLED_MASK) == DISABLED
17873                 && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
17874             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
17875                 setPressed(false);
17876             }
17877             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
17878             // A disabled view that is clickable still consumes the touch
17879             // events, it just doesn't respond to them.
17880             return clickable;
17881         }
17882         if (mTouchDelegate != null) {
17883             if (mTouchDelegate.onTouchEvent(event)) {
17884                 return true;
17885             }
17886         }
17887 
17888         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
17889             switch (action) {
17890                 case MotionEvent.ACTION_UP:
17891                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
17892                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
17893                         handleTooltipUp();
17894                     }
17895                     if (!clickable) {
17896                         removeTapCallback();
17897                         removeLongPressCallback();
17898                         mInContextButtonPress = false;
17899                         mHasPerformedLongPress = false;
17900                         mIgnoreNextUpEvent = false;
17901                         break;
17902                     }
17903                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
17904                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
17905                         // take focus if we don't have it already and we should in
17906                         // touch mode.
17907                         boolean focusTaken = false;
17908                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
17909                             focusTaken = requestFocus();
17910                         }
17911 
17912                         if (prepressed) {
17913                             // The button is being released before we actually
17914                             // showed it as pressed.  Make it show the pressed
17915                             // state now (before scheduling the click) to ensure
17916                             // the user sees it.
17917                             setPressed(true, x, y);
17918                         }
17919 
17920                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
17921                             // This is a tap, so remove the longpress check
17922                             removeLongPressCallback();
17923 
17924                             // Only perform take click actions if we were in the pressed state
17925                             if (!focusTaken) {
17926                                 // Use a Runnable and post this rather than calling
17927                                 // performClick directly. This lets other visual state
17928                                 // of the view update before click actions start.
17929                                 if (mPerformClick == null) {
17930                                     mPerformClick = new PerformClick();
17931                                 }
17932                                 if (!post(mPerformClick)) {
17933                                     performClickInternal();
17934                                 }
17935                             }
17936                         }
17937 
17938                         if (mUnsetPressedState == null) {
17939                             mUnsetPressedState = new UnsetPressedState();
17940                         }
17941 
17942                         if (prepressed) {
17943                             postDelayed(mUnsetPressedState,
17944                                     ViewConfiguration.getPressedStateDuration());
17945                         } else if (!post(mUnsetPressedState)) {
17946                             // If the post failed, unpress right now
17947                             mUnsetPressedState.run();
17948                         }
17949 
17950                         removeTapCallback();
17951                     }
17952                     mIgnoreNextUpEvent = false;
17953                     break;
17954 
17955                 case MotionEvent.ACTION_DOWN:
17956                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
17957                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
17958                     }
17959                     mHasPerformedLongPress = false;
17960 
17961                     if (!clickable) {
17962                         checkForLongClick(
17963                                 ViewConfiguration.getLongPressTimeout(),
17964                                 x,
17965                                 y,
17966                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
17967                         break;
17968                     }
17969 
17970                     if (performButtonActionOnTouchDown(event)) {
17971                         break;
17972                     }
17973 
17974                     // Walk up the hierarchy to determine if we're inside a scrolling container.
17975                     boolean isInScrollingContainer = isInScrollingContainer();
17976 
17977                     // For views inside a scrolling container, delay the pressed feedback for
17978                     // a short period in case this is a scroll.
17979                     if (isInScrollingContainer) {
17980                         mPrivateFlags |= PFLAG_PREPRESSED;
17981                         if (mPendingCheckForTap == null) {
17982                             mPendingCheckForTap = new CheckForTap();
17983                         }
17984                         mPendingCheckForTap.x = event.getX();
17985                         mPendingCheckForTap.y = event.getY();
17986                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
17987                     } else {
17988                         // Not inside a scrolling container, so show the feedback right away
17989                         setPressed(true, x, y);
17990                         checkForLongClick(
17991                                 ViewConfiguration.getLongPressTimeout(),
17992                                 x,
17993                                 y,
17994                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
17995                     }
17996                     break;
17997 
17998                 case MotionEvent.ACTION_CANCEL:
17999                     if (clickable) {
18000                         setPressed(false);
18001                     }
18002                     removeTapCallback();
18003                     removeLongPressCallback();
18004                     mInContextButtonPress = false;
18005                     mHasPerformedLongPress = false;
18006                     mIgnoreNextUpEvent = false;
18007                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
18008                     break;
18009 
18010                 case MotionEvent.ACTION_MOVE:
18011                     if (clickable) {
18012                         drawableHotspotChanged(x, y);
18013                     }
18014 
18015                     final int motionClassification = event.getClassification();
18016                     final boolean ambiguousGesture =
18017                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
18018                     int touchSlop = mTouchSlop;
18019                     if (ambiguousGesture && hasPendingLongPressCallback()) {
18020                         if (!pointInView(x, y, touchSlop)) {
18021                             // The default action here is to cancel long press. But instead, we
18022                             // just extend the timeout here, in case the classification
18023                             // stays ambiguous.
18024                             removeLongPressCallback();
18025                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
18026                                     * mAmbiguousGestureMultiplier);
18027                             // Subtract the time already spent
18028                             delay -= event.getEventTime() - event.getDownTime();
18029                             checkForLongClick(
18030                                     delay,
18031                                     x,
18032                                     y,
18033                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
18034                         }
18035                         touchSlop *= mAmbiguousGestureMultiplier;
18036                     }
18037 
18038                     // Be lenient about moving outside of buttons
18039                     if (!pointInView(x, y, touchSlop)) {
18040                         // Outside button
18041                         // Remove any future long press/tap checks
18042                         removeTapCallback();
18043                         removeLongPressCallback();
18044                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
18045                             setPressed(false);
18046                         }
18047                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
18048                     }
18049 
18050                     final boolean deepPress =
18051                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
18052                     if (deepPress && hasPendingLongPressCallback()) {
18053                         // process the long click action immediately
18054                         removeLongPressCallback();
18055                         checkForLongClick(
18056                                 0 /* send immediately */,
18057                                 x,
18058                                 y,
18059                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
18060                     }
18061 
18062                     break;
18063             }
18064 
18065             return true;
18066         }
18067 
18068         return false;
18069     }
18070 
18071     /**
18072      * Called by {@link #measure(int, int)} to check if the current frame presentation got
18073      * delayed by an expensive view mesures during the input event dispatching. (e.g. scrolling)
18074      */
hasExpensiveMeasuresDuringInputEvent()18075     private boolean hasExpensiveMeasuresDuringInputEvent() {
18076         final AttachInfo attachInfo = mAttachInfo;
18077         if (attachInfo == null || attachInfo.mRootView == null) {
18078             return false;
18079         }
18080         if (!attachInfo.mHandlingPointerEvent) {
18081             return false;
18082         }
18083         final ViewFrameInfo info = attachInfo.mViewRootImpl.mViewFrameInfo;
18084         final long durationFromVsyncTimeMs = (System.nanoTime()
18085                 - Choreographer.getInstance().getLastFrameTimeNanos()) / TimeUtils.NANOS_PER_MS;
18086         return durationFromVsyncTimeMs > 3L || info.getAndIncreaseViewMeasuredCount() > 10;
18087     }
18088 
18089     /**
18090      * @hide
18091      */
18092     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInScrollingContainer()18093     public boolean isInScrollingContainer() {
18094         ViewParent p = getParent();
18095         while (p != null && p instanceof ViewGroup) {
18096             if (((ViewGroup) p).shouldDelayChildPressedState()) {
18097                 return true;
18098             }
18099             p = p.getParent();
18100         }
18101         return false;
18102     }
18103 
18104     /**
18105      * Remove the longpress detection timer.
18106      */
removeLongPressCallback()18107     private void removeLongPressCallback() {
18108         if (mPendingCheckForLongPress != null) {
18109             removeCallbacks(mPendingCheckForLongPress);
18110         }
18111     }
18112 
18113     /**
18114      * Return true if the long press callback is scheduled to run sometime in the future.
18115      * Return false if there is no scheduled long press callback at the moment.
18116      */
hasPendingLongPressCallback()18117     private boolean hasPendingLongPressCallback() {
18118         if (mPendingCheckForLongPress == null) {
18119             return false;
18120         }
18121         final AttachInfo attachInfo = mAttachInfo;
18122         if (attachInfo == null) {
18123             return false;
18124         }
18125         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
18126     }
18127 
18128     /**
18129      * Remove the pending click action
18130      */
18131     @UnsupportedAppUsage
removePerformClickCallback()18132     private void removePerformClickCallback() {
18133         if (mPerformClick != null) {
18134             removeCallbacks(mPerformClick);
18135         }
18136     }
18137 
18138     /**
18139      * Remove the prepress detection timer.
18140      */
removeUnsetPressCallback()18141     private void removeUnsetPressCallback() {
18142         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
18143             setPressed(false);
18144             removeCallbacks(mUnsetPressedState);
18145         }
18146     }
18147 
18148     /**
18149      * Remove the tap detection timer.
18150      */
removeTapCallback()18151     private void removeTapCallback() {
18152         if (mPendingCheckForTap != null) {
18153             mPrivateFlags &= ~PFLAG_PREPRESSED;
18154             removeCallbacks(mPendingCheckForTap);
18155         }
18156     }
18157 
18158     /**
18159      * Cancels a pending long press.  Your subclass can use this if you
18160      * want the context menu to come up if the user presses and holds
18161      * at the same place, but you don't want it to come up if they press
18162      * and then move around enough to cause scrolling.
18163      */
cancelLongPress()18164     public void cancelLongPress() {
18165         removeLongPressCallback();
18166 
18167         /*
18168          * The prepressed state handled by the tap callback is a display
18169          * construct, but the tap callback will post a long press callback
18170          * less its own timeout. Remove it here.
18171          */
18172         removeTapCallback();
18173     }
18174 
18175     /**
18176      * Sets the TouchDelegate for this View.
18177      */
setTouchDelegate(TouchDelegate delegate)18178     public void setTouchDelegate(TouchDelegate delegate) {
18179         mTouchDelegate = delegate;
18180     }
18181 
18182     /**
18183      * Gets the TouchDelegate for this View.
18184      */
getTouchDelegate()18185     public TouchDelegate getTouchDelegate() {
18186         return mTouchDelegate;
18187     }
18188 
18189     /**
18190      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
18191      *
18192      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
18193      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
18194      * available. This method should only be called for touch events.
18195      *
18196      * <p class="note">This API is not intended for most applications. Buffered dispatch
18197      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
18198      * streams will not improve your input latency. Side effects include: increased latency,
18199      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
18200      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
18201      * you.</p>
18202      *
18203      * To receive unbuffered events for arbitrary input device source classes, use
18204      * {@link #requestUnbufferedDispatch(int)},
18205      *
18206      * @see View#requestUnbufferedDispatch(int)
18207      */
requestUnbufferedDispatch(MotionEvent event)18208     public final void requestUnbufferedDispatch(MotionEvent event) {
18209         final int action = event.getAction();
18210         if (mAttachInfo == null
18211                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
18212                 || !event.isTouchEvent()) {
18213             return;
18214         }
18215         mAttachInfo.mUnbufferedDispatchRequested = true;
18216     }
18217 
18218     /**
18219      * Request unbuffered dispatch of the given event source class to this view.
18220      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
18221      * automatically terminate, and allows the specification of arbitrary input source classes.
18222      *
18223      * <p>Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, calling this method
18224      * will not result in any behavioral changes when this View is not attached to a window.
18225      *
18226      * @param source The combined input source class to request unbuffered dispatch for. All
18227      *               events coming from these source classes will not be buffered. Set to
18228      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
18229      *
18230      * @see View#requestUnbufferedDispatch(MotionEvent)
18231      */
requestUnbufferedDispatch(@nputSourceClass int source)18232     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
18233         if (mUnbufferedInputSource == source) {
18234             return;
18235         }
18236         mUnbufferedInputSource = source;
18237         if (mParent != null) {
18238             mParent.onDescendantUnbufferedRequested();
18239         }
18240     }
18241 
hasSize()18242     private boolean hasSize() {
18243         return (mBottom > mTop) && (mRight > mLeft);
18244     }
18245 
canTakeFocus()18246     private boolean canTakeFocus() {
18247         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
18248                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
18249                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
18250                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
18251     }
18252 
18253     /**
18254      * Set flags controlling behavior of this view.
18255      *
18256      * @param flags Constant indicating the value which should be set
18257      * @param mask Constant indicating the bit range that should be changed
18258      */
18259     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)18260     void setFlags(int flags, int mask) {
18261         final boolean accessibilityEnabled =
18262                 AccessibilityManager.getInstance(mContext).isEnabled();
18263         final boolean oldIncludeForAccessibility =
18264                 accessibilityEnabled && includeForAccessibility(false);
18265 
18266         int old = mViewFlags;
18267         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
18268 
18269         int changed = mViewFlags ^ old;
18270         if (changed == 0) {
18271             return;
18272         }
18273         int privateFlags = mPrivateFlags;
18274         boolean shouldNotifyFocusableAvailable = false;
18275 
18276         // If focusable is auto, update the FOCUSABLE bit.
18277         int focusableChangedByAuto = 0;
18278         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
18279                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
18280             // Heuristic only takes into account whether view is clickable.
18281             final int newFocus;
18282             if ((mViewFlags & CLICKABLE) != 0) {
18283                 newFocus = FOCUSABLE;
18284             } else {
18285                 newFocus = NOT_FOCUSABLE;
18286             }
18287             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
18288             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
18289             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
18290         }
18291 
18292         /* Check if the FOCUSABLE bit has changed */
18293         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
18294             if (((old & FOCUSABLE) == FOCUSABLE)
18295                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
18296                 /* Give up focus if we are no longer focusable */
18297                 clearFocus();
18298                 if (mParent instanceof ViewGroup) {
18299                     ((ViewGroup) mParent).clearFocusedInCluster();
18300                 }
18301             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
18302                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
18303                 /*
18304                  * Tell the view system that we are now available to take focus
18305                  * if no one else already has it.
18306                  */
18307                 if (mParent != null) {
18308                     ViewRootImpl viewRootImpl = getViewRootImpl();
18309                     if (!sAutoFocusableOffUIThreadWontNotifyParents
18310                             || focusableChangedByAuto == 0
18311                             || viewRootImpl == null
18312                             || viewRootImpl.mThread == Thread.currentThread()) {
18313                         shouldNotifyFocusableAvailable = canTakeFocus();
18314                     }
18315                 }
18316             }
18317         }
18318 
18319         final int newVisibility = flags & VISIBILITY_MASK;
18320         if (newVisibility == VISIBLE) {
18321             if ((changed & VISIBILITY_MASK) != 0) {
18322                 /*
18323                  * If this view is becoming visible, invalidate it in case it changed while
18324                  * it was not visible. Marking it drawn ensures that the invalidation will
18325                  * go through.
18326                  */
18327                 mPrivateFlags |= PFLAG_DRAWN;
18328                 invalidate(true);
18329 
18330                 needGlobalAttributesUpdate(true);
18331 
18332                 // a view becoming visible is worth notifying the parent about in case nothing has
18333                 // focus. Even if this specific view isn't focusable, it may contain something that
18334                 // is, so let the root view try to give this focus if nothing else does.
18335                 shouldNotifyFocusableAvailable = hasSize();
18336             }
18337         }
18338 
18339         if ((changed & ENABLED_MASK) != 0) {
18340             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
18341                 // a view becoming enabled should notify the parent as long as the view is also
18342                 // visible and the parent wasn't already notified by becoming visible during this
18343                 // setFlags invocation.
18344                 shouldNotifyFocusableAvailable = canTakeFocus();
18345             } else {
18346                 if (isFocused()) clearFocus();
18347             }
18348         }
18349 
18350         if (shouldNotifyFocusableAvailable && mParent != null) {
18351             mParent.focusableViewAvailable(this);
18352         }
18353 
18354         /* Check if the GONE bit has changed */
18355         if ((changed & GONE) != 0) {
18356             needGlobalAttributesUpdate(false);
18357             requestLayout();
18358 
18359             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
18360                 if (hasFocus()) {
18361                     clearFocus();
18362                     if (mParent instanceof ViewGroup) {
18363                         ((ViewGroup) mParent).clearFocusedInCluster();
18364                     }
18365                 }
18366                 clearAccessibilityFocus();
18367                 destroyDrawingCache();
18368                 if (mParent instanceof View) {
18369                     // GONE views noop invalidation, so invalidate the parent
18370                     ((View) mParent).invalidate(true);
18371                 }
18372                 // Mark the view drawn to ensure that it gets invalidated properly the next
18373                 // time it is visible and gets invalidated
18374                 mPrivateFlags |= PFLAG_DRAWN;
18375             }
18376             if (mAttachInfo != null) {
18377                 mAttachInfo.mViewVisibilityChanged = true;
18378             }
18379         }
18380 
18381         /* Check if the VISIBLE bit has changed */
18382         if ((changed & INVISIBLE) != 0) {
18383             needGlobalAttributesUpdate(false);
18384             /*
18385              * If this view is becoming invisible, set the DRAWN flag so that
18386              * the next invalidate() will not be skipped.
18387              */
18388             mPrivateFlags |= PFLAG_DRAWN;
18389 
18390             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
18391                 // root view becoming invisible shouldn't clear focus and accessibility focus
18392                 if (getRootView() != this) {
18393                     if (hasFocus()) {
18394                         clearFocus();
18395                         if (mParent instanceof ViewGroup) {
18396                             ((ViewGroup) mParent).clearFocusedInCluster();
18397                         }
18398                     }
18399                     clearAccessibilityFocus();
18400                 }
18401             }
18402             if (mAttachInfo != null) {
18403                 mAttachInfo.mViewVisibilityChanged = true;
18404             }
18405         }
18406 
18407         if ((changed & VISIBILITY_MASK) != 0) {
18408             // If the view is invisible, cleanup its display list to free up resources
18409             if (newVisibility != VISIBLE && mAttachInfo != null) {
18410                 cleanupDraw();
18411             }
18412 
18413             if (mParent instanceof ViewGroup) {
18414                 ViewGroup parent = (ViewGroup) mParent;
18415                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
18416                         newVisibility);
18417                 parent.invalidate(true);
18418             } else if (mParent != null) {
18419                 mParent.invalidateChild(this, null);
18420             }
18421 
18422             if (mAttachInfo != null) {
18423                 dispatchVisibilityChanged(this, newVisibility);
18424 
18425                 // Aggregated visibility changes are dispatched to attached views
18426                 // in visible windows where the parent is currently shown/drawn
18427                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
18428                 // discounting clipping or overlapping. This makes it a good place
18429                 // to change animation states.
18430                 if (mParent != null && getWindowVisibility() == VISIBLE &&
18431                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
18432                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
18433                 }
18434                 // If this view is invisible from visible, then sending the A11y event by its
18435                 // parent which is shown and has the accessibility important.
18436                 if ((old & VISIBILITY_MASK) == VISIBLE) {
18437                     notifySubtreeAccessibilityStateChangedByParentIfNeeded();
18438                 } else {
18439                     notifySubtreeAccessibilityStateChangedIfNeeded();
18440                 }
18441             }
18442         }
18443 
18444         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
18445             destroyDrawingCache();
18446         }
18447 
18448         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
18449             destroyDrawingCache();
18450             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18451             invalidateParentCaches();
18452         }
18453 
18454         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
18455             destroyDrawingCache();
18456             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18457         }
18458 
18459         if ((changed & DRAW_MASK) != 0) {
18460             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
18461                 if (mBackground != null
18462                         || mDefaultFocusHighlight != null
18463                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
18464                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18465                 } else {
18466                     mPrivateFlags |= PFLAG_SKIP_DRAW;
18467                 }
18468             } else {
18469                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18470             }
18471             requestLayout();
18472             invalidate(true);
18473         }
18474 
18475         if ((changed & KEEP_SCREEN_ON) != 0) {
18476             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18477                 mParent.recomputeViewAttributes(this);
18478             }
18479         }
18480 
18481         if (accessibilityEnabled) {
18482             // If we're an accessibility pane and the visibility changed, we already have sent
18483             // a state change, so we really don't need to report other changes.
18484             if (isAccessibilityPane()) {
18485                 changed &= ~VISIBILITY_MASK;
18486             }
18487             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
18488                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
18489                     || (changed & CONTEXT_CLICKABLE) != 0) {
18490                 if (oldIncludeForAccessibility != includeForAccessibility(false)) {
18491                     notifySubtreeAccessibilityStateChangedIfNeeded();
18492                 } else {
18493                     notifyViewAccessibilityStateChangedIfNeeded(
18494                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18495                 }
18496             } else if ((changed & ENABLED_MASK) != 0) {
18497                 notifyViewAccessibilityStateChangedIfNeeded(
18498                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18499             }
18500         }
18501     }
18502 
18503     /**
18504      * Change the view's z order in the tree, so it's on top of other sibling
18505      * views. This ordering change may affect layout, if the parent container
18506      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
18507      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
18508      * method should be followed by calls to {@link #requestLayout()} and
18509      * {@link View#invalidate()} on the view's parent to force the parent to redraw
18510      * with the new child ordering.
18511      *
18512      * @see ViewGroup#bringChildToFront(View)
18513      */
bringToFront()18514     public void bringToFront() {
18515         if (mParent != null) {
18516             mParent.bringChildToFront(this);
18517         }
18518     }
18519 
getScrollFeedbackProvider()18520     private HapticScrollFeedbackProvider getScrollFeedbackProvider() {
18521         if (mScrollFeedbackProvider == null) {
18522             mScrollFeedbackProvider = new HapticScrollFeedbackProvider(this,
18523                     ViewConfiguration.get(mContext), /* disabledIfViewPlaysScrollHaptics= */ false);
18524         }
18525         return mScrollFeedbackProvider;
18526     }
18527 
doRotaryProgressForScrollHaptics(MotionEvent rotaryEvent)18528     private void doRotaryProgressForScrollHaptics(MotionEvent rotaryEvent) {
18529         final float axisScrollValue = rotaryEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
18530         final float verticalScrollFactor =
18531                 ViewConfiguration.get(mContext).getScaledVerticalScrollFactor();
18532         final int scrollAmount = -Math.round(axisScrollValue * verticalScrollFactor);
18533         getScrollFeedbackProvider().onScrollProgress(
18534                 rotaryEvent.getDeviceId(), InputDevice.SOURCE_ROTARY_ENCODER,
18535                 MotionEvent.AXIS_SCROLL, scrollAmount);
18536     }
18537 
doRotaryLimitForScrollHaptics(MotionEvent rotaryEvent)18538     private void doRotaryLimitForScrollHaptics(MotionEvent rotaryEvent) {
18539         final boolean isStart = rotaryEvent.getAxisValue(MotionEvent.AXIS_SCROLL) > 0;
18540         getScrollFeedbackProvider().onScrollLimit(
18541                 rotaryEvent.getDeviceId(), InputDevice.SOURCE_ROTARY_ENCODER,
18542                 MotionEvent.AXIS_SCROLL, isStart);
18543     }
18544 
processScrollEventForRotaryEncoderHaptics()18545     private void processScrollEventForRotaryEncoderHaptics() {
18546         if ((mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT) != 0) {
18547             mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
18548             mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
18549         }
18550     }
18551 
18552     /**
18553      * This is called in response to an internal scroll in this view (i.e., the
18554      * view scrolled its own contents). This is typically as a result of
18555      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
18556      * called.
18557      *
18558      * @param l Current horizontal scroll origin.
18559      * @param t Current vertical scroll origin.
18560      * @param oldl Previous horizontal scroll origin.
18561      * @param oldt Previous vertical scroll origin.
18562      */
onScrollChanged(int l, int t, int oldl, int oldt)18563     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
18564         notifySubtreeAccessibilityStateChangedIfNeeded();
18565         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
18566 
18567         processScrollEventForRotaryEncoderHaptics();
18568 
18569         mBackgroundSizeChanged = true;
18570         mDefaultFocusHighlightSizeChanged = true;
18571         if (mForegroundInfo != null) {
18572             mForegroundInfo.mBoundsChanged = true;
18573         }
18574 
18575         final AttachInfo ai = mAttachInfo;
18576         if (ai != null) {
18577             ai.mViewScrollChanged = true;
18578         }
18579 
18580         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
18581             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
18582         }
18583     }
18584 
18585     /**
18586      * Interface definition for a callback to be invoked when the scroll
18587      * X or Y positions of a view change.
18588      * <p>
18589      * <b>Note:</b> Some views handle scrolling independently from View and may
18590      * have their own separate listeners for scroll-type events. For example,
18591      * {@link android.widget.ListView ListView} allows clients to register an
18592      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
18593      * to listen for changes in list scroll position.
18594      *
18595      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
18596      */
18597     public interface OnScrollChangeListener {
18598         /**
18599          * Called when the scroll position of a view changes.
18600          *
18601          * @param v The view whose scroll position has changed.
18602          * @param scrollX Current horizontal scroll origin.
18603          * @param scrollY Current vertical scroll origin.
18604          * @param oldScrollX Previous horizontal scroll origin.
18605          * @param oldScrollY Previous vertical scroll origin.
18606          */
18607         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
18608     }
18609 
18610     /**
18611      * Interface definition for a callback to be invoked when the layout bounds of a view
18612      * changes due to layout processing.
18613      */
18614     public interface OnLayoutChangeListener {
18615         /**
18616          * Called when the layout bounds of a view changes due to layout processing.
18617          *
18618          * @param v The view whose bounds have changed.
18619          * @param left The new value of the view's left property.
18620          * @param top The new value of the view's top property.
18621          * @param right The new value of the view's right property.
18622          * @param bottom The new value of the view's bottom property.
18623          * @param oldLeft The previous value of the view's left property.
18624          * @param oldTop The previous value of the view's top property.
18625          * @param oldRight The previous value of the view's right property.
18626          * @param oldBottom The previous value of the view's bottom property.
18627          */
18628         void onLayoutChange(View v, int left, int top, int right, int bottom,
18629             int oldLeft, int oldTop, int oldRight, int oldBottom);
18630     }
18631 
18632     /**
18633      * This is called during layout when the size of this view has changed. If
18634      * you were just added to the view hierarchy, you're called with the old
18635      * values of 0.
18636      *
18637      * @param w Current width of this view.
18638      * @param h Current height of this view.
18639      * @param oldw Old width of this view.
18640      * @param oldh Old height of this view.
18641      */
onSizeChanged(int w, int h, int oldw, int oldh)18642     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
18643     }
18644 
18645     /**
18646      * Called by draw to draw the child views. This may be overridden
18647      * by derived classes to gain control just before its children are drawn
18648      * (but after its own view has been drawn).
18649      * @param canvas the canvas on which to draw the view
18650      */
dispatchDraw(@onNull Canvas canvas)18651     protected void dispatchDraw(@NonNull Canvas canvas) {
18652 
18653     }
18654 
18655     /**
18656      * Gets the parent of this view. Note that the parent is a
18657      * ViewParent and not necessarily a View.
18658      *
18659      * @return Parent of this view.
18660      */
getParent()18661     public final ViewParent getParent() {
18662         return mParent;
18663     }
18664 
18665     /**
18666      * Set the horizontal scrolled position of your view. This will cause a call to
18667      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18668      * invalidated.
18669      * @param value the x position to scroll to
18670      */
setScrollX(int value)18671     public void setScrollX(int value) {
18672         scrollTo(value, mScrollY);
18673     }
18674 
18675     /**
18676      * Set the vertical scrolled position of your view. This will cause a call to
18677      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18678      * invalidated.
18679      * @param value the y position to scroll to
18680      */
setScrollY(int value)18681     public void setScrollY(int value) {
18682         scrollTo(mScrollX, value);
18683     }
18684 
18685     /**
18686      * Return the scrolled left position of this view. This is the left edge of
18687      * the displayed part of your view. You do not need to draw any pixels
18688      * farther left, since those are outside of the frame of your view on
18689      * screen.
18690      *
18691      * @return The left edge of the displayed part of your view, in pixels.
18692      */
18693     @InspectableProperty
getScrollX()18694     public final int getScrollX() {
18695         return mScrollX;
18696     }
18697 
18698     /**
18699      * Return the scrolled top position of this view. This is the top edge of
18700      * the displayed part of your view. You do not need to draw any pixels above
18701      * it, since those are outside of the frame of your view on screen.
18702      *
18703      * @return The top edge of the displayed part of your view, in pixels.
18704      */
18705     @InspectableProperty
getScrollY()18706     public final int getScrollY() {
18707         return mScrollY;
18708     }
18709 
18710     /**
18711      * Return the width of your view.
18712      *
18713      * @return The width of your view, in pixels.
18714      */
18715     @ViewDebug.ExportedProperty(category = "layout")
getWidth()18716     public final int getWidth() {
18717         return mRight - mLeft;
18718     }
18719 
18720     /**
18721      * Return the height of your view.
18722      *
18723      * @return The height of your view, in pixels.
18724      */
18725     @ViewDebug.ExportedProperty(category = "layout")
getHeight()18726     public final int getHeight() {
18727         return mBottom - mTop;
18728     }
18729 
18730     /**
18731      * Return the visible drawing bounds of your view. Fills in the output
18732      * rectangle with the values from getScrollX(), getScrollY(),
18733      * getWidth(), and getHeight(). These bounds do not account for any
18734      * transformation properties currently set on the view, such as
18735      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
18736      *
18737      * @param outRect The (scrolled) drawing bounds of the view.
18738      */
getDrawingRect(Rect outRect)18739     public void getDrawingRect(Rect outRect) {
18740         outRect.left = mScrollX;
18741         outRect.top = mScrollY;
18742         outRect.right = mScrollX + (mRight - mLeft);
18743         outRect.bottom = mScrollY + (mBottom - mTop);
18744     }
18745 
18746     /**
18747      * Like {@link #getMeasuredWidthAndState()}, but only returns the
18748      * raw width component (that is the result is masked by
18749      * {@link #MEASURED_SIZE_MASK}).
18750      *
18751      * @return The raw measured width of this view.
18752      */
getMeasuredWidth()18753     public final int getMeasuredWidth() {
18754         return mMeasuredWidth & MEASURED_SIZE_MASK;
18755     }
18756 
18757     /**
18758      * Return the full width measurement information for this view as computed
18759      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
18760      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
18761      * This should be used during measurement and layout calculations only. Use
18762      * {@link #getWidth()} to see how wide a view is after layout.
18763      *
18764      * @return The measured width of this view as a bit mask.
18765      */
18766     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
18767             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
18768                     name = "MEASURED_STATE_TOO_SMALL"),
18769     })
getMeasuredWidthAndState()18770     public final int getMeasuredWidthAndState() {
18771         return mMeasuredWidth;
18772     }
18773 
18774     /**
18775      * Like {@link #getMeasuredHeightAndState()}, but only returns the
18776      * raw height component (that is the result is masked by
18777      * {@link #MEASURED_SIZE_MASK}).
18778      *
18779      * @return The raw measured height of this view.
18780      */
getMeasuredHeight()18781     public final int getMeasuredHeight() {
18782         return mMeasuredHeight & MEASURED_SIZE_MASK;
18783     }
18784 
18785     /**
18786      * Return the full height measurement information for this view as computed
18787      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
18788      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
18789      * This should be used during measurement and layout calculations only. Use
18790      * {@link #getHeight()} to see how high a view is after layout.
18791      *
18792      * @return The measured height of this view as a bit mask.
18793      */
18794     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
18795             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
18796                     name = "MEASURED_STATE_TOO_SMALL"),
18797     })
getMeasuredHeightAndState()18798     public final int getMeasuredHeightAndState() {
18799         return mMeasuredHeight;
18800     }
18801 
18802     /**
18803      * Return only the state bits of {@link #getMeasuredWidthAndState()}
18804      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
18805      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
18806      * and the height component is at the shifted bits
18807      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
18808      */
getMeasuredState()18809     public final int getMeasuredState() {
18810         return (mMeasuredWidth&MEASURED_STATE_MASK)
18811                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
18812                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
18813     }
18814 
18815     /**
18816      * The transform matrix of this view, which is calculated based on the current
18817      * rotation, scale, and pivot properties.
18818      *
18819      * @see #getRotation()
18820      * @see #getScaleX()
18821      * @see #getScaleY()
18822      * @see #getPivotX()
18823      * @see #getPivotY()
18824      * @return The current transform matrix for the view
18825      */
getMatrix()18826     public Matrix getMatrix() {
18827         ensureTransformationInfo();
18828         final Matrix matrix = mTransformationInfo.mMatrix;
18829         mRenderNode.getMatrix(matrix);
18830         return matrix;
18831     }
18832 
18833     /**
18834      * Returns true if the transform matrix is the identity matrix.
18835      * Recomputes the matrix if necessary.
18836      *
18837      * @return True if the transform matrix is the identity matrix, false otherwise.
18838      * @hide
18839      */
18840     @UnsupportedAppUsage
hasIdentityMatrix()18841     public final boolean hasIdentityMatrix() {
18842         return mRenderNode.hasIdentityMatrix();
18843     }
18844 
18845     @UnsupportedAppUsage
ensureTransformationInfo()18846     void ensureTransformationInfo() {
18847         if (mTransformationInfo == null) {
18848             mTransformationInfo = new TransformationInfo();
18849         }
18850     }
18851 
18852     /**
18853      * Utility method to retrieve the inverse of the current mMatrix property.
18854      * We cache the matrix to avoid recalculating it when transform properties
18855      * have not changed.
18856      *
18857      * @return The inverse of the current matrix of this view.
18858      * @hide
18859      */
18860     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getInverseMatrix()18861     public final Matrix getInverseMatrix() {
18862         ensureTransformationInfo();
18863         if (mTransformationInfo.mInverseMatrix == null) {
18864             mTransformationInfo.mInverseMatrix = new Matrix();
18865         }
18866         final Matrix matrix = mTransformationInfo.mInverseMatrix;
18867         mRenderNode.getInverseMatrix(matrix);
18868         return matrix;
18869     }
18870 
18871     /**
18872      * Gets the distance along the Z axis from the camera to this view.
18873      *
18874      * @see #setCameraDistance(float)
18875      *
18876      * @return The distance along the Z axis.
18877      */
getCameraDistance()18878     public float getCameraDistance() {
18879         final float dpi = mResources.getDisplayMetrics().densityDpi;
18880         return mRenderNode.getCameraDistance() * dpi;
18881     }
18882 
18883     /**
18884      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
18885      * views are drawn) from the camera to this view. The camera's distance
18886      * affects 3D transformations, for instance rotations around the X and Y
18887      * axis. If the rotationX or rotationY properties are changed and this view is
18888      * large (more than half the size of the screen), it is recommended to always
18889      * use a camera distance that's greater than the height (X axis rotation) or
18890      * the width (Y axis rotation) of this view.</p>
18891      *
18892      * <p>The distance of the camera from the view plane can have an affect on the
18893      * perspective distortion of the view when it is rotated around the x or y axis.
18894      * For example, a large distance will result in a large viewing angle, and there
18895      * will not be much perspective distortion of the view as it rotates. A short
18896      * distance may cause much more perspective distortion upon rotation, and can
18897      * also result in some drawing artifacts if the rotated view ends up partially
18898      * behind the camera (which is why the recommendation is to use a distance at
18899      * least as far as the size of the view, if the view is to be rotated.)</p>
18900      *
18901      * <p>The distance is expressed in "depth pixels." The default distance depends
18902      * on the screen density. For instance, on a medium density display, the
18903      * default distance is 1280. On a high density display, the default distance
18904      * is 1920.</p>
18905      *
18906      * <p>If you want to specify a distance that leads to visually consistent
18907      * results across various densities, use the following formula:</p>
18908      * <pre>
18909      * float scale = context.getResources().getDisplayMetrics().density;
18910      * view.setCameraDistance(distance * scale);
18911      * </pre>
18912      *
18913      * <p>The density scale factor of a high density display is 1.5,
18914      * and 1920 = 1280 * 1.5.</p>
18915      *
18916      * @param distance The distance in "depth pixels", if negative the opposite
18917      *        value is used
18918      *
18919      * @see #setRotationX(float)
18920      * @see #setRotationY(float)
18921      */
setCameraDistance(float distance)18922     public void setCameraDistance(float distance) {
18923         final float dpi = mResources.getDisplayMetrics().densityDpi;
18924 
18925         invalidateViewProperty(true, false);
18926         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
18927         invalidateViewProperty(false, false);
18928 
18929         invalidateParentIfNeededAndWasQuickRejected();
18930     }
18931 
18932     /**
18933      * The degrees that the view is rotated around the pivot point.
18934      *
18935      * @see #setRotation(float)
18936      * @see #getPivotX()
18937      * @see #getPivotY()
18938      *
18939      * @return The degrees of rotation.
18940      */
18941     @ViewDebug.ExportedProperty(category = "drawing")
18942     @InspectableProperty
getRotation()18943     public float getRotation() {
18944         return mRenderNode.getRotationZ();
18945     }
18946 
18947     /**
18948      * Sets the degrees that the view is rotated around the pivot point. Increasing values
18949      * result in clockwise rotation.
18950      *
18951      * @param rotation The degrees of rotation.
18952      *
18953      * @see #getRotation()
18954      * @see #getPivotX()
18955      * @see #getPivotY()
18956      * @see #setRotationX(float)
18957      * @see #setRotationY(float)
18958      *
18959      * @attr ref android.R.styleable#View_rotation
18960      */
18961     @RemotableViewMethod
setRotation(float rotation)18962     public void setRotation(float rotation) {
18963         if (rotation != getRotation()) {
18964             // Double-invalidation is necessary to capture view's old and new areas
18965             invalidateViewProperty(true, false);
18966             mRenderNode.setRotationZ(rotation);
18967             invalidateViewProperty(false, true);
18968 
18969             invalidateParentIfNeededAndWasQuickRejected();
18970             notifySubtreeAccessibilityStateChangedIfNeeded();
18971         }
18972     }
18973 
18974     /**
18975      * The degrees that the view is rotated around the vertical axis through the pivot point.
18976      *
18977      * @see #getPivotX()
18978      * @see #getPivotY()
18979      * @see #setRotationY(float)
18980      *
18981      * @return The degrees of Y rotation.
18982      */
18983     @ViewDebug.ExportedProperty(category = "drawing")
18984     @InspectableProperty
getRotationY()18985     public float getRotationY() {
18986         return mRenderNode.getRotationY();
18987     }
18988 
18989     /**
18990      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
18991      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
18992      * down the y axis.
18993      *
18994      * When rotating large views, it is recommended to adjust the camera distance
18995      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
18996      *
18997      * @param rotationY The degrees of Y rotation.
18998      *
18999      * @see #getRotationY()
19000      * @see #getPivotX()
19001      * @see #getPivotY()
19002      * @see #setRotation(float)
19003      * @see #setRotationX(float)
19004      * @see #setCameraDistance(float)
19005      *
19006      * @attr ref android.R.styleable#View_rotationY
19007      */
19008     @RemotableViewMethod
setRotationY(float rotationY)19009     public void setRotationY(float rotationY) {
19010         if (rotationY != getRotationY()) {
19011             invalidateViewProperty(true, false);
19012             mRenderNode.setRotationY(rotationY);
19013             invalidateViewProperty(false, true);
19014 
19015             invalidateParentIfNeededAndWasQuickRejected();
19016             notifySubtreeAccessibilityStateChangedIfNeeded();
19017         }
19018     }
19019 
19020     /**
19021      * The degrees that the view is rotated around the horizontal axis through the pivot point.
19022      *
19023      * @see #getPivotX()
19024      * @see #getPivotY()
19025      * @see #setRotationX(float)
19026      *
19027      * @return The degrees of X rotation.
19028      */
19029     @ViewDebug.ExportedProperty(category = "drawing")
19030     @InspectableProperty
getRotationX()19031     public float getRotationX() {
19032         return mRenderNode.getRotationX();
19033     }
19034 
19035     /**
19036      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
19037      * Increasing values result in clockwise rotation from the viewpoint of looking down the
19038      * x axis.
19039      *
19040      * When rotating large views, it is recommended to adjust the camera distance
19041      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
19042      *
19043      * @param rotationX The degrees of X rotation.
19044      *
19045      * @see #getRotationX()
19046      * @see #getPivotX()
19047      * @see #getPivotY()
19048      * @see #setRotation(float)
19049      * @see #setRotationY(float)
19050      * @see #setCameraDistance(float)
19051      *
19052      * @attr ref android.R.styleable#View_rotationX
19053      */
19054     @RemotableViewMethod
setRotationX(float rotationX)19055     public void setRotationX(float rotationX) {
19056         if (rotationX != getRotationX()) {
19057             invalidateViewProperty(true, false);
19058             mRenderNode.setRotationX(rotationX);
19059             invalidateViewProperty(false, true);
19060 
19061             invalidateParentIfNeededAndWasQuickRejected();
19062             notifySubtreeAccessibilityStateChangedIfNeeded();
19063         }
19064     }
19065 
19066     /**
19067      * The amount that the view is scaled in x around the pivot point, as a proportion of
19068      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
19069      *
19070      * <p>By default, this is 1.0f.
19071      *
19072      * @see #getPivotX()
19073      * @see #getPivotY()
19074      * @return The scaling factor.
19075      */
19076     @ViewDebug.ExportedProperty(category = "drawing")
19077     @InspectableProperty
getScaleX()19078     public float getScaleX() {
19079         return mRenderNode.getScaleX();
19080     }
19081 
19082     /**
19083      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
19084      * the view's unscaled width. A value of 1 means that no scaling is applied.
19085      *
19086      * @param scaleX The scaling factor.
19087      * @see #getPivotX()
19088      * @see #getPivotY()
19089      *
19090      * @attr ref android.R.styleable#View_scaleX
19091      */
19092     @RemotableViewMethod
setScaleX(float scaleX)19093     public void setScaleX(float scaleX) {
19094         if (scaleX != getScaleX()) {
19095             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
19096             invalidateViewProperty(true, false);
19097             mRenderNode.setScaleX(scaleX);
19098             invalidateViewProperty(false, true);
19099 
19100             invalidateParentIfNeededAndWasQuickRejected();
19101             notifySubtreeAccessibilityStateChangedIfNeeded();
19102         }
19103     }
19104 
19105     /**
19106      * The amount that the view is scaled in y around the pivot point, as a proportion of
19107      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
19108      *
19109      * <p>By default, this is 1.0f.
19110      *
19111      * @see #getPivotX()
19112      * @see #getPivotY()
19113      * @return The scaling factor.
19114      */
19115     @ViewDebug.ExportedProperty(category = "drawing")
19116     @InspectableProperty
getScaleY()19117     public float getScaleY() {
19118         return mRenderNode.getScaleY();
19119     }
19120 
19121     /**
19122      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
19123      * the view's unscaled width. A value of 1 means that no scaling is applied.
19124      *
19125      * @param scaleY The scaling factor.
19126      * @see #getPivotX()
19127      * @see #getPivotY()
19128      *
19129      * @attr ref android.R.styleable#View_scaleY
19130      */
19131     @RemotableViewMethod
setScaleY(float scaleY)19132     public void setScaleY(float scaleY) {
19133         if (scaleY != getScaleY()) {
19134             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
19135             invalidateViewProperty(true, false);
19136             mRenderNode.setScaleY(scaleY);
19137             invalidateViewProperty(false, true);
19138 
19139             invalidateParentIfNeededAndWasQuickRejected();
19140             notifySubtreeAccessibilityStateChangedIfNeeded();
19141         }
19142     }
19143 
19144     /**
19145      * The x location of the point around which the view is {@link #setRotation(float) rotated}
19146      * and {@link #setScaleX(float) scaled}.
19147      *
19148      * @see #getRotation()
19149      * @see #getScaleX()
19150      * @see #getScaleY()
19151      * @see #getPivotY()
19152      * @return The x location of the pivot point.
19153      *
19154      * @attr ref android.R.styleable#View_transformPivotX
19155      */
19156     @ViewDebug.ExportedProperty(category = "drawing")
19157     @InspectableProperty(name = "transformPivotX")
getPivotX()19158     public float getPivotX() {
19159         return mRenderNode.getPivotX();
19160     }
19161 
19162     /**
19163      * Sets the x location of the point around which the view is
19164      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
19165      * By default, the pivot point is centered on the object.
19166      * Setting this property disables this behavior and causes the view to use only the
19167      * explicitly set pivotX and pivotY values.
19168      *
19169      * @param pivotX The x location of the pivot point.
19170      * @see #getRotation()
19171      * @see #getScaleX()
19172      * @see #getScaleY()
19173      * @see #getPivotY()
19174      *
19175      * @attr ref android.R.styleable#View_transformPivotX
19176      */
19177     @RemotableViewMethod
setPivotX(float pivotX)19178     public void setPivotX(float pivotX) {
19179         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
19180             invalidateViewProperty(true, false);
19181             mRenderNode.setPivotX(pivotX);
19182             invalidateViewProperty(false, true);
19183 
19184             invalidateParentIfNeededAndWasQuickRejected();
19185         }
19186     }
19187 
19188     /**
19189      * The y location of the point around which the view is {@link #setRotation(float) rotated}
19190      * and {@link #setScaleY(float) scaled}.
19191      *
19192      * @see #getRotation()
19193      * @see #getScaleX()
19194      * @see #getScaleY()
19195      * @see #getPivotY()
19196      * @return The y location of the pivot point.
19197      *
19198      * @attr ref android.R.styleable#View_transformPivotY
19199      */
19200     @ViewDebug.ExportedProperty(category = "drawing")
19201     @InspectableProperty(name = "transformPivotY")
getPivotY()19202     public float getPivotY() {
19203         return mRenderNode.getPivotY();
19204     }
19205 
19206     /**
19207      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
19208      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
19209      * Setting this property disables this behavior and causes the view to use only the
19210      * explicitly set pivotX and pivotY values.
19211      *
19212      * @param pivotY The y location of the pivot point.
19213      * @see #getRotation()
19214      * @see #getScaleX()
19215      * @see #getScaleY()
19216      * @see #getPivotY()
19217      *
19218      * @attr ref android.R.styleable#View_transformPivotY
19219      */
19220     @RemotableViewMethod
setPivotY(float pivotY)19221     public void setPivotY(float pivotY) {
19222         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
19223             invalidateViewProperty(true, false);
19224             mRenderNode.setPivotY(pivotY);
19225             invalidateViewProperty(false, true);
19226 
19227             invalidateParentIfNeededAndWasQuickRejected();
19228         }
19229     }
19230 
19231     /**
19232      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
19233      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
19234      * of the view.
19235      *
19236      * @return True if a pivot has been set, false if the default pivot is being used
19237      */
isPivotSet()19238     public boolean isPivotSet() {
19239         return mRenderNode.isPivotExplicitlySet();
19240     }
19241 
19242     /**
19243      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
19244      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
19245      * and the pivot used for rotation will return to default of being centered on the view.
19246      */
resetPivot()19247     public void resetPivot() {
19248         if (mRenderNode.resetPivot()) {
19249             invalidateViewProperty(false, false);
19250         }
19251     }
19252 
19253     /**
19254      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
19255      * completely transparent and 1 means the view is completely opaque.
19256      *
19257      * <p>By default this is 1.0f.
19258      * @return The opacity of the view.
19259      */
19260     @ViewDebug.ExportedProperty(category = "drawing")
19261     @InspectableProperty
getAlpha()19262     public float getAlpha() {
19263         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
19264     }
19265 
19266     /**
19267      * Sets the behavior for overlapping rendering for this view (see {@link
19268      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
19269      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
19270      * providing the value which is then used internally. That is, when {@link
19271      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
19272      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
19273      * instead.
19274      *
19275      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
19276      * instead of that returned by {@link #hasOverlappingRendering()}.
19277      *
19278      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
19279      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)19280     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
19281         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
19282         if (hasOverlappingRendering) {
19283             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
19284         } else {
19285             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
19286         }
19287     }
19288 
19289     /**
19290      * Returns the value for overlapping rendering that is used internally. This is either
19291      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
19292      * the return value of {@link #hasOverlappingRendering()}, otherwise.
19293      *
19294      * @return The value for overlapping rendering being used internally.
19295      */
getHasOverlappingRendering()19296     public final boolean getHasOverlappingRendering() {
19297         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
19298                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
19299                 hasOverlappingRendering();
19300     }
19301 
19302     /**
19303      * Returns whether this View has content which overlaps.
19304      *
19305      * <p>This function, intended to be overridden by specific View types, is an optimization when
19306      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
19307      * an offscreen buffer and then composited into place, which can be expensive. If the view has
19308      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
19309      * directly. An example of overlapping rendering is a TextView with a background image, such as
19310      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
19311      * ImageView with only the foreground image. The default implementation returns true; subclasses
19312      * should override if they have cases which can be optimized.</p>
19313      *
19314      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
19315      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
19316      *
19317      * @return true if the content in this view might overlap, false otherwise.
19318      */
19319     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()19320     public boolean hasOverlappingRendering() {
19321         return true;
19322     }
19323 
19324     /**
19325      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
19326      * completely transparent and 1 means the view is completely opaque.
19327      *
19328      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
19329      * can have significant performance implications, especially for large views. It is best to use
19330      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
19331      *
19332      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
19333      * strongly recommended for performance reasons to either override
19334      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
19335      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
19336      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
19337      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
19338      * of rendering cost, even for simple or small views. Starting with
19339      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
19340      * applied to the view at the rendering level.</p>
19341      *
19342      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
19343      * responsible for applying the opacity itself.</p>
19344      *
19345      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
19346      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
19347      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
19348      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
19349      *
19350      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
19351      * value will clip a View to its bounds, unless the View returns <code>false</code> from
19352      * {@link #hasOverlappingRendering}.</p>
19353      *
19354      * @param alpha The opacity of the view.
19355      *
19356      * @see #hasOverlappingRendering()
19357      * @see #setLayerType(int, android.graphics.Paint)
19358      *
19359      * @attr ref android.R.styleable#View_alpha
19360      */
19361     @RemotableViewMethod
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)19362     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
19363         ensureTransformationInfo();
19364         if (mTransformationInfo.mAlpha != alpha) {
19365             setAlphaInternal(alpha);
19366             if (onSetAlpha((int) (alpha * 255))) {
19367                 mPrivateFlags |= PFLAG_ALPHA_SET;
19368                 // subclass is handling alpha - don't optimize rendering cache invalidation
19369                 invalidateParentCaches();
19370                 invalidate(true);
19371             } else {
19372                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
19373                 invalidateViewProperty(true, false);
19374                 mRenderNode.setAlpha(getFinalAlpha());
19375             }
19376         }
19377     }
19378 
19379     /**
19380      * Faster version of setAlpha() which performs the same steps except there are
19381      * no calls to invalidate(). The caller of this function should perform proper invalidation
19382      * on the parent and this object. The return value indicates whether the subclass handles
19383      * alpha (the return value for onSetAlpha()).
19384      *
19385      * @param alpha The new value for the alpha property
19386      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
19387      *         the new value for the alpha property is different from the old value
19388      */
19389     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)19390     boolean setAlphaNoInvalidation(float alpha) {
19391         ensureTransformationInfo();
19392         if (mTransformationInfo.mAlpha != alpha) {
19393             setAlphaInternal(alpha);
19394             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
19395             if (subclassHandlesAlpha) {
19396                 mPrivateFlags |= PFLAG_ALPHA_SET;
19397                 return true;
19398             } else {
19399                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
19400                 mRenderNode.setAlpha(getFinalAlpha());
19401             }
19402         }
19403         return false;
19404     }
19405 
setAlphaInternal(float alpha)19406     void setAlphaInternal(float alpha) {
19407         float oldAlpha = mTransformationInfo.mAlpha;
19408         mTransformationInfo.mAlpha = alpha;
19409         // Report visibility changes, which can affect children, to accessibility
19410         if ((alpha == 0) ^ (oldAlpha == 0)) {
19411             notifySubtreeAccessibilityStateChangedIfNeeded();
19412         }
19413     }
19414 
19415     /**
19416      * This property is intended only for use by the Fade transition, which animates it
19417      * to produce a visual translucency that does not side-effect (or get affected by)
19418      * the real alpha property. This value is composited with the other alpha value
19419      * (and the AlphaAnimation value, when that is present) to produce a final visual
19420      * translucency result, which is what is passed into the DisplayList.
19421      */
setTransitionAlpha(float alpha)19422     public void setTransitionAlpha(float alpha) {
19423         ensureTransformationInfo();
19424         if (mTransformationInfo.mTransitionAlpha != alpha) {
19425             mTransformationInfo.mTransitionAlpha = alpha;
19426             mPrivateFlags &= ~PFLAG_ALPHA_SET;
19427             invalidateViewProperty(true, false);
19428             mRenderNode.setAlpha(getFinalAlpha());
19429         }
19430     }
19431 
19432     /**
19433      * Calculates the visual alpha of this view, which is a combination of the actual
19434      * alpha value and the transitionAlpha value (if set).
19435      */
getFinalAlpha()19436     private float getFinalAlpha() {
19437         if (mTransformationInfo != null) {
19438             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
19439         }
19440         return 1;
19441     }
19442 
19443     /**
19444      * This property is intended only for use by the Fade transition, which animates
19445      * it to produce a visual translucency that does not side-effect (or get affected
19446      * by) the real alpha property. This value is composited with the other alpha
19447      * value (and the AlphaAnimation value, when that is present) to produce a final
19448      * visual translucency result, which is what is passed into the DisplayList.
19449      */
19450     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()19451     public float getTransitionAlpha() {
19452         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
19453     }
19454 
19455     /**
19456      * Sets whether or not to allow force dark to apply to this view.
19457      *
19458      * Setting this to false will disable the auto-dark feature on everything this view
19459      * draws, including any descendants.
19460      *
19461      * Setting this to true will allow this view to be automatically made dark, however
19462      * a value of 'true' will not override any 'false' value in its parent chain nor will
19463      * it prevent any 'false' in any of its children.
19464      *
19465      * The default behavior of force dark is also influenced by the Theme's
19466      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
19467      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
19468      *
19469      * @param allow Whether or not to allow force dark.
19470      */
setForceDarkAllowed(boolean allow)19471     public void setForceDarkAllowed(boolean allow) {
19472         if (mRenderNode.setForceDarkAllowed(allow)) {
19473             // Currently toggling force-dark requires a new display list push to apply
19474             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
19475             invalidate();
19476         }
19477     }
19478 
19479     /**
19480      * See {@link #setForceDarkAllowed(boolean)}
19481      *
19482      * @return true if force dark is allowed (default), false if it is disabled
19483      */
19484     @ViewDebug.ExportedProperty(category = "drawing")
19485     @InspectableProperty
isForceDarkAllowed()19486     public boolean isForceDarkAllowed() {
19487         return mRenderNode.isForceDarkAllowed();
19488     }
19489 
19490     /**
19491      * Top position of this view relative to its parent.
19492      *
19493      * @return The top of this view, in pixels.
19494      */
19495     @ViewDebug.CapturedViewProperty
getTop()19496     public final int getTop() {
19497         return mTop;
19498     }
19499 
19500     /**
19501      * Sets the top position of this view relative to its parent. This method is meant to be called
19502      * by the layout system and should not generally be called otherwise, because the property
19503      * may be changed at any time by the layout.
19504      *
19505      * @param top The top of this view, in pixels.
19506      */
setTop(int top)19507     public final void setTop(int top) {
19508         if (top != mTop) {
19509             final boolean matrixIsIdentity = hasIdentityMatrix();
19510             if (matrixIsIdentity) {
19511                 if (mAttachInfo != null) {
19512                     int minTop;
19513                     int yLoc;
19514                     if (top < mTop) {
19515                         minTop = top;
19516                         yLoc = top - mTop;
19517                     } else {
19518                         minTop = mTop;
19519                         yLoc = 0;
19520                     }
19521                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
19522                 }
19523             } else {
19524                 // Double-invalidation is necessary to capture view's old and new areas
19525                 invalidate(true);
19526             }
19527 
19528             int width = mRight - mLeft;
19529             int oldHeight = mBottom - mTop;
19530 
19531             mTop = top;
19532             mRenderNode.setTop(mTop);
19533 
19534             sizeChange(width, mBottom - mTop, width, oldHeight);
19535 
19536             if (!matrixIsIdentity) {
19537                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19538                 invalidate(true);
19539             }
19540             mBackgroundSizeChanged = true;
19541             mDefaultFocusHighlightSizeChanged = true;
19542             if (mForegroundInfo != null) {
19543                 mForegroundInfo.mBoundsChanged = true;
19544             }
19545             invalidateParentIfNeeded();
19546         }
19547     }
19548 
19549     /**
19550      * Bottom position of this view relative to its parent.
19551      *
19552      * @return The bottom of this view, in pixels.
19553      */
19554     @ViewDebug.CapturedViewProperty
getBottom()19555     public final int getBottom() {
19556         return mBottom;
19557     }
19558 
19559     /**
19560      * True if this view has changed since the last time being drawn.
19561      *
19562      * @return The dirty state of this view.
19563      */
isDirty()19564     public boolean isDirty() {
19565         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
19566     }
19567 
19568     /**
19569      * Sets the bottom position of this view relative to its parent. This method is meant to be
19570      * called by the layout system and should not generally be called otherwise, because the
19571      * property may be changed at any time by the layout.
19572      *
19573      * @param bottom The bottom of this view, in pixels.
19574      */
setBottom(int bottom)19575     public final void setBottom(int bottom) {
19576         if (bottom != mBottom) {
19577             final boolean matrixIsIdentity = hasIdentityMatrix();
19578             if (matrixIsIdentity) {
19579                 if (mAttachInfo != null) {
19580                     int maxBottom;
19581                     if (bottom < mBottom) {
19582                         maxBottom = mBottom;
19583                     } else {
19584                         maxBottom = bottom;
19585                     }
19586                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
19587                 }
19588             } else {
19589                 // Double-invalidation is necessary to capture view's old and new areas
19590                 invalidate(true);
19591             }
19592 
19593             int width = mRight - mLeft;
19594             int oldHeight = mBottom - mTop;
19595 
19596             mBottom = bottom;
19597             mRenderNode.setBottom(mBottom);
19598 
19599             sizeChange(width, mBottom - mTop, width, oldHeight);
19600 
19601             if (!matrixIsIdentity) {
19602                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19603                 invalidate(true);
19604             }
19605             mBackgroundSizeChanged = true;
19606             mDefaultFocusHighlightSizeChanged = true;
19607             if (mForegroundInfo != null) {
19608                 mForegroundInfo.mBoundsChanged = true;
19609             }
19610             invalidateParentIfNeeded();
19611         }
19612     }
19613 
19614     /**
19615      * Left position of this view relative to its parent.
19616      *
19617      * @return The left edge of this view, in pixels.
19618      */
19619     @ViewDebug.CapturedViewProperty
getLeft()19620     public final int getLeft() {
19621         return mLeft;
19622     }
19623 
19624     /**
19625      * Sets the left position of this view relative to its parent. This method is meant to be called
19626      * by the layout system and should not generally be called otherwise, because the property
19627      * may be changed at any time by the layout.
19628      *
19629      * @param left The left of this view, in pixels.
19630      */
setLeft(int left)19631     public final void setLeft(int left) {
19632         if (left != mLeft) {
19633             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
19634             final boolean matrixIsIdentity = hasIdentityMatrix();
19635             if (matrixIsIdentity) {
19636                 if (mAttachInfo != null) {
19637                     int minLeft;
19638                     int xLoc;
19639                     if (left < mLeft) {
19640                         minLeft = left;
19641                         xLoc = left - mLeft;
19642                     } else {
19643                         minLeft = mLeft;
19644                         xLoc = 0;
19645                     }
19646                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
19647                 }
19648             } else {
19649                 // Double-invalidation is necessary to capture view's old and new areas
19650                 invalidate(true);
19651             }
19652 
19653             int oldWidth = mRight - mLeft;
19654             int height = mBottom - mTop;
19655 
19656             mLeft = left;
19657             mRenderNode.setLeft(left);
19658 
19659             sizeChange(mRight - mLeft, height, oldWidth, height);
19660 
19661             if (!matrixIsIdentity) {
19662                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19663                 invalidate(true);
19664             }
19665             mBackgroundSizeChanged = true;
19666             mDefaultFocusHighlightSizeChanged = true;
19667             if (mForegroundInfo != null) {
19668                 mForegroundInfo.mBoundsChanged = true;
19669             }
19670             invalidateParentIfNeeded();
19671         }
19672     }
19673 
19674     /**
19675      * Right position of this view relative to its parent.
19676      *
19677      * @return The right edge of this view, in pixels.
19678      */
19679     @ViewDebug.CapturedViewProperty
getRight()19680     public final int getRight() {
19681         return mRight;
19682     }
19683 
19684     /**
19685      * Sets the right position of this view relative to its parent. This method is meant to be called
19686      * by the layout system and should not generally be called otherwise, because the property
19687      * may be changed at any time by the layout.
19688      *
19689      * @param right The right of this view, in pixels.
19690      */
setRight(int right)19691     public final void setRight(int right) {
19692         if (right != mRight) {
19693             final boolean matrixIsIdentity = hasIdentityMatrix();
19694             if (matrixIsIdentity) {
19695                 if (mAttachInfo != null) {
19696                     int maxRight;
19697                     if (right < mRight) {
19698                         maxRight = mRight;
19699                     } else {
19700                         maxRight = right;
19701                     }
19702                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
19703                 }
19704             } else {
19705                 // Double-invalidation is necessary to capture view's old and new areas
19706                 invalidate(true);
19707             }
19708 
19709             int oldWidth = mRight - mLeft;
19710             int height = mBottom - mTop;
19711 
19712             mRight = right;
19713             mRenderNode.setRight(mRight);
19714 
19715             sizeChange(mRight - mLeft, height, oldWidth, height);
19716 
19717             if (!matrixIsIdentity) {
19718                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19719                 invalidate(true);
19720             }
19721             mBackgroundSizeChanged = true;
19722             mDefaultFocusHighlightSizeChanged = true;
19723             if (mForegroundInfo != null) {
19724                 mForegroundInfo.mBoundsChanged = true;
19725             }
19726             invalidateParentIfNeeded();
19727         }
19728     }
19729 
sanitizeFloatPropertyValue(float value, String propertyName)19730     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
19731         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
19732     }
19733 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)19734     private static float sanitizeFloatPropertyValue(float value, String propertyName,
19735             float min, float max) {
19736         // The expected "nothing bad happened" path
19737         if (value >= min && value <= max) return value;
19738 
19739         if (value < min || value == Float.NEGATIVE_INFINITY) {
19740             if (sThrowOnInvalidFloatProperties) {
19741                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
19742                         + value + ", the value must be >= " + min);
19743             }
19744             return min;
19745         }
19746 
19747         if (value > max || value == Float.POSITIVE_INFINITY) {
19748             if (sThrowOnInvalidFloatProperties) {
19749                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
19750                         + value + ", the value must be <= " + max);
19751             }
19752             return max;
19753         }
19754 
19755         if (Float.isNaN(value)) {
19756             if (sThrowOnInvalidFloatProperties) {
19757                 throw new IllegalArgumentException(
19758                         "Cannot set '" + propertyName + "' to Float.NaN");
19759             }
19760             return 0; // Unclear which direction this NaN went so... 0?
19761         }
19762 
19763         // Shouldn't be possible to reach this.
19764         throw new IllegalStateException("How do you get here?? " + value);
19765     }
19766 
19767     /**
19768      * The visual x position of this view, in pixels. This is equivalent to the
19769      * {@link #setTranslationX(float) translationX} property plus the current
19770      * {@link #getLeft() left} property.
19771      *
19772      * @return The visual x position of this view, in pixels.
19773      */
19774     @ViewDebug.ExportedProperty(category = "drawing")
getX()19775     public float getX() {
19776         return mLeft + getTranslationX();
19777     }
19778 
19779     /**
19780      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
19781      * {@link #setTranslationX(float) translationX} property to be the difference between
19782      * the x value passed in and the current {@link #getLeft() left} property.
19783      *
19784      * @param x The visual x position of this view, in pixels.
19785      */
setX(float x)19786     public void setX(float x) {
19787         setTranslationX(x - mLeft);
19788     }
19789 
19790     /**
19791      * The visual y position of this view, in pixels. This is equivalent to the
19792      * {@link #setTranslationY(float) translationY} property plus the current
19793      * {@link #getTop() top} property.
19794      *
19795      * @return The visual y position of this view, in pixels.
19796      */
19797     @ViewDebug.ExportedProperty(category = "drawing")
getY()19798     public float getY() {
19799         return mTop + getTranslationY();
19800     }
19801 
19802     /**
19803      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
19804      * {@link #setTranslationY(float) translationY} property to be the difference between
19805      * the y value passed in and the current {@link #getTop() top} property.
19806      *
19807      * @param y The visual y position of this view, in pixels.
19808      */
setY(float y)19809     public void setY(float y) {
19810         setTranslationY(y - mTop);
19811     }
19812 
19813     /**
19814      * The visual z position of this view, in pixels. This is equivalent to the
19815      * {@link #setTranslationZ(float) translationZ} property plus the current
19816      * {@link #getElevation() elevation} property.
19817      *
19818      * @return The visual z position of this view, in pixels.
19819      */
19820     @ViewDebug.ExportedProperty(category = "drawing")
getZ()19821     public float getZ() {
19822         return getElevation() + getTranslationZ();
19823     }
19824 
19825     /**
19826      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
19827      * {@link #setTranslationZ(float) translationZ} property to be the difference between
19828      * the z value passed in and the current {@link #getElevation() elevation} property.
19829      *
19830      * @param z The visual z position of this view, in pixels.
19831      */
setZ(float z)19832     public void setZ(float z) {
19833         setTranslationZ(z - getElevation());
19834     }
19835 
19836     /**
19837      * The base elevation of this view relative to its parent, in pixels.
19838      *
19839      * @return The base depth position of the view, in pixels.
19840      */
19841     @ViewDebug.ExportedProperty(category = "drawing")
19842     @InspectableProperty
getElevation()19843     public float getElevation() {
19844         return mRenderNode.getElevation();
19845     }
19846 
19847     /**
19848      * Sets the base elevation of this view, in pixels.
19849      *
19850      * @attr ref android.R.styleable#View_elevation
19851      */
19852     @RemotableViewMethod
setElevation(float elevation)19853     public void setElevation(float elevation) {
19854         if (elevation != getElevation()) {
19855             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
19856             invalidateViewProperty(true, false);
19857             mRenderNode.setElevation(elevation);
19858             invalidateViewProperty(false, true);
19859 
19860             invalidateParentIfNeededAndWasQuickRejected();
19861         }
19862     }
19863 
19864     /**
19865      * The horizontal location of this view relative to its {@link #getLeft() left} position.
19866      * This position is post-layout, in addition to wherever the object's
19867      * layout placed it.
19868      *
19869      * @return The horizontal position of this view relative to its left position, in pixels.
19870      */
19871     @ViewDebug.ExportedProperty(category = "drawing")
19872     @InspectableProperty
getTranslationX()19873     public float getTranslationX() {
19874         return mRenderNode.getTranslationX();
19875     }
19876 
19877     /**
19878      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
19879      * This effectively positions the object post-layout, in addition to wherever the object's
19880      * layout placed it.
19881      *
19882      * @param translationX The horizontal position of this view relative to its left position,
19883      * in pixels.
19884      *
19885      * @attr ref android.R.styleable#View_translationX
19886      */
19887     @RemotableViewMethod
setTranslationX(float translationX)19888     public void setTranslationX(float translationX) {
19889         if (translationX != getTranslationX()) {
19890             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
19891             invalidateViewProperty(true, false);
19892             mRenderNode.setTranslationX(translationX);
19893             invalidateViewProperty(false, true);
19894 
19895             invalidateParentIfNeededAndWasQuickRejected();
19896             notifySubtreeAccessibilityStateChangedIfNeeded();
19897         }
19898     }
19899 
19900     /**
19901      * The vertical location of this view relative to its {@link #getTop() top} position.
19902      * This position is post-layout, in addition to wherever the object's
19903      * layout placed it.
19904      *
19905      * @return The vertical position of this view relative to its top position,
19906      * in pixels.
19907      */
19908     @ViewDebug.ExportedProperty(category = "drawing")
19909     @InspectableProperty
getTranslationY()19910     public float getTranslationY() {
19911         return mRenderNode.getTranslationY();
19912     }
19913 
19914     /**
19915      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
19916      * This effectively positions the object post-layout, in addition to wherever the object's
19917      * layout placed it.
19918      *
19919      * @param translationY The vertical position of this view relative to its top position,
19920      * in pixels.
19921      *
19922      * @attr ref android.R.styleable#View_translationY
19923      */
19924     @RemotableViewMethod
setTranslationY(float translationY)19925     public void setTranslationY(float translationY) {
19926         if (translationY != getTranslationY()) {
19927             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
19928             invalidateViewProperty(true, false);
19929             mRenderNode.setTranslationY(translationY);
19930             invalidateViewProperty(false, true);
19931 
19932             invalidateParentIfNeededAndWasQuickRejected();
19933             notifySubtreeAccessibilityStateChangedIfNeeded();
19934         }
19935     }
19936 
19937     /**
19938      * The depth location of this view relative to its {@link #getElevation() elevation}.
19939      *
19940      * @return The depth of this view relative to its elevation.
19941      */
19942     @ViewDebug.ExportedProperty(category = "drawing")
19943     @InspectableProperty
getTranslationZ()19944     public float getTranslationZ() {
19945         return mRenderNode.getTranslationZ();
19946     }
19947 
19948     /**
19949      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
19950      *
19951      * @attr ref android.R.styleable#View_translationZ
19952      */
19953     @RemotableViewMethod
setTranslationZ(float translationZ)19954     public void setTranslationZ(float translationZ) {
19955         if (translationZ != getTranslationZ()) {
19956             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
19957             invalidateViewProperty(true, false);
19958             mRenderNode.setTranslationZ(translationZ);
19959             invalidateViewProperty(false, true);
19960 
19961             invalidateParentIfNeededAndWasQuickRejected();
19962         }
19963     }
19964 
19965     /**
19966      * Changes the transformation matrix on the view. This is used in animation frameworks,
19967      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
19968      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
19969      * Application developers should use transformation methods like {@link #setRotation(float)},
19970      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
19971      * and {@link #setTranslationY(float)} (float)}} instead.
19972      *
19973      * @param matrix The matrix, null indicates that the matrix should be cleared.
19974      * @see #getAnimationMatrix()
19975      */
setAnimationMatrix(@ullable Matrix matrix)19976     public void setAnimationMatrix(@Nullable Matrix matrix) {
19977         invalidateViewProperty(true, false);
19978         mRenderNode.setAnimationMatrix(matrix);
19979         invalidateViewProperty(false, true);
19980 
19981         invalidateParentIfNeededAndWasQuickRejected();
19982     }
19983 
19984     /**
19985      * Return the current transformation matrix of the view. This is used in animation frameworks,
19986      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
19987      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
19988      * Application developers should use transformation methods like {@link #setRotation(float)},
19989      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
19990      * and {@link #setTranslationY(float)} (float)}} instead.
19991      *
19992      * @return the Matrix, null indicates there is no transformation
19993      * @see #setAnimationMatrix(Matrix)
19994      */
19995     @Nullable
getAnimationMatrix()19996     public Matrix getAnimationMatrix() {
19997         return mRenderNode.getAnimationMatrix();
19998     }
19999 
20000     /**
20001      * Returns the current StateListAnimator if exists.
20002      *
20003      * @return StateListAnimator or null if it does not exists
20004      * @see    #setStateListAnimator(android.animation.StateListAnimator)
20005      */
20006     @InspectableProperty
getStateListAnimator()20007     public StateListAnimator getStateListAnimator() {
20008         return mStateListAnimator;
20009     }
20010 
20011     /**
20012      * Attaches the provided StateListAnimator to this View.
20013      * <p>
20014      * Any previously attached StateListAnimator will be detached.
20015      *
20016      * @param stateListAnimator The StateListAnimator to update the view
20017      * @see android.animation.StateListAnimator
20018      */
setStateListAnimator(StateListAnimator stateListAnimator)20019     public void setStateListAnimator(StateListAnimator stateListAnimator) {
20020         if (mStateListAnimator == stateListAnimator) {
20021             return;
20022         }
20023         if (mStateListAnimator != null) {
20024             mStateListAnimator.setTarget(null);
20025         }
20026         mStateListAnimator = stateListAnimator;
20027         if (stateListAnimator != null) {
20028             stateListAnimator.setTarget(this);
20029             if (isAttachedToWindow()) {
20030                 stateListAnimator.setState(getDrawableState());
20031             }
20032         }
20033     }
20034 
20035     /**
20036      * Returns whether the Outline should be used to clip the contents of the View.
20037      * <p>
20038      * Note that this flag will only be respected if the View's Outline returns true from
20039      * {@link Outline#canClip()}.
20040      *
20041      * @see #setOutlineProvider(ViewOutlineProvider)
20042      * @see #setClipToOutline(boolean)
20043      */
getClipToOutline()20044     public final boolean getClipToOutline() {
20045         return mRenderNode.getClipToOutline();
20046     }
20047 
20048     /**
20049      * Sets whether the View's Outline should be used to clip the contents of the View.
20050      * <p>
20051      * Only a single non-rectangular clip can be applied on a View at any time.
20052      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
20053      * circular reveal} animation take priority over Outline clipping, and
20054      * child Outline clipping takes priority over Outline clipping done by a
20055      * parent.
20056      * <p>
20057      * Note that this flag will only be respected if the View's Outline returns true from
20058      * {@link Outline#canClip()}.
20059      *
20060      * @see #setOutlineProvider(ViewOutlineProvider)
20061      * @see #getClipToOutline()
20062      *
20063      * @attr ref android.R.styleable#View_clipToOutline
20064      */
20065     @RemotableViewMethod
setClipToOutline(boolean clipToOutline)20066     public void setClipToOutline(boolean clipToOutline) {
20067         damageInParent();
20068         if (getClipToOutline() != clipToOutline) {
20069             mRenderNode.setClipToOutline(clipToOutline);
20070         }
20071     }
20072 
20073     // correspond to the enum values of View_outlineProvider
20074     private static final int PROVIDER_BACKGROUND = 0;
20075     private static final int PROVIDER_NONE = 1;
20076     private static final int PROVIDER_BOUNDS = 2;
20077     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)20078     private void setOutlineProviderFromAttribute(int providerInt) {
20079         switch (providerInt) {
20080             case PROVIDER_BACKGROUND:
20081                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
20082                 break;
20083             case PROVIDER_NONE:
20084                 setOutlineProvider(null);
20085                 break;
20086             case PROVIDER_BOUNDS:
20087                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
20088                 break;
20089             case PROVIDER_PADDED_BOUNDS:
20090                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
20091                 break;
20092         }
20093     }
20094 
20095     /**
20096      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
20097      * the shape of the shadow it casts, and enables outline clipping.
20098      * <p>
20099      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
20100      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
20101      * outline provider with this method allows this behavior to be overridden.
20102      * <p>
20103      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
20104      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
20105      * <p>
20106      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
20107      *
20108      * @see #setClipToOutline(boolean)
20109      * @see #getClipToOutline()
20110      * @see #getOutlineProvider()
20111      */
setOutlineProvider(ViewOutlineProvider provider)20112     public void setOutlineProvider(ViewOutlineProvider provider) {
20113         if (mOutlineProvider != provider) {
20114             mOutlineProvider = provider;
20115             invalidateOutline();
20116         }
20117     }
20118 
20119     /**
20120      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
20121      * that defines the shape of the shadow it casts, and enables outline clipping.
20122      *
20123      * @see #setOutlineProvider(ViewOutlineProvider)
20124      */
20125     @InspectableProperty
getOutlineProvider()20126     public ViewOutlineProvider getOutlineProvider() {
20127         return mOutlineProvider;
20128     }
20129 
20130     /**
20131      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
20132      *
20133      * @see #setOutlineProvider(ViewOutlineProvider)
20134      */
invalidateOutline()20135     public void invalidateOutline() {
20136         rebuildOutline();
20137 
20138         notifySubtreeAccessibilityStateChangedIfNeeded();
20139         invalidateViewProperty(false, false);
20140     }
20141 
20142     /**
20143      * Internal version of {@link #invalidateOutline()} which invalidates the
20144      * outline without invalidating the view itself. This is intended to be called from
20145      * within methods in the View class itself which are the result of the view being
20146      * invalidated already. For example, when we are drawing the background of a View,
20147      * we invalidate the outline in case it changed in the meantime, but we do not
20148      * need to invalidate the view because we're already drawing the background as part
20149      * of drawing the view in response to an earlier invalidation of the view.
20150      */
rebuildOutline()20151     private void rebuildOutline() {
20152         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
20153         if (mAttachInfo == null) return;
20154 
20155         if (mOutlineProvider == null) {
20156             // no provider, remove outline
20157             mRenderNode.setOutline(null);
20158         } else {
20159             final Outline outline = mAttachInfo.mTmpOutline;
20160             outline.setEmpty();
20161             outline.setAlpha(1.0f);
20162 
20163             mOutlineProvider.getOutline(this, outline);
20164             mRenderNode.setOutline(outline);
20165         }
20166     }
20167 
20168     /**
20169      * HierarchyViewer only
20170      *
20171      * @hide
20172      */
20173     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()20174     public boolean hasShadow() {
20175         return mRenderNode.hasShadow();
20176     }
20177 
20178     /**
20179      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
20180      * elevation value.
20181      * <p>
20182      * By default the shadow color is black. Generally, this color will be opaque so the intensity
20183      * of the shadow is consistent between different views with different colors.
20184      * <p>
20185      * The opacity of the final spot shadow is a function of the shadow caster height, the
20186      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
20187      * {@link android.R.attr#spotShadowAlpha} theme attribute.
20188      *
20189      * @attr ref android.R.styleable#View_outlineSpotShadowColor
20190      * @param color The color this View will cast for its elevation spot shadow.
20191      */
setOutlineSpotShadowColor(@olorInt int color)20192     public void setOutlineSpotShadowColor(@ColorInt int color) {
20193         if (mRenderNode.setSpotShadowColor(color)) {
20194             invalidateViewProperty(true, true);
20195         }
20196     }
20197 
20198     /**
20199      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
20200      * was set
20201      */
20202     @InspectableProperty
getOutlineSpotShadowColor()20203     public @ColorInt int getOutlineSpotShadowColor() {
20204         return mRenderNode.getSpotShadowColor();
20205     }
20206 
20207     /**
20208      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
20209      * elevation value.
20210      * <p>
20211      * By default the shadow color is black. Generally, this color will be opaque so the intensity
20212      * of the shadow is consistent between different views with different colors.
20213      * <p>
20214      * The opacity of the final ambient shadow is a function of the shadow caster height, the
20215      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
20216      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
20217      *
20218      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
20219      * @param color The color this View will cast for its elevation shadow.
20220      */
setOutlineAmbientShadowColor(@olorInt int color)20221     public void setOutlineAmbientShadowColor(@ColorInt int color) {
20222         if (mRenderNode.setAmbientShadowColor(color)) {
20223             invalidateViewProperty(true, true);
20224         }
20225     }
20226 
20227     /**
20228      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
20229      * nothing was set
20230      */
20231     @InspectableProperty
getOutlineAmbientShadowColor()20232     public @ColorInt int getOutlineAmbientShadowColor() {
20233         return mRenderNode.getAmbientShadowColor();
20234     }
20235 
20236 
20237     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)20238     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
20239         mRenderNode.setRevealClip(shouldClip, x, y, radius);
20240         invalidateViewProperty(false, false);
20241     }
20242 
20243     /**
20244      * Hit rectangle in parent's coordinates
20245      *
20246      * @param outRect The hit rectangle of the view.
20247      */
getHitRect(Rect outRect)20248     public void getHitRect(Rect outRect) {
20249         if (hasIdentityMatrix() || mAttachInfo == null) {
20250             outRect.set(mLeft, mTop, mRight, mBottom);
20251         } else {
20252             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
20253             tmpRect.set(0, 0, getWidth(), getHeight());
20254             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
20255             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
20256                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
20257         }
20258     }
20259 
20260     /**
20261      * Determines whether the given point, in local coordinates is inside the view.
20262      */
pointInView(float localX, float localY)20263     /*package*/ final boolean pointInView(float localX, float localY) {
20264         return pointInView(localX, localY, 0);
20265     }
20266 
20267     /**
20268      * Utility method to determine whether the given point, in local coordinates,
20269      * is inside the view, where the area of the view is expanded by the slop factor.
20270      * This method is called while processing touch-move events to determine if the event
20271      * is still within the view.
20272      *
20273      * @hide
20274      */
20275     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)20276     public boolean pointInView(float localX, float localY, float slop) {
20277         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
20278                 localY < ((mBottom - mTop) + slop);
20279     }
20280 
20281     /**
20282      * When a view has focus and the user navigates away from it, the next view is searched for
20283      * starting from the rectangle filled in by this method.
20284      *
20285      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
20286      * of the view.  However, if your view maintains some idea of internal selection,
20287      * such as a cursor, or a selected row or column, you should override this method and
20288      * fill in a more specific rectangle.
20289      *
20290      * @param r The rectangle to fill in, in this view's coordinates.
20291      */
getFocusedRect(Rect r)20292     public void getFocusedRect(Rect r) {
20293         getDrawingRect(r);
20294     }
20295 
20296     /**
20297      * Sets {@code r} to the coordinates of the non-clipped area of this view in
20298      * the coordinate space of the view's root view. Sets {@code globalOffset}
20299      * to the offset of the view's x and y coordinates from the coordinate space
20300      * origin, which is the top left corner of the root view irrespective of
20301      * screen decorations and system UI elements.
20302      *
20303      * <p>To convert {@code r} to coordinates relative to the top left corner of
20304      * this view (without taking view rotations into account), offset {@code r}
20305      * by the inverse values of
20306      * {@code globalOffset}&mdash;{@code r.offset(-globalOffset.x,
20307      * -globalOffset.y)}&mdash;which is equivalent to calling
20308      * {@link #getLocalVisibleRect(Rect) getLocalVisibleRect(Rect)}.
20309      *
20310      * <p><b>Note:</b> Do not use this method to determine the size of a window
20311      * in multi-window mode; use
20312      * {@link WindowManager#getCurrentWindowMetrics()}.
20313      *
20314      * @param r If the method returns true, contains the coordinates of the
20315      *      visible portion of this view in the coordinate space of the view's
20316      *      root view. If the method returns false, the contents of {@code r}
20317      *      are undefined.
20318      * @param globalOffset If the method returns true, contains the offset of
20319      *      the x and y coordinates of this view from the top left corner of the
20320      *      view's root view. If the method returns false, the contents of
20321      *      {@code globalOffset} are undefined. The argument can be null (see
20322      *      {@link #getGlobalVisibleRect(Rect) getGlobalVisibleRect(Rect)}.
20323      * @return true if at least part of the view is visible within the root
20324      *      view; false if the view is completely clipped or translated out of
20325      *      the visible area of the root view.
20326      *
20327      * @see #getLocalVisibleRect(Rect)
20328      */
getGlobalVisibleRect(Rect r, Point globalOffset)20329     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
20330         int width = mRight - mLeft;
20331         int height = mBottom - mTop;
20332         if (width > 0 && height > 0) {
20333             r.set(0, 0, width, height);
20334             if (globalOffset != null) {
20335                 globalOffset.set(-mScrollX, -mScrollY);
20336             }
20337             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
20338         }
20339         return false;
20340     }
20341 
20342     /**
20343      * Sets {@code r} to the coordinates of the non-clipped area of this view in
20344      * the coordinate space of the view's root view.
20345      *
20346      * <p>See {@link #getGlobalVisibleRect(Rect, Point)
20347      * getGlobalVisibleRect(Rect, Point)} for more information.
20348      *
20349      * @param r If the method returns true, contains the coordinates of the
20350      *      visible portion of this view in the coordinate space of the view's
20351      *      root view. If the method returns false, the contents of {@code r}
20352      *      are undefined.
20353      * @return true if at least part of the view is visible within the root
20354      *      view; otherwise false.
20355      */
getGlobalVisibleRect(Rect r)20356     public final boolean getGlobalVisibleRect(Rect r) {
20357         return getGlobalVisibleRect(r, null);
20358     }
20359 
20360     /**
20361      * Sets {@code r} to the coordinates of the non-clipped area of this view
20362      * relative to the top left corner of the view.
20363      *
20364      * <p>If the view is clipped on the left or top, the left and top
20365      * coordinates are offset from 0 by the clipped amount. For example, if the
20366      * view is off screen 50px on the left and 30px at the top, the left and top
20367      * coordinates are 50 and 30 respectively.
20368      *
20369      * <p>If the view is clipped on the right or bottom, the right and bottom
20370      * coordinates are reduced by the clipped amount. For example, if the view
20371      * is off screen 40px on the right and 20px at the bottom, the right
20372      * coordinate is the view width - 40, and the bottom coordinate is the view
20373      * height - 20.
20374      *
20375      * @param r If the method returns true, contains the coordinates of the
20376      *      visible portion of this view relative to the top left corner of the
20377      *      view. If the method returns false, the contents of {@code r} are
20378      *      undefined.
20379      * @return true if at least part of the view is visible; false if the view
20380      *      is completely clipped or translated out of the visible area.
20381      *
20382      * @see #getGlobalVisibleRect(Rect, Point)
20383      */
getLocalVisibleRect(Rect r)20384     public final boolean getLocalVisibleRect(Rect r) {
20385         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
20386         if (getGlobalVisibleRect(r, offset)) {
20387             r.offset(-offset.x, -offset.y); // make r local
20388             return true;
20389         }
20390         return false;
20391     }
20392 
20393     /**
20394      * Offset this view's vertical location by the specified number of pixels.
20395      *
20396      * @param offset the number of pixels to offset the view by
20397      */
offsetTopAndBottom(int offset)20398     public void offsetTopAndBottom(int offset) {
20399         if (offset != 0) {
20400             final boolean matrixIsIdentity = hasIdentityMatrix();
20401             if (matrixIsIdentity) {
20402                 if (isHardwareAccelerated()) {
20403                     invalidateViewProperty(false, false);
20404                 } else {
20405                     final ViewParent p = mParent;
20406                     if (p != null && mAttachInfo != null) {
20407                         final Rect r = mAttachInfo.mTmpInvalRect;
20408                         int minTop;
20409                         int maxBottom;
20410                         int yLoc;
20411                         if (offset < 0) {
20412                             minTop = mTop + offset;
20413                             maxBottom = mBottom;
20414                             yLoc = offset;
20415                         } else {
20416                             minTop = mTop;
20417                             maxBottom = mBottom + offset;
20418                             yLoc = 0;
20419                         }
20420                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
20421                         p.invalidateChild(this, r);
20422                     }
20423                 }
20424             } else {
20425                 invalidateViewProperty(false, false);
20426             }
20427 
20428             mTop += offset;
20429             mBottom += offset;
20430             mRenderNode.offsetTopAndBottom(offset);
20431             if (isHardwareAccelerated()) {
20432                 invalidateViewProperty(false, false);
20433                 invalidateParentIfNeededAndWasQuickRejected();
20434             } else {
20435                 if (!matrixIsIdentity) {
20436                     invalidateViewProperty(false, true);
20437                 }
20438                 invalidateParentIfNeeded();
20439             }
20440             notifySubtreeAccessibilityStateChangedIfNeeded();
20441         }
20442     }
20443 
20444     /**
20445      * Offset this view's horizontal location by the specified amount of pixels.
20446      *
20447      * @param offset the number of pixels to offset the view by
20448      */
offsetLeftAndRight(int offset)20449     public void offsetLeftAndRight(int offset) {
20450         if (offset != 0) {
20451             final boolean matrixIsIdentity = hasIdentityMatrix();
20452             if (matrixIsIdentity) {
20453                 if (isHardwareAccelerated()) {
20454                     invalidateViewProperty(false, false);
20455                 } else {
20456                     final ViewParent p = mParent;
20457                     if (p != null && mAttachInfo != null) {
20458                         final Rect r = mAttachInfo.mTmpInvalRect;
20459                         int minLeft;
20460                         int maxRight;
20461                         if (offset < 0) {
20462                             minLeft = mLeft + offset;
20463                             maxRight = mRight;
20464                         } else {
20465                             minLeft = mLeft;
20466                             maxRight = mRight + offset;
20467                         }
20468                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
20469                         p.invalidateChild(this, r);
20470                     }
20471                 }
20472             } else {
20473                 invalidateViewProperty(false, false);
20474             }
20475 
20476             mLeft += offset;
20477             mRight += offset;
20478             mRenderNode.offsetLeftAndRight(offset);
20479             if (isHardwareAccelerated()) {
20480                 invalidateViewProperty(false, false);
20481                 invalidateParentIfNeededAndWasQuickRejected();
20482             } else {
20483                 if (!matrixIsIdentity) {
20484                     invalidateViewProperty(false, true);
20485                 }
20486                 invalidateParentIfNeeded();
20487             }
20488             notifySubtreeAccessibilityStateChangedIfNeeded();
20489         }
20490     }
20491 
20492     /**
20493      * Get the LayoutParams associated with this view. All views should have
20494      * layout parameters. These supply parameters to the <i>parent</i> of this
20495      * view specifying how it should be arranged. There are many subclasses of
20496      * ViewGroup.LayoutParams, and these correspond to the different subclasses
20497      * of ViewGroup that are responsible for arranging their children.
20498      *
20499      * This method may return null if this View is not attached to a parent
20500      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
20501      * was not invoked successfully. When a View is attached to a parent
20502      * ViewGroup, this method must not return null.
20503      *
20504      * @return The LayoutParams associated with this view, or null if no
20505      *         parameters have been set yet
20506      */
20507     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()20508     public ViewGroup.LayoutParams getLayoutParams() {
20509         return mLayoutParams;
20510     }
20511 
20512     /**
20513      * Set the layout parameters associated with this view. These supply
20514      * parameters to the <i>parent</i> of this view specifying how it should be
20515      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
20516      * correspond to the different subclasses of ViewGroup that are responsible
20517      * for arranging their children.
20518      *
20519      * @param params The layout parameters for this view, cannot be null
20520      */
setLayoutParams(ViewGroup.LayoutParams params)20521     public void setLayoutParams(ViewGroup.LayoutParams params) {
20522         if (params == null) {
20523             throw new NullPointerException("Layout parameters cannot be null");
20524         }
20525         mLayoutParams = params;
20526         resolveLayoutParams();
20527         if (mParent instanceof ViewGroup) {
20528             ((ViewGroup) mParent).onSetLayoutParams(this, params);
20529         }
20530         requestLayout();
20531     }
20532 
20533     /**
20534      * Resolve the layout parameters depending on the resolved layout direction
20535      *
20536      * @hide
20537      */
resolveLayoutParams()20538     public void resolveLayoutParams() {
20539         if (mLayoutParams != null) {
20540             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
20541         }
20542     }
20543 
20544     /**
20545      * Set the scrolled position of your view. This will cause a call to
20546      * {@link #onScrollChanged(int, int, int, int)} and the view will be
20547      * invalidated.
20548      * @param x the x position to scroll to
20549      * @param y the y position to scroll to
20550      */
scrollTo(int x, int y)20551     public void scrollTo(int x, int y) {
20552         if (mScrollX != x || mScrollY != y) {
20553             int oldX = mScrollX;
20554             int oldY = mScrollY;
20555             mScrollX = x;
20556             mScrollY = y;
20557             invalidateParentCaches();
20558             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
20559             if (!awakenScrollBars()) {
20560                 postInvalidateOnAnimation();
20561             }
20562         }
20563     }
20564 
20565     /**
20566      * Move the scrolled position of your view. This will cause a call to
20567      * {@link #onScrollChanged(int, int, int, int)} and the view will be
20568      * invalidated.
20569      * @param x the amount of pixels to scroll by horizontally
20570      * @param y the amount of pixels to scroll by vertically
20571      */
scrollBy(int x, int y)20572     public void scrollBy(int x, int y) {
20573         scrollTo(mScrollX + x, mScrollY + y);
20574     }
20575 
20576     /**
20577      * <p>Trigger the scrollbars to draw. When invoked this method starts an
20578      * animation to fade the scrollbars out after a default delay. If a subclass
20579      * provides animated scrolling, the start delay should equal the duration
20580      * of the scrolling animation.</p>
20581      *
20582      * <p>The animation starts only if at least one of the scrollbars is
20583      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
20584      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
20585      * this method returns true, and false otherwise. If the animation is
20586      * started, this method calls {@link #invalidate()}; in that case the
20587      * caller should not call {@link #invalidate()}.</p>
20588      *
20589      * <p>This method should be invoked every time a subclass directly updates
20590      * the scroll parameters.</p>
20591      *
20592      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
20593      * and {@link #scrollTo(int, int)}.</p>
20594      *
20595      * @return true if the animation is played, false otherwise
20596      *
20597      * @see #awakenScrollBars(int)
20598      * @see #scrollBy(int, int)
20599      * @see #scrollTo(int, int)
20600      * @see #isHorizontalScrollBarEnabled()
20601      * @see #isVerticalScrollBarEnabled()
20602      * @see #setHorizontalScrollBarEnabled(boolean)
20603      * @see #setVerticalScrollBarEnabled(boolean)
20604      */
awakenScrollBars()20605     protected boolean awakenScrollBars() {
20606         return mScrollCache != null &&
20607                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
20608     }
20609 
20610     /**
20611      * Trigger the scrollbars to draw.
20612      * This method differs from awakenScrollBars() only in its default duration.
20613      * initialAwakenScrollBars() will show the scroll bars for longer than
20614      * usual to give the user more of a chance to notice them.
20615      *
20616      * @return true if the animation is played, false otherwise.
20617      */
initialAwakenScrollBars()20618     private boolean initialAwakenScrollBars() {
20619         return mScrollCache != null &&
20620                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
20621     }
20622 
20623     /**
20624      * <p>
20625      * Trigger the scrollbars to draw. When invoked this method starts an
20626      * animation to fade the scrollbars out after a fixed delay. If a subclass
20627      * provides animated scrolling, the start delay should equal the duration of
20628      * the scrolling animation.
20629      * </p>
20630      *
20631      * <p>
20632      * The animation starts only if at least one of the scrollbars is enabled,
20633      * as specified by {@link #isHorizontalScrollBarEnabled()} and
20634      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
20635      * this method returns true, and false otherwise. If the animation is
20636      * started, this method calls {@link #invalidate()}; in that case the caller
20637      * should not call {@link #invalidate()}.
20638      * </p>
20639      *
20640      * <p>
20641      * This method should be invoked every time a subclass directly updates the
20642      * scroll parameters.
20643      * </p>
20644      *
20645      * @param startDelay the delay, in milliseconds, after which the animation
20646      *        should start; when the delay is 0, the animation starts
20647      *        immediately
20648      * @return true if the animation is played, false otherwise
20649      *
20650      * @see #scrollBy(int, int)
20651      * @see #scrollTo(int, int)
20652      * @see #isHorizontalScrollBarEnabled()
20653      * @see #isVerticalScrollBarEnabled()
20654      * @see #setHorizontalScrollBarEnabled(boolean)
20655      * @see #setVerticalScrollBarEnabled(boolean)
20656      */
awakenScrollBars(int startDelay)20657     protected boolean awakenScrollBars(int startDelay) {
20658         return awakenScrollBars(startDelay, true);
20659     }
20660 
20661     /**
20662      * <p>
20663      * Trigger the scrollbars to draw. When invoked this method starts an
20664      * animation to fade the scrollbars out after a fixed delay. If a subclass
20665      * provides animated scrolling, the start delay should equal the duration of
20666      * the scrolling animation.
20667      * </p>
20668      *
20669      * <p>
20670      * The animation starts only if at least one of the scrollbars is enabled,
20671      * as specified by {@link #isHorizontalScrollBarEnabled()} and
20672      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
20673      * this method returns true, and false otherwise. If the animation is
20674      * started, this method calls {@link #invalidate()} if the invalidate parameter
20675      * is set to true; in that case the caller
20676      * should not call {@link #invalidate()}.
20677      * </p>
20678      *
20679      * <p>
20680      * This method should be invoked every time a subclass directly updates the
20681      * scroll parameters.
20682      * </p>
20683      *
20684      * @param startDelay the delay, in milliseconds, after which the animation
20685      *        should start; when the delay is 0, the animation starts
20686      *        immediately
20687      *
20688      * @param invalidate Whether this method should call invalidate
20689      *
20690      * @return true if the animation is played, false otherwise
20691      *
20692      * @see #scrollBy(int, int)
20693      * @see #scrollTo(int, int)
20694      * @see #isHorizontalScrollBarEnabled()
20695      * @see #isVerticalScrollBarEnabled()
20696      * @see #setHorizontalScrollBarEnabled(boolean)
20697      * @see #setVerticalScrollBarEnabled(boolean)
20698      */
awakenScrollBars(int startDelay, boolean invalidate)20699     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
20700         final ScrollabilityCache scrollCache = mScrollCache;
20701 
20702         if (scrollCache == null || !scrollCache.fadeScrollBars) {
20703             return false;
20704         }
20705 
20706         if (scrollCache.scrollBar == null) {
20707             scrollCache.scrollBar = new ScrollBarDrawable();
20708             scrollCache.scrollBar.setState(getDrawableState());
20709             scrollCache.scrollBar.setCallback(this);
20710         }
20711 
20712         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
20713 
20714             if (invalidate) {
20715                 // Invalidate to show the scrollbars
20716                 postInvalidateOnAnimation();
20717             }
20718 
20719             if (scrollCache.state == ScrollabilityCache.OFF) {
20720                 // FIXME: this is copied from WindowManagerService.
20721                 // We should get this value from the system when it
20722                 // is possible to do so.
20723                 final int KEY_REPEAT_FIRST_DELAY = 750;
20724                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
20725             }
20726 
20727             // Tell mScrollCache when we should start fading. This may
20728             // extend the fade start time if one was already scheduled
20729             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
20730             scrollCache.fadeStartTime = fadeStartTime;
20731             scrollCache.state = ScrollabilityCache.ON;
20732 
20733             // Schedule our fader to run, unscheduling any old ones first
20734             if (mAttachInfo != null) {
20735                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
20736                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
20737             }
20738 
20739             return true;
20740         }
20741 
20742         return false;
20743     }
20744 
20745     /**
20746      * Do not invalidate views which are not visible and which are not running an animation. They
20747      * will not get drawn and they should not set dirty flags as if they will be drawn
20748      */
skipInvalidate()20749     private boolean skipInvalidate() {
20750         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
20751                 (!(mParent instanceof ViewGroup) ||
20752                         !((ViewGroup) mParent).isViewTransitioning(this));
20753     }
20754 
20755     /**
20756      * Mark the area defined by dirty as needing to be drawn. If the view is
20757      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
20758      * point in the future.
20759      * <p>
20760      * This must be called from a UI thread. To call from a non-UI thread, call
20761      * {@link #postInvalidate()}.
20762      * <p>
20763      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
20764      * {@code dirty}.
20765      *
20766      * @param dirty the rectangle representing the bounds of the dirty region
20767      *
20768      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
20769      * the importance of the dirty rectangle. In API 21 the given rectangle is
20770      * ignored entirely in favor of an internally-calculated area instead.
20771      * Because of this, clients are encouraged to just call {@link #invalidate()}.
20772      */
20773     @Deprecated
invalidate(Rect dirty)20774     public void invalidate(Rect dirty) {
20775         final int scrollX = mScrollX;
20776         final int scrollY = mScrollY;
20777         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
20778                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
20779     }
20780 
20781     /**
20782      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
20783      * coordinates of the dirty rect are relative to the view. If the view is
20784      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
20785      * point in the future.
20786      * <p>
20787      * This must be called from a UI thread. To call from a non-UI thread, call
20788      * {@link #postInvalidate()}.
20789      *
20790      * @param l the left position of the dirty region
20791      * @param t the top position of the dirty region
20792      * @param r the right position of the dirty region
20793      * @param b the bottom position of the dirty region
20794      *
20795      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
20796      * the importance of the dirty rectangle. In API 21 the given rectangle is
20797      * ignored entirely in favor of an internally-calculated area instead.
20798      * Because of this, clients are encouraged to just call {@link #invalidate()}.
20799      */
20800     @Deprecated
invalidate(int l, int t, int r, int b)20801     public void invalidate(int l, int t, int r, int b) {
20802         final int scrollX = mScrollX;
20803         final int scrollY = mScrollY;
20804         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
20805     }
20806 
20807     /**
20808      * Invalidate the whole view. If the view is visible,
20809      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
20810      * the future.
20811      * <p>
20812      * This must be called from a UI thread. To call from a non-UI thread, call
20813      * {@link #postInvalidate()}.
20814      */
invalidate()20815     public void invalidate() {
20816         invalidate(true);
20817     }
20818 
20819     /**
20820      * This is where the invalidate() work actually happens. A full invalidate()
20821      * causes the drawing cache to be invalidated, but this function can be
20822      * called with invalidateCache set to false to skip that invalidation step
20823      * for cases that do not need it (for example, a component that remains at
20824      * the same dimensions with the same content).
20825      *
20826      * @param invalidateCache Whether the drawing cache for this view should be
20827      *            invalidated as well. This is usually true for a full
20828      *            invalidate, but may be set to false if the View's contents or
20829      *            dimensions have not changed.
20830      * @hide
20831      */
20832     @UnsupportedAppUsage
invalidate(boolean invalidateCache)20833     public void invalidate(boolean invalidateCache) {
20834         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
20835     }
20836 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)20837     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
20838             boolean fullInvalidate) {
20839         if (mGhostView != null) {
20840             mGhostView.invalidate(true);
20841             return;
20842         }
20843 
20844         if (skipInvalidate()) {
20845             return;
20846         }
20847 
20848         // Reset content capture caches
20849         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
20850         mContentCaptureSessionCached = false;
20851 
20852         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
20853                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
20854                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
20855                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
20856             if (fullInvalidate) {
20857                 mLastIsOpaque = isOpaque();
20858                 mPrivateFlags &= ~PFLAG_DRAWN;
20859             }
20860 
20861             mPrivateFlags |= PFLAG_DIRTY;
20862 
20863             if (invalidateCache) {
20864                 mPrivateFlags |= PFLAG_INVALIDATED;
20865                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
20866             }
20867 
20868             // Propagate the damage rectangle to the parent view.
20869             final AttachInfo ai = mAttachInfo;
20870             final ViewParent p = mParent;
20871             if (p != null && ai != null && l < r && t < b) {
20872                 final Rect damage = ai.mTmpInvalRect;
20873                 damage.set(l, t, r, b);
20874                 p.invalidateChild(this, damage);
20875             }
20876 
20877             // Damage the entire projection receiver, if necessary.
20878             if (mBackground != null && mBackground.isProjected()) {
20879                 final View receiver = getProjectionReceiver();
20880                 if (receiver != null) {
20881                     receiver.damageInParent();
20882                 }
20883             }
20884         }
20885     }
20886 
20887     /**
20888      * @return this view's projection receiver, or {@code null} if none exists
20889      */
getProjectionReceiver()20890     private View getProjectionReceiver() {
20891         ViewParent p = getParent();
20892         while (p != null && p instanceof View) {
20893             final View v = (View) p;
20894             if (v.isProjectionReceiver()) {
20895                 return v;
20896             }
20897             p = p.getParent();
20898         }
20899 
20900         return null;
20901     }
20902 
20903     /**
20904      * @return whether the view is a projection receiver
20905      */
isProjectionReceiver()20906     private boolean isProjectionReceiver() {
20907         return mBackground != null;
20908     }
20909 
20910     /**
20911      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
20912      * set any flags or handle all of the cases handled by the default invalidation methods.
20913      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
20914      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
20915      * walk up the hierarchy, transforming the dirty rect as necessary.
20916      *
20917      * The method also handles normal invalidation logic if display list properties are not
20918      * being used in this view. The invalidateParent and forceRedraw flags are used by that
20919      * backup approach, to handle these cases used in the various property-setting methods.
20920      *
20921      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
20922      * are not being used in this view
20923      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
20924      * list properties are not being used in this view
20925      */
20926     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)20927     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
20928         if (!isHardwareAccelerated()
20929                 || !mRenderNode.hasDisplayList()
20930                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
20931             if (invalidateParent) {
20932                 invalidateParentCaches();
20933             }
20934             if (forceRedraw) {
20935                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
20936             }
20937             invalidate(false);
20938         } else {
20939             damageInParent();
20940         }
20941         mPrivateFlags4 |= PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
20942     }
20943 
20944     /**
20945      * Tells the parent view to damage this view's bounds.
20946      *
20947      * @hide
20948      */
damageInParent()20949     protected void damageInParent() {
20950         if (mParent != null && mAttachInfo != null) {
20951             mParent.onDescendantInvalidated(this, this);
20952         }
20953     }
20954 
20955     /**
20956      * Used to indicate that the parent of this view should clear its caches. This functionality
20957      * is used to force the parent to rebuild its display list (when hardware-accelerated),
20958      * which is necessary when various parent-managed properties of the view change, such as
20959      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
20960      * clears the parent caches and does not causes an invalidate event.
20961      *
20962      * @hide
20963      */
20964     @UnsupportedAppUsage
invalidateParentCaches()20965     protected void invalidateParentCaches() {
20966         if (mParent instanceof View) {
20967             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
20968         }
20969     }
20970 
20971     /**
20972      * Used to indicate that the parent of this view should be invalidated. This functionality
20973      * is used to force the parent to rebuild its display list (when hardware-accelerated),
20974      * which is necessary when various parent-managed properties of the view change, such as
20975      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
20976      * an invalidation event to the parent.
20977      *
20978      * @hide
20979      */
20980     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
invalidateParentIfNeeded()20981     protected void invalidateParentIfNeeded() {
20982         if (isHardwareAccelerated() && mParent instanceof View) {
20983             ((View) mParent).invalidate(true);
20984         }
20985     }
20986 
20987     /**
20988      * @hide
20989      */
invalidateParentIfNeededAndWasQuickRejected()20990     protected void invalidateParentIfNeededAndWasQuickRejected() {
20991         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
20992             // View was rejected last time it was drawn by its parent; this may have changed
20993             invalidateParentIfNeeded();
20994         }
20995     }
20996 
20997     /**
20998      * Indicates whether this View is opaque. An opaque View guarantees that it will
20999      * draw all the pixels overlapping its bounds using a fully opaque color.
21000      *
21001      * Subclasses of View should override this method whenever possible to indicate
21002      * whether an instance is opaque. Opaque Views are treated in a special way by
21003      * the View hierarchy, possibly allowing it to perform optimizations during
21004      * invalidate/draw passes.
21005      *
21006      * @return True if this View is guaranteed to be fully opaque, false otherwise.
21007      */
21008     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()21009     public boolean isOpaque() {
21010         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
21011                 getFinalAlpha() >= 1.0f;
21012     }
21013 
21014     /**
21015      * @hide
21016      */
21017     @UnsupportedAppUsage
computeOpaqueFlags()21018     protected void computeOpaqueFlags() {
21019         // Opaque if:
21020         //   - Has a background
21021         //   - Background is opaque
21022         //   - Doesn't have scrollbars or scrollbars overlay
21023 
21024         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
21025             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
21026         } else {
21027             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
21028         }
21029 
21030         final int flags = mViewFlags;
21031         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
21032                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
21033                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
21034             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
21035         } else {
21036             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
21037         }
21038     }
21039 
21040     /**
21041      * @hide
21042      */
hasOpaqueScrollbars()21043     protected boolean hasOpaqueScrollbars() {
21044         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
21045     }
21046 
21047     /**
21048      * @return A handler associated with the thread running the View. This
21049      * handler can be used to pump events in the UI events queue.
21050      */
getHandler()21051     public Handler getHandler() {
21052         final AttachInfo attachInfo = mAttachInfo;
21053         if (attachInfo != null) {
21054             return attachInfo.mHandler;
21055         }
21056         return null;
21057     }
21058 
21059     /**
21060      * Returns the queue of runnable for this view.
21061      *
21062      * @return the queue of runnables for this view
21063      */
getRunQueue()21064     private HandlerActionQueue getRunQueue() {
21065         if (mRunQueue == null) {
21066             mRunQueue = new HandlerActionQueue();
21067         }
21068         return mRunQueue;
21069     }
21070 
21071     /**
21072      * Gets the view root associated with the View.
21073      * @return The view root, or null if none.
21074      * @hide
21075      */
21076     @UnsupportedAppUsage
getViewRootImpl()21077     public ViewRootImpl getViewRootImpl() {
21078         if (mAttachInfo != null) {
21079             return mAttachInfo.mViewRootImpl;
21080         }
21081         return null;
21082     }
21083 
21084     /**
21085      * @hide
21086      */
21087     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getThreadedRenderer()21088     public ThreadedRenderer getThreadedRenderer() {
21089         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
21090     }
21091 
21092     /**
21093      * <p>Causes the Runnable to be added to the message queue.
21094      * The runnable will be run on the user interface thread.</p>
21095      *
21096      * @param action The Runnable that will be executed.
21097      *
21098      * @return Returns true if the Runnable was successfully placed in to the
21099      *         message queue.  Returns false on failure, usually because the
21100      *         looper processing the message queue is exiting.
21101      *
21102      * @see #postDelayed
21103      * @see #removeCallbacks
21104      */
post(Runnable action)21105     public boolean post(Runnable action) {
21106         final AttachInfo attachInfo = mAttachInfo;
21107         if (attachInfo != null) {
21108             return attachInfo.mHandler.post(action);
21109         }
21110 
21111         // Postpone the runnable until we know on which thread it needs to run.
21112         // Assume that the runnable will be successfully placed after attach.
21113         getRunQueue().post(action);
21114         return true;
21115     }
21116 
21117     /**
21118      * <p>Causes the Runnable to be added to the message queue, to be run
21119      * after the specified amount of time elapses.
21120      * The runnable will be run on the user interface thread.</p>
21121      *
21122      * @param action The Runnable that will be executed.
21123      * @param delayMillis The delay (in milliseconds) until the Runnable
21124      *        will be executed.
21125      *
21126      * @return true if the Runnable was successfully placed in to the
21127      *         message queue.  Returns false on failure, usually because the
21128      *         looper processing the message queue is exiting.  Note that a
21129      *         result of true does not mean the Runnable will be processed --
21130      *         if the looper is quit before the delivery time of the message
21131      *         occurs then the message will be dropped.
21132      *
21133      * @see #post
21134      * @see #removeCallbacks
21135      */
postDelayed(Runnable action, long delayMillis)21136     public boolean postDelayed(Runnable action, long delayMillis) {
21137         final AttachInfo attachInfo = mAttachInfo;
21138         if (attachInfo != null) {
21139             return attachInfo.mHandler.postDelayed(action, delayMillis);
21140         }
21141 
21142         // Postpone the runnable until we know on which thread it needs to run.
21143         // Assume that the runnable will be successfully placed after attach.
21144         getRunQueue().postDelayed(action, delayMillis);
21145         return true;
21146     }
21147 
21148     /**
21149      * <p>Causes the Runnable to execute on the next animation time step.
21150      * The runnable will be run on the user interface thread.</p>
21151      *
21152      * @param action The Runnable that will be executed.
21153      *
21154      * @see #postOnAnimationDelayed
21155      * @see #removeCallbacks
21156      */
postOnAnimation(Runnable action)21157     public void postOnAnimation(Runnable action) {
21158         final AttachInfo attachInfo = mAttachInfo;
21159         if (attachInfo != null) {
21160             attachInfo.mViewRootImpl.mChoreographer.postCallback(
21161                     Choreographer.CALLBACK_ANIMATION, action, null);
21162         } else {
21163             // Postpone the runnable until we know
21164             // on which thread it needs to run.
21165             getRunQueue().post(action);
21166         }
21167     }
21168 
21169     /**
21170      * <p>Causes the Runnable to execute on the next animation time step,
21171      * after the specified amount of time elapses.
21172      * The runnable will be run on the user interface thread.</p>
21173      *
21174      * @param action The Runnable that will be executed.
21175      * @param delayMillis The delay (in milliseconds) until the Runnable
21176      *        will be executed.
21177      *
21178      * @see #postOnAnimation
21179      * @see #removeCallbacks
21180      */
postOnAnimationDelayed(Runnable action, long delayMillis)21181     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
21182         final AttachInfo attachInfo = mAttachInfo;
21183         if (attachInfo != null) {
21184             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
21185                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
21186         } else {
21187             // Postpone the runnable until we know
21188             // on which thread it needs to run.
21189             getRunQueue().postDelayed(action, delayMillis);
21190         }
21191     }
21192 
21193     /**
21194      * <p>Removes the specified Runnable from the message queue.</p>
21195      *
21196      * @param action The Runnable to remove from the message handling queue
21197      *
21198      * @return true if this view could ask the Handler to remove the Runnable,
21199      *         false otherwise. When the returned value is true, the Runnable
21200      *         may or may not have been actually removed from the message queue
21201      *         (for instance, if the Runnable was not in the queue already.)
21202      *
21203      * @see #post
21204      * @see #postDelayed
21205      * @see #postOnAnimation
21206      * @see #postOnAnimationDelayed
21207      */
removeCallbacks(Runnable action)21208     public boolean removeCallbacks(Runnable action) {
21209         if (action != null) {
21210             final AttachInfo attachInfo = mAttachInfo;
21211             if (attachInfo != null) {
21212                 attachInfo.mHandler.removeCallbacks(action);
21213                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
21214                         Choreographer.CALLBACK_ANIMATION, action, null);
21215             }
21216             getRunQueue().removeCallbacks(action);
21217         }
21218         return true;
21219     }
21220 
21221     /**
21222      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
21223      * Use this to invalidate the View from a non-UI thread.</p>
21224      *
21225      * <p>This method can be invoked from outside of the UI thread
21226      * only when this View is attached to a window.</p>
21227      *
21228      * @see #invalidate()
21229      * @see #postInvalidateDelayed(long)
21230      */
postInvalidate()21231     public void postInvalidate() {
21232         postInvalidateDelayed(0);
21233     }
21234 
21235     /**
21236      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
21237      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
21238      *
21239      * <p>This method can be invoked from outside of the UI thread
21240      * only when this View is attached to a window.</p>
21241      *
21242      * @param left The left coordinate of the rectangle to invalidate.
21243      * @param top The top coordinate of the rectangle to invalidate.
21244      * @param right The right coordinate of the rectangle to invalidate.
21245      * @param bottom The bottom coordinate of the rectangle to invalidate.
21246      *
21247      * @see #invalidate(int, int, int, int)
21248      * @see #invalidate(Rect)
21249      * @see #postInvalidateDelayed(long, int, int, int, int)
21250      */
postInvalidate(int left, int top, int right, int bottom)21251     public void postInvalidate(int left, int top, int right, int bottom) {
21252         postInvalidateDelayed(0, left, top, right, bottom);
21253     }
21254 
21255     /**
21256      * <p>Cause an invalidate to happen on a subsequent cycle through the event
21257      * loop. Waits for the specified amount of time.</p>
21258      *
21259      * <p>This method can be invoked from outside of the UI thread
21260      * only when this View is attached to a window.</p>
21261      *
21262      * @param delayMilliseconds the duration in milliseconds to delay the
21263      *         invalidation by
21264      *
21265      * @see #invalidate()
21266      * @see #postInvalidate()
21267      */
postInvalidateDelayed(long delayMilliseconds)21268     public void postInvalidateDelayed(long delayMilliseconds) {
21269         // We try only with the AttachInfo because there's no point in invalidating
21270         // if we are not attached to our window
21271         final AttachInfo attachInfo = mAttachInfo;
21272         if (attachInfo != null) {
21273             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
21274         }
21275     }
21276 
21277     /**
21278      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
21279      * through the event loop. Waits for the specified amount of time.</p>
21280      *
21281      * <p>This method can be invoked from outside of the UI thread
21282      * only when this View is attached to a window.</p>
21283      *
21284      * @param delayMilliseconds the duration in milliseconds to delay the
21285      *         invalidation by
21286      * @param left The left coordinate of the rectangle to invalidate.
21287      * @param top The top coordinate of the rectangle to invalidate.
21288      * @param right The right coordinate of the rectangle to invalidate.
21289      * @param bottom The bottom coordinate of the rectangle to invalidate.
21290      *
21291      * @see #invalidate(int, int, int, int)
21292      * @see #invalidate(Rect)
21293      * @see #postInvalidate(int, int, int, int)
21294      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)21295     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
21296             int right, int bottom) {
21297 
21298         // We try only with the AttachInfo because there's no point in invalidating
21299         // if we are not attached to our window
21300         final AttachInfo attachInfo = mAttachInfo;
21301         if (attachInfo != null) {
21302             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
21303             info.target = this;
21304             info.left = left;
21305             info.top = top;
21306             info.right = right;
21307             info.bottom = bottom;
21308 
21309             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
21310         }
21311     }
21312 
21313     /**
21314      * <p>Cause an invalidate to happen on the next animation time step, typically the
21315      * next display frame.</p>
21316      *
21317      * <p>This method can be invoked from outside of the UI thread
21318      * only when this View is attached to a window.</p>
21319      *
21320      * @see #invalidate()
21321      */
postInvalidateOnAnimation()21322     public void postInvalidateOnAnimation() {
21323         // We try only with the AttachInfo because there's no point in invalidating
21324         // if we are not attached to our window
21325         final AttachInfo attachInfo = mAttachInfo;
21326         if (attachInfo != null) {
21327             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
21328         }
21329     }
21330 
21331     /**
21332      * <p>Cause an invalidate of the specified area to happen on the next animation
21333      * time step, typically the next display frame.</p>
21334      *
21335      * <p>This method can be invoked from outside of the UI thread
21336      * only when this View is attached to a window.</p>
21337      *
21338      * @param left The left coordinate of the rectangle to invalidate.
21339      * @param top The top coordinate of the rectangle to invalidate.
21340      * @param right The right coordinate of the rectangle to invalidate.
21341      * @param bottom The bottom coordinate of the rectangle to invalidate.
21342      *
21343      * @see #invalidate(int, int, int, int)
21344      * @see #invalidate(Rect)
21345      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)21346     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
21347         // We try only with the AttachInfo because there's no point in invalidating
21348         // if we are not attached to our window
21349         final AttachInfo attachInfo = mAttachInfo;
21350         if (attachInfo != null) {
21351             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
21352             info.target = this;
21353             info.left = left;
21354             info.top = top;
21355             info.right = right;
21356             info.bottom = bottom;
21357 
21358             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
21359         }
21360     }
21361 
21362     /**
21363      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
21364      * This event is sent at most once every
21365      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
21366      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)21367     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
21368         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21369             AccessibilityEvent event =
21370                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
21371             event.setScrollDeltaX(dx);
21372             event.setScrollDeltaY(dy);
21373             sendAccessibilityEventUnchecked(event);
21374         }
21375     }
21376 
21377     /**
21378      * Called by a parent to request that a child update its values for mScrollX
21379      * and mScrollY if necessary. This will typically be done if the child is
21380      * animating a scroll using a {@link android.widget.Scroller Scroller}
21381      * object.
21382      */
computeScroll()21383     public void computeScroll() {
21384     }
21385 
21386     /**
21387      * <p>Indicate whether the horizontal edges are faded when the view is
21388      * scrolled horizontally.</p>
21389      *
21390      * @return true if the horizontal edges should are faded on scroll, false
21391      *         otherwise
21392      *
21393      * @see #setHorizontalFadingEdgeEnabled(boolean)
21394      *
21395      * @attr ref android.R.styleable#View_requiresFadingEdge
21396      */
isHorizontalFadingEdgeEnabled()21397     public boolean isHorizontalFadingEdgeEnabled() {
21398         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
21399     }
21400 
21401     /**
21402      * <p>Define whether the horizontal edges should be faded when this view
21403      * is scrolled horizontally.</p>
21404      *
21405      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
21406      *                                    be faded when the view is scrolled
21407      *                                    horizontally
21408      *
21409      * @see #isHorizontalFadingEdgeEnabled()
21410      *
21411      * @attr ref android.R.styleable#View_requiresFadingEdge
21412      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)21413     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
21414         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
21415             if (horizontalFadingEdgeEnabled) {
21416                 initScrollCache();
21417             }
21418 
21419             mViewFlags ^= FADING_EDGE_HORIZONTAL;
21420         }
21421     }
21422 
21423     /**
21424      * <p>Indicate whether the vertical edges are faded when the view is
21425      * scrolled horizontally.</p>
21426      *
21427      * @return true if the vertical edges should are faded on scroll, false
21428      *         otherwise
21429      *
21430      * @see #setVerticalFadingEdgeEnabled(boolean)
21431      *
21432      * @attr ref android.R.styleable#View_requiresFadingEdge
21433      */
isVerticalFadingEdgeEnabled()21434     public boolean isVerticalFadingEdgeEnabled() {
21435         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
21436     }
21437 
21438     /**
21439      * <p>Define whether the vertical edges should be faded when this view
21440      * is scrolled vertically.</p>
21441      *
21442      * @param verticalFadingEdgeEnabled true if the vertical edges should
21443      *                                  be faded when the view is scrolled
21444      *                                  vertically
21445      *
21446      * @see #isVerticalFadingEdgeEnabled()
21447      *
21448      * @attr ref android.R.styleable#View_requiresFadingEdge
21449      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)21450     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
21451         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
21452             if (verticalFadingEdgeEnabled) {
21453                 initScrollCache();
21454             }
21455 
21456             mViewFlags ^= FADING_EDGE_VERTICAL;
21457         }
21458     }
21459 
21460     /**
21461      * Get the fading edge flags, used for inspection.
21462      *
21463      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
21464      *         or {@link #FADING_EDGE_HORIZONTAL}
21465      * @hide
21466      */
21467     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
21468             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
21469             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
21470             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
21471     })
getFadingEdge()21472     public int getFadingEdge() {
21473         return mViewFlags & FADING_EDGE_MASK;
21474     }
21475 
21476     /**
21477      * Get the fading edge length, used for inspection
21478      *
21479      * @return The fading edge length or 0
21480      * @hide
21481      */
21482     @InspectableProperty
getFadingEdgeLength()21483     public int getFadingEdgeLength() {
21484         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
21485             return mScrollCache.fadingEdgeLength;
21486         }
21487         return 0;
21488     }
21489 
21490     /**
21491      * Returns the strength, or intensity, of the top faded edge. The strength is
21492      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21493      * returns 0.0 or 1.0 but no value in between.
21494      *
21495      * Subclasses should override this method to provide a smoother fade transition
21496      * when scrolling occurs.
21497      *
21498      * @return the intensity of the top fade as a float between 0.0f and 1.0f
21499      */
getTopFadingEdgeStrength()21500     protected float getTopFadingEdgeStrength() {
21501         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
21502     }
21503 
21504     /**
21505      * Returns the strength, or intensity, of the bottom faded edge. The strength is
21506      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21507      * returns 0.0 or 1.0 but no value in between.
21508      *
21509      * Subclasses should override this method to provide a smoother fade transition
21510      * when scrolling occurs.
21511      *
21512      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
21513      */
getBottomFadingEdgeStrength()21514     protected float getBottomFadingEdgeStrength() {
21515         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
21516                 computeVerticalScrollRange() ? 1.0f : 0.0f;
21517     }
21518 
21519     /**
21520      * Returns the strength, or intensity, of the left faded edge. The strength is
21521      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21522      * returns 0.0 or 1.0 but no value in between.
21523      *
21524      * Subclasses should override this method to provide a smoother fade transition
21525      * when scrolling occurs.
21526      *
21527      * @return the intensity of the left fade as a float between 0.0f and 1.0f
21528      */
getLeftFadingEdgeStrength()21529     protected float getLeftFadingEdgeStrength() {
21530         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
21531     }
21532 
21533     /**
21534      * Returns the strength, or intensity, of the right faded edge. The strength is
21535      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21536      * returns 0.0 or 1.0 but no value in between.
21537      *
21538      * Subclasses should override this method to provide a smoother fade transition
21539      * when scrolling occurs.
21540      *
21541      * @return the intensity of the right fade as a float between 0.0f and 1.0f
21542      */
getRightFadingEdgeStrength()21543     protected float getRightFadingEdgeStrength() {
21544         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
21545                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
21546     }
21547 
21548     /**
21549      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
21550      * scrollbar is not drawn by default.</p>
21551      *
21552      * @return true if the horizontal scrollbar should be painted, false
21553      *         otherwise
21554      *
21555      * @see #setHorizontalScrollBarEnabled(boolean)
21556      */
isHorizontalScrollBarEnabled()21557     public boolean isHorizontalScrollBarEnabled() {
21558         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
21559     }
21560 
21561     /**
21562      * <p>Define whether the horizontal scrollbar should be drawn or not. The
21563      * scrollbar is not drawn by default.</p>
21564      *
21565      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
21566      *                                   be painted
21567      *
21568      * @see #isHorizontalScrollBarEnabled()
21569      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)21570     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
21571         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
21572             mViewFlags ^= SCROLLBARS_HORIZONTAL;
21573             computeOpaqueFlags();
21574             resolvePadding();
21575         }
21576     }
21577 
21578     /**
21579      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
21580      * scrollbar is not drawn by default.</p>
21581      *
21582      * @return true if the vertical scrollbar should be painted, false
21583      *         otherwise
21584      *
21585      * @see #setVerticalScrollBarEnabled(boolean)
21586      */
isVerticalScrollBarEnabled()21587     public boolean isVerticalScrollBarEnabled() {
21588         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
21589     }
21590 
21591     /**
21592      * <p>Define whether the vertical scrollbar should be drawn or not. The
21593      * scrollbar is not drawn by default.</p>
21594      *
21595      * @param verticalScrollBarEnabled true if the vertical scrollbar should
21596      *                                 be painted
21597      *
21598      * @see #isVerticalScrollBarEnabled()
21599      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)21600     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
21601         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
21602             mViewFlags ^= SCROLLBARS_VERTICAL;
21603             computeOpaqueFlags();
21604             resolvePadding();
21605         }
21606     }
21607 
21608     /**
21609      * @hide
21610      */
21611     @UnsupportedAppUsage
recomputePadding()21612     protected void recomputePadding() {
21613         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
21614     }
21615 
21616     /**
21617      * Define whether scrollbars will fade when the view is not scrolling.
21618      *
21619      * @param fadeScrollbars whether to enable fading
21620      *
21621      * @attr ref android.R.styleable#View_fadeScrollbars
21622      */
setScrollbarFadingEnabled(boolean fadeScrollbars)21623     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
21624         initScrollCache();
21625         final ScrollabilityCache scrollabilityCache = mScrollCache;
21626         scrollabilityCache.fadeScrollBars = fadeScrollbars;
21627         if (fadeScrollbars) {
21628             scrollabilityCache.state = ScrollabilityCache.OFF;
21629         } else {
21630             scrollabilityCache.state = ScrollabilityCache.ON;
21631         }
21632     }
21633 
21634     /**
21635      *
21636      * Returns true if scrollbars will fade when this view is not scrolling
21637      *
21638      * @return true if scrollbar fading is enabled
21639      *
21640      * @attr ref android.R.styleable#View_fadeScrollbars
21641      */
isScrollbarFadingEnabled()21642     public boolean isScrollbarFadingEnabled() {
21643         return mScrollCache != null && mScrollCache.fadeScrollBars;
21644     }
21645 
21646     /**
21647      *
21648      * Returns the delay before scrollbars fade.
21649      *
21650      * @return the delay before scrollbars fade
21651      *
21652      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
21653      */
21654     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()21655     public int getScrollBarDefaultDelayBeforeFade() {
21656         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
21657                 mScrollCache.scrollBarDefaultDelayBeforeFade;
21658     }
21659 
21660     /**
21661      * Define the delay before scrollbars fade.
21662      *
21663      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
21664      *
21665      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
21666      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)21667     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
21668         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
21669     }
21670 
21671     /**
21672      *
21673      * Returns the scrollbar fade duration.
21674      *
21675      * @return the scrollbar fade duration, in milliseconds
21676      *
21677      * @attr ref android.R.styleable#View_scrollbarFadeDuration
21678      */
21679     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()21680     public int getScrollBarFadeDuration() {
21681         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
21682                 mScrollCache.scrollBarFadeDuration;
21683     }
21684 
21685     /**
21686      * Define the scrollbar fade duration.
21687      *
21688      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
21689      *
21690      * @attr ref android.R.styleable#View_scrollbarFadeDuration
21691      */
setScrollBarFadeDuration(int scrollBarFadeDuration)21692     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
21693         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
21694     }
21695 
21696     /**
21697      *
21698      * Returns the scrollbar size.
21699      *
21700      * @return the scrollbar size
21701      *
21702      * @attr ref android.R.styleable#View_scrollbarSize
21703      */
21704     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()21705     public int getScrollBarSize() {
21706         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
21707                 mScrollCache.scrollBarSize;
21708     }
21709 
21710     /**
21711      * Define the scrollbar size.
21712      *
21713      * @param scrollBarSize - the scrollbar size
21714      *
21715      * @attr ref android.R.styleable#View_scrollbarSize
21716      */
setScrollBarSize(int scrollBarSize)21717     public void setScrollBarSize(int scrollBarSize) {
21718         getScrollCache().scrollBarSize = scrollBarSize;
21719     }
21720 
21721     /**
21722      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
21723      * inset. When inset, they add to the padding of the view. And the scrollbars
21724      * can be drawn inside the padding area or on the edge of the view. For example,
21725      * if a view has a background drawable and you want to draw the scrollbars
21726      * inside the padding specified by the drawable, you can use
21727      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
21728      * appear at the edge of the view, ignoring the padding, then you can use
21729      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
21730      * @param style the style of the scrollbars. Should be one of
21731      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
21732      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
21733      * @see #SCROLLBARS_INSIDE_OVERLAY
21734      * @see #SCROLLBARS_INSIDE_INSET
21735      * @see #SCROLLBARS_OUTSIDE_OVERLAY
21736      * @see #SCROLLBARS_OUTSIDE_INSET
21737      *
21738      * @attr ref android.R.styleable#View_scrollbarStyle
21739      */
setScrollBarStyle(@crollBarStyle int style)21740     public void setScrollBarStyle(@ScrollBarStyle int style) {
21741         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
21742             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
21743             computeOpaqueFlags();
21744             resolvePadding();
21745         }
21746     }
21747 
21748     /**
21749      * <p>Returns the current scrollbar style.</p>
21750      * @return the current scrollbar style
21751      * @see #SCROLLBARS_INSIDE_OVERLAY
21752      * @see #SCROLLBARS_INSIDE_INSET
21753      * @see #SCROLLBARS_OUTSIDE_OVERLAY
21754      * @see #SCROLLBARS_OUTSIDE_INSET
21755      *
21756      * @attr ref android.R.styleable#View_scrollbarStyle
21757      */
21758     @ViewDebug.ExportedProperty(mapping = {
21759             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
21760             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
21761             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
21762             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
21763     })
21764     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
21765             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
21766             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
21767             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
21768             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
21769     })
21770     @ScrollBarStyle
getScrollBarStyle()21771     public int getScrollBarStyle() {
21772         return mViewFlags & SCROLLBARS_STYLE_MASK;
21773     }
21774 
21775     /**
21776      * <p>Compute the horizontal range that the horizontal scrollbar
21777      * represents.</p>
21778      *
21779      * <p>The range is expressed in arbitrary units that must be the same as the
21780      * units used by {@link #computeHorizontalScrollExtent()} and
21781      * {@link #computeHorizontalScrollOffset()}.</p>
21782      *
21783      * <p>The default range is the drawing width of this view.</p>
21784      *
21785      * @return the total horizontal range represented by the horizontal
21786      *         scrollbar
21787      *
21788      * @see #computeHorizontalScrollExtent()
21789      * @see #computeHorizontalScrollOffset()
21790      */
computeHorizontalScrollRange()21791     protected int computeHorizontalScrollRange() {
21792         return getWidth();
21793     }
21794 
21795     /**
21796      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
21797      * within the horizontal range. This value is used to compute the position
21798      * of the thumb within the scrollbar's track.</p>
21799      *
21800      * <p>The range is expressed in arbitrary units that must be the same as the
21801      * units used by {@link #computeHorizontalScrollRange()} and
21802      * {@link #computeHorizontalScrollExtent()}.</p>
21803      *
21804      * <p>The default offset is the scroll offset of this view.</p>
21805      *
21806      * @return the horizontal offset of the scrollbar's thumb
21807      *
21808      * @see #computeHorizontalScrollRange()
21809      * @see #computeHorizontalScrollExtent()
21810      */
computeHorizontalScrollOffset()21811     protected int computeHorizontalScrollOffset() {
21812         return mScrollX;
21813     }
21814 
21815     /**
21816      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
21817      * within the horizontal range. This value is used to compute the length
21818      * of the thumb within the scrollbar's track.</p>
21819      *
21820      * <p>The range is expressed in arbitrary units that must be the same as the
21821      * units used by {@link #computeHorizontalScrollRange()} and
21822      * {@link #computeHorizontalScrollOffset()}.</p>
21823      *
21824      * <p>The default extent is the drawing width of this view.</p>
21825      *
21826      * @return the horizontal extent of the scrollbar's thumb
21827      *
21828      * @see #computeHorizontalScrollRange()
21829      * @see #computeHorizontalScrollOffset()
21830      */
computeHorizontalScrollExtent()21831     protected int computeHorizontalScrollExtent() {
21832         return getWidth();
21833     }
21834 
21835     /**
21836      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
21837      *
21838      * <p>The range is expressed in arbitrary units that must be the same as the
21839      * units used by {@link #computeVerticalScrollExtent()} and
21840      * {@link #computeVerticalScrollOffset()}.</p>
21841      *
21842      * @return the total vertical range represented by the vertical scrollbar
21843      *
21844      * <p>The default range is the drawing height of this view.</p>
21845      *
21846      * @see #computeVerticalScrollExtent()
21847      * @see #computeVerticalScrollOffset()
21848      */
computeVerticalScrollRange()21849     protected int computeVerticalScrollRange() {
21850         return getHeight();
21851     }
21852 
21853     /**
21854      * <p>Compute the vertical offset of the vertical scrollbar's thumb
21855      * within the horizontal range. This value is used to compute the position
21856      * of the thumb within the scrollbar's track.</p>
21857      *
21858      * <p>The range is expressed in arbitrary units that must be the same as the
21859      * units used by {@link #computeVerticalScrollRange()} and
21860      * {@link #computeVerticalScrollExtent()}.</p>
21861      *
21862      * <p>The default offset is the scroll offset of this view.</p>
21863      *
21864      * @return the vertical offset of the scrollbar's thumb
21865      *
21866      * @see #computeVerticalScrollRange()
21867      * @see #computeVerticalScrollExtent()
21868      */
computeVerticalScrollOffset()21869     protected int computeVerticalScrollOffset() {
21870         return mScrollY;
21871     }
21872 
21873     /**
21874      * <p>Compute the vertical extent of the vertical scrollbar's thumb
21875      * within the vertical range. This value is used to compute the length
21876      * of the thumb within the scrollbar's track.</p>
21877      *
21878      * <p>The range is expressed in arbitrary units that must be the same as the
21879      * units used by {@link #computeVerticalScrollRange()} and
21880      * {@link #computeVerticalScrollOffset()}.</p>
21881      *
21882      * <p>The default extent is the drawing height of this view.</p>
21883      *
21884      * @return the vertical extent of the scrollbar's thumb
21885      *
21886      * @see #computeVerticalScrollRange()
21887      * @see #computeVerticalScrollOffset()
21888      */
computeVerticalScrollExtent()21889     protected int computeVerticalScrollExtent() {
21890         return getHeight();
21891     }
21892 
21893     /**
21894      * Check if this view can be scrolled horizontally in a certain direction.
21895      *
21896      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
21897      * in response to user input or not.
21898      *
21899      * @param direction Negative to check scrolling left, positive to check scrolling right.
21900      * @return true if this view can be scrolled in the specified direction, false otherwise.
21901      */
canScrollHorizontally(int direction)21902     public boolean canScrollHorizontally(int direction) {
21903         final int offset = computeHorizontalScrollOffset();
21904         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
21905         if (range == 0) return false;
21906         if (direction < 0) {
21907             return offset > 0;
21908         } else {
21909             return offset < range - 1;
21910         }
21911     }
21912 
21913     /**
21914      * Check if this view can be scrolled vertically in a certain direction.
21915      *
21916      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
21917      * in response to user input or not.
21918      *
21919      * @param direction Negative to check scrolling up, positive to check scrolling down.
21920      * @return true if this view can be scrolled in the specified direction, false otherwise.
21921      */
canScrollVertically(int direction)21922     public boolean canScrollVertically(int direction) {
21923         final int offset = computeVerticalScrollOffset();
21924         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
21925         if (range == 0) return false;
21926         if (direction < 0) {
21927             return offset > 0;
21928         } else {
21929             return offset < range - 1;
21930         }
21931     }
21932 
getScrollIndicatorBounds(@onNull Rect out)21933     void getScrollIndicatorBounds(@NonNull Rect out) {
21934         out.left = mScrollX;
21935         out.right = mScrollX + mRight - mLeft;
21936         out.top = mScrollY;
21937         out.bottom = mScrollY + mBottom - mTop;
21938     }
21939 
onDrawScrollIndicators(@onNull Canvas c)21940     private void onDrawScrollIndicators(@NonNull Canvas c) {
21941         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
21942             // No scroll indicators enabled.
21943             return;
21944         }
21945 
21946         final Drawable dr = mScrollIndicatorDrawable;
21947         if (dr == null) {
21948             // Scroll indicators aren't supported here.
21949             return;
21950         }
21951 
21952         if (mAttachInfo == null) {
21953             // View is not attached.
21954             return;
21955         }
21956 
21957         final int h = dr.getIntrinsicHeight();
21958         final int w = dr.getIntrinsicWidth();
21959         final Rect rect = mAttachInfo.mTmpInvalRect;
21960         getScrollIndicatorBounds(rect);
21961 
21962         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
21963             final boolean canScrollUp = canScrollVertically(-1);
21964             if (canScrollUp) {
21965                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
21966                 dr.draw(c);
21967             }
21968         }
21969 
21970         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
21971             final boolean canScrollDown = canScrollVertically(1);
21972             if (canScrollDown) {
21973                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
21974                 dr.draw(c);
21975             }
21976         }
21977 
21978         final int leftRtl;
21979         final int rightRtl;
21980         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
21981             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
21982             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
21983         } else {
21984             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
21985             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
21986         }
21987 
21988         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
21989         if ((mPrivateFlags3 & leftMask) != 0) {
21990             final boolean canScrollLeft = canScrollHorizontally(-1);
21991             if (canScrollLeft) {
21992                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
21993                 dr.draw(c);
21994             }
21995         }
21996 
21997         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
21998         if ((mPrivateFlags3 & rightMask) != 0) {
21999             final boolean canScrollRight = canScrollHorizontally(1);
22000             if (canScrollRight) {
22001                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
22002                 dr.draw(c);
22003             }
22004         }
22005     }
22006 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)22007     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
22008             @Nullable Rect touchBounds) {
22009         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
22010         if (bounds == null) {
22011             return;
22012         }
22013         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
22014         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
22015                 && !isVerticalScrollBarHidden();
22016         final int size = getHorizontalScrollbarHeight();
22017         final int verticalScrollBarGap = drawVerticalScrollBar ?
22018                 getVerticalScrollbarWidth() : 0;
22019         final int width = mRight - mLeft;
22020         final int height = mBottom - mTop;
22021         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
22022         bounds.left = mScrollX + (mPaddingLeft & inside);
22023         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
22024         bounds.bottom = bounds.top + size;
22025 
22026         if (touchBounds == null) {
22027             return;
22028         }
22029         if (touchBounds != bounds) {
22030             touchBounds.set(bounds);
22031         }
22032         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
22033         if (touchBounds.height() < minTouchTarget) {
22034             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
22035             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
22036             touchBounds.top = touchBounds.bottom - minTouchTarget;
22037         }
22038         if (touchBounds.width() < minTouchTarget) {
22039             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
22040             touchBounds.left -= adjust;
22041             touchBounds.right = touchBounds.left + minTouchTarget;
22042         }
22043     }
22044 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)22045     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
22046         if (mRoundScrollbarRenderer == null) {
22047             getStraightVerticalScrollBarBounds(bounds, touchBounds);
22048         } else {
22049             mRoundScrollbarRenderer.getRoundVerticalScrollBarBounds(
22050                     bounds != null ? bounds : touchBounds);
22051         }
22052     }
22053 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)22054     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
22055             @Nullable Rect touchBounds) {
22056         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
22057         if (bounds == null) {
22058             return;
22059         }
22060         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
22061         final int size = getVerticalScrollbarWidth();
22062         int verticalScrollbarPosition = mVerticalScrollbarPosition;
22063         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
22064             verticalScrollbarPosition = isLayoutRtl() ?
22065                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
22066         }
22067         final int width = mRight - mLeft;
22068         final int height = mBottom - mTop;
22069         switch (verticalScrollbarPosition) {
22070             default:
22071             case SCROLLBAR_POSITION_RIGHT:
22072                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
22073                 break;
22074             case SCROLLBAR_POSITION_LEFT:
22075                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
22076                 break;
22077         }
22078         bounds.top = mScrollY + (mPaddingTop & inside);
22079         bounds.right = bounds.left + size;
22080         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
22081 
22082         if (touchBounds == null) {
22083             return;
22084         }
22085         if (touchBounds != bounds) {
22086             touchBounds.set(bounds);
22087         }
22088         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
22089         if (touchBounds.width() < minTouchTarget) {
22090             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
22091             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
22092                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
22093                 touchBounds.left = touchBounds.right - minTouchTarget;
22094             } else {
22095                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
22096                 touchBounds.right = touchBounds.left + minTouchTarget;
22097             }
22098         }
22099         if (touchBounds.height() < minTouchTarget) {
22100             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
22101             touchBounds.top -= adjust;
22102             touchBounds.bottom = touchBounds.top + minTouchTarget;
22103         }
22104     }
22105 
22106     /**
22107      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
22108      * scrollbars are painted only if they have been awakened first.</p>
22109      *
22110      * @param canvas the canvas on which to draw the scrollbars
22111      *
22112      * @see #awakenScrollBars(int)
22113      */
onDrawScrollBars(@onNull Canvas canvas)22114     protected final void onDrawScrollBars(@NonNull Canvas canvas) {
22115         // scrollbars are drawn only when the animation is running
22116         final ScrollabilityCache cache = mScrollCache;
22117 
22118         if (cache != null) {
22119 
22120             int state = cache.state;
22121 
22122             if (state == ScrollabilityCache.OFF) {
22123                 return;
22124             }
22125 
22126             boolean invalidate = false;
22127 
22128             if (state == ScrollabilityCache.FADING) {
22129                 // We're fading -- get our fade interpolation
22130                 if (cache.interpolatorValues == null) {
22131                     cache.interpolatorValues = new float[1];
22132                 }
22133 
22134                 float[] values = cache.interpolatorValues;
22135 
22136                 // Stops the animation if we're done
22137                 if (cache.scrollBarInterpolator.timeToValues(values) ==
22138                         Interpolator.Result.FREEZE_END) {
22139                     cache.state = ScrollabilityCache.OFF;
22140                 } else {
22141                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
22142                 }
22143 
22144                 // This will make the scroll bars inval themselves after
22145                 // drawing. We only want this when we're fading so that
22146                 // we prevent excessive redraws
22147                 invalidate = true;
22148             } else {
22149                 // We're just on -- but we may have been fading before so
22150                 // reset alpha
22151                 cache.scrollBar.mutate().setAlpha(255);
22152             }
22153 
22154             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
22155             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
22156                     && !isVerticalScrollBarHidden();
22157 
22158             // Fork out the scroll bar drawing for round wearable devices.
22159             if (mRoundScrollbarRenderer != null) {
22160                 if (drawVerticalScrollBar) {
22161                     final Rect bounds = cache.mScrollBarBounds;
22162                     getVerticalScrollBarBounds(bounds, null);
22163                     boolean shouldDrawScrollbarAtLeft =
22164                             (mVerticalScrollbarPosition == SCROLLBAR_POSITION_LEFT)
22165                                     || (mVerticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT
22166                                     && isLayoutRtl());
22167 
22168                     mRoundScrollbarRenderer.drawRoundScrollbars(
22169                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds,
22170                             shouldDrawScrollbarAtLeft);
22171                     if (invalidate) {
22172                         invalidate();
22173                     }
22174                 }
22175                 // Do not draw horizontal scroll bars for round wearable devices.
22176             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
22177                 final ScrollBarDrawable scrollBar = cache.scrollBar;
22178 
22179                 if (drawHorizontalScrollBar) {
22180                     scrollBar.setParameters(computeHorizontalScrollRange(),
22181                             computeHorizontalScrollOffset(),
22182                             computeHorizontalScrollExtent(), false);
22183                     final Rect bounds = cache.mScrollBarBounds;
22184                     getHorizontalScrollBarBounds(bounds, null);
22185                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
22186                             bounds.right, bounds.bottom);
22187                     if (invalidate) {
22188                         invalidate(bounds);
22189                     }
22190                 }
22191 
22192                 if (drawVerticalScrollBar) {
22193                     scrollBar.setParameters(computeVerticalScrollRange(),
22194                             computeVerticalScrollOffset(),
22195                             computeVerticalScrollExtent(), true);
22196                     final Rect bounds = cache.mScrollBarBounds;
22197                     getVerticalScrollBarBounds(bounds, null);
22198                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
22199                             bounds.right, bounds.bottom);
22200                     if (invalidate) {
22201                         invalidate(bounds);
22202                     }
22203                 }
22204             }
22205         }
22206     }
22207 
22208     /**
22209      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
22210      * FastScroller is visible.
22211      * @return whether to temporarily hide the vertical scrollbar
22212      * @hide
22213      */
isVerticalScrollBarHidden()22214     protected boolean isVerticalScrollBarHidden() {
22215         return false;
22216     }
22217 
22218     /**
22219      * <p>Draw the horizontal scrollbar if
22220      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
22221      *
22222      * @param canvas the canvas on which to draw the scrollbar
22223      * @param scrollBar the scrollbar's drawable
22224      *
22225      * @see #isHorizontalScrollBarEnabled()
22226      * @see #computeHorizontalScrollRange()
22227      * @see #computeHorizontalScrollExtent()
22228      * @see #computeHorizontalScrollOffset()
22229      * @hide
22230      */
22231     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDrawHorizontalScrollBar(@onNull Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)22232     protected void onDrawHorizontalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
22233             int l, int t, int r, int b) {
22234         scrollBar.setBounds(l, t, r, b);
22235         scrollBar.draw(canvas);
22236     }
22237 
22238     /**
22239      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
22240      * returns true.</p>
22241      *
22242      * @param canvas the canvas on which to draw the scrollbar
22243      * @param scrollBar the scrollbar's drawable
22244      *
22245      * @see #isVerticalScrollBarEnabled()
22246      * @see #computeVerticalScrollRange()
22247      * @see #computeVerticalScrollExtent()
22248      * @see #computeVerticalScrollOffset()
22249      * @hide
22250      */
22251     @UnsupportedAppUsage
onDrawVerticalScrollBar(@onNull Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)22252     protected void onDrawVerticalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
22253             int l, int t, int r, int b) {
22254         scrollBar.setBounds(l, t, r, b);
22255         scrollBar.draw(canvas);
22256     }
22257 
22258     /**
22259      * Implement this to do your drawing.
22260      *
22261      * @param canvas the canvas on which the background will be drawn
22262      */
onDraw(@onNull Canvas canvas)22263     protected void onDraw(@NonNull Canvas canvas) {
22264     }
22265 
22266     /*
22267      * Caller is responsible for calling requestLayout if necessary.
22268      * (This allows addViewInLayout to not request a new layout.)
22269      */
22270     @UnsupportedAppUsage
assignParent(ViewParent parent)22271     void assignParent(ViewParent parent) {
22272         if (mParent == null) {
22273             mParent = parent;
22274         } else if (parent == null) {
22275             mParent = null;
22276         } else {
22277             throw new RuntimeException("view " + this + " being added, but"
22278                     + " it already has a parent");
22279         }
22280     }
22281 
22282     /**
22283      * This is called when the view is attached to a window.  At this point it
22284      * has a Surface and will start drawing.  Note that this function is
22285      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
22286      * however it may be called any time before the first onDraw -- including
22287      * before or after {@link #onMeasure(int, int)}.
22288      *
22289      * @see #onDetachedFromWindow()
22290      */
22291     @CallSuper
onAttachedToWindow()22292     protected void onAttachedToWindow() {
22293         if (mParent != null && (mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
22294             mParent.requestTransparentRegion(this);
22295         }
22296 
22297         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
22298 
22299         jumpDrawablesToCurrentState();
22300 
22301         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
22302         resetSubtreeAccessibilityStateChanged();
22303 
22304         // rebuild, since Outline not maintained while View is detached
22305         rebuildOutline();
22306 
22307         if (isFocused()) {
22308             notifyFocusChangeToImeFocusController(true /* hasFocus */);
22309         }
22310 
22311         if (sTraceLayoutSteps) {
22312             setTraversalTracingEnabled(true);
22313         }
22314         if (sTraceRequestLayoutClass != null
22315                 && sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
22316             setRelayoutTracingEnabled(true);
22317         }
22318     }
22319 
22320     /**
22321      * Resolve all RTL related properties.
22322      *
22323      * @return true if resolution of RTL properties has been done
22324      *
22325      * @hide
22326      */
resolveRtlPropertiesIfNeeded()22327     public boolean resolveRtlPropertiesIfNeeded() {
22328         if (!needRtlPropertiesResolution()) return false;
22329 
22330         // Order is important here: LayoutDirection MUST be resolved first
22331         if (!isLayoutDirectionResolved()) {
22332             resolveLayoutDirection();
22333             resolveLayoutParams();
22334         }
22335         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
22336         if (!isTextDirectionResolved()) {
22337             resolveTextDirection();
22338         }
22339         if (!isTextAlignmentResolved()) {
22340             resolveTextAlignment();
22341         }
22342         // Should resolve Drawables before Padding because we need the layout direction of the
22343         // Drawable to correctly resolve Padding.
22344         if (!areDrawablesResolved()) {
22345             resolveDrawables();
22346         }
22347         if (!isPaddingResolved()) {
22348             resolvePadding();
22349         }
22350         onRtlPropertiesChanged(getLayoutDirection());
22351         return true;
22352     }
22353 
22354     /**
22355      * Reset resolution of all RTL related properties.
22356      *
22357      * @hide
22358      */
22359     @TestApi
resetRtlProperties()22360     public void resetRtlProperties() {
22361         resetResolvedLayoutDirection();
22362         resetResolvedTextDirection();
22363         resetResolvedTextAlignment();
22364         resetResolvedPadding();
22365         resetResolvedDrawables();
22366     }
22367 
22368     /**
22369      * @see #onScreenStateChanged(int)
22370      */
dispatchScreenStateChanged(int screenState)22371     void dispatchScreenStateChanged(int screenState) {
22372         onScreenStateChanged(screenState);
22373     }
22374 
22375     /**
22376      * This method is called whenever the state of the screen this view is
22377      * attached to changes. A state change will usually occurs when the screen
22378      * turns on or off (whether it happens automatically or the user does it
22379      * manually.)
22380      *
22381      * @param screenState The new state of the screen. Can be either
22382      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
22383      */
onScreenStateChanged(int screenState)22384     public void onScreenStateChanged(int screenState) {
22385     }
22386 
22387     /**
22388      * @see #onMovedToDisplay(int, Configuration)
22389      */
dispatchMovedToDisplay(Display display, Configuration config)22390     void dispatchMovedToDisplay(Display display, Configuration config) {
22391         mAttachInfo.mDisplay = display;
22392         mAttachInfo.mDisplayState = display.getState();
22393         onMovedToDisplay(display.getDisplayId(), config);
22394     }
22395 
22396     /**
22397      * Called by the system when the hosting activity is moved from one display to another without
22398      * recreation. This means that the activity is declared to handle all changes to configuration
22399      * that happened when it was switched to another display, so it wasn't destroyed and created
22400      * again.
22401      *
22402      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
22403      * applied configuration actually changed. It is up to app developer to choose whether to handle
22404      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
22405      * call.
22406      *
22407      * <p>Use this callback to track changes to the displays if some functionality relies on an
22408      * association with some display properties.
22409      *
22410      * @param displayId The id of the display to which the view was moved.
22411      * @param config Configuration of the resources on new display after move.
22412      *
22413      * @see #onConfigurationChanged(Configuration)
22414      * @hide
22415      */
onMovedToDisplay(int displayId, Configuration config)22416     public void onMovedToDisplay(int displayId, Configuration config) {
22417     }
22418 
22419     /**
22420      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
22421      */
22422     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hasRtlSupport()22423     private boolean hasRtlSupport() {
22424         return mContext.getApplicationInfo().hasRtlSupport();
22425     }
22426 
22427     /**
22428      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
22429      * RTL not supported)
22430      */
isRtlCompatibilityMode()22431     private boolean isRtlCompatibilityMode() {
22432         return !hasRtlSupport();
22433     }
22434 
22435     /**
22436      * @return true if RTL properties need resolution.
22437      *
22438      */
needRtlPropertiesResolution()22439     private boolean needRtlPropertiesResolution() {
22440         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
22441     }
22442 
22443     /**
22444      * Called when any RTL property (layout direction or text direction or text alignment) has
22445      * been changed.
22446      *
22447      * Subclasses need to override this method to take care of cached information that depends on the
22448      * resolved layout direction, or to inform child views that inherit their layout direction.
22449      *
22450      * The default implementation does nothing.
22451      *
22452      * @param layoutDirection the direction of the layout
22453      *
22454      * @see #LAYOUT_DIRECTION_LTR
22455      * @see #LAYOUT_DIRECTION_RTL
22456      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)22457     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
22458     }
22459 
22460     /**
22461      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
22462      * that the parent directionality can and will be resolved before its children.
22463      *
22464      * @return true if resolution has been done, false otherwise.
22465      *
22466      * @hide
22467      */
resolveLayoutDirection()22468     public boolean resolveLayoutDirection() {
22469         // Clear any previous layout direction resolution
22470         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
22471 
22472         if (hasRtlSupport()) {
22473             // Set resolved depending on layout direction
22474             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
22475                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
22476                 case LAYOUT_DIRECTION_INHERIT:
22477                     // We cannot resolve yet. LTR is by default and let the resolution happen again
22478                     // later to get the correct resolved value
22479                     if (!canResolveLayoutDirection()) return false;
22480 
22481                     // Parent has not yet resolved, LTR is still the default
22482                     try {
22483                         if (!mParent.isLayoutDirectionResolved()) return false;
22484 
22485                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
22486                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
22487                         }
22488                     } catch (AbstractMethodError e) {
22489                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22490                                 " does not fully implement ViewParent", e);
22491                     }
22492                     break;
22493                 case LAYOUT_DIRECTION_RTL:
22494                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
22495                     break;
22496                 case LAYOUT_DIRECTION_LOCALE:
22497                     if((LAYOUT_DIRECTION_RTL ==
22498                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
22499                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
22500                     }
22501                     break;
22502                 default:
22503                     // Nothing to do, LTR by default
22504             }
22505         }
22506 
22507         // Set to resolved
22508         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
22509         return true;
22510     }
22511 
22512     /**
22513      * Check if layout direction resolution can be done.
22514      *
22515      * @return true if layout direction resolution can be done otherwise return false.
22516      */
canResolveLayoutDirection()22517     public boolean canResolveLayoutDirection() {
22518         switch (getRawLayoutDirection()) {
22519             case LAYOUT_DIRECTION_INHERIT:
22520                 if (mParent != null) {
22521                     try {
22522                         return mParent.canResolveLayoutDirection();
22523                     } catch (AbstractMethodError e) {
22524                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22525                                 " does not fully implement ViewParent", e);
22526                     }
22527                 }
22528                 return false;
22529 
22530             default:
22531                 return true;
22532         }
22533     }
22534 
22535     /**
22536      * Reset the resolved layout direction. Layout direction will be resolved during a call to
22537      * {@link #onMeasure(int, int)}.
22538      *
22539      * @hide
22540      */
22541     @TestApi
resetResolvedLayoutDirection()22542     public void resetResolvedLayoutDirection() {
22543         // Reset the current resolved bits
22544         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
22545     }
22546 
22547     /**
22548      * @return true if the layout direction is inherited.
22549      *
22550      * @hide
22551      */
isLayoutDirectionInherited()22552     public boolean isLayoutDirectionInherited() {
22553         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
22554     }
22555 
22556     /**
22557      * @return true if layout direction has been resolved.
22558      */
isLayoutDirectionResolved()22559     public boolean isLayoutDirectionResolved() {
22560         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
22561     }
22562 
22563     /**
22564      * Return if padding has been resolved
22565      *
22566      * @hide
22567      */
22568     @UnsupportedAppUsage
isPaddingResolved()22569     boolean isPaddingResolved() {
22570         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
22571     }
22572 
22573     /**
22574      * Resolves padding depending on layout direction, if applicable, and
22575      * recomputes internal padding values to adjust for scroll bars.
22576      *
22577      * @hide
22578      */
22579     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resolvePadding()22580     public void resolvePadding() {
22581         final int resolvedLayoutDirection = getLayoutDirection();
22582 
22583         if (!isRtlCompatibilityMode()) {
22584             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
22585             // If start / end padding are defined, they will be resolved (hence overriding) to
22586             // left / right or right / left depending on the resolved layout direction.
22587             // If start / end padding are not defined, use the left / right ones.
22588             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
22589                 Rect padding = sThreadLocal.get();
22590                 if (padding == null) {
22591                     padding = new Rect();
22592                     sThreadLocal.set(padding);
22593                 }
22594                 mBackground.getPadding(padding);
22595                 if (!mLeftPaddingDefined) {
22596                     mUserPaddingLeftInitial = padding.left;
22597                 }
22598                 if (!mRightPaddingDefined) {
22599                     mUserPaddingRightInitial = padding.right;
22600                 }
22601             }
22602             switch (resolvedLayoutDirection) {
22603                 case LAYOUT_DIRECTION_RTL:
22604                     if (mUserPaddingStart != UNDEFINED_PADDING) {
22605                         mUserPaddingRight = mUserPaddingStart;
22606                     } else {
22607                         mUserPaddingRight = mUserPaddingRightInitial;
22608                     }
22609                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
22610                         mUserPaddingLeft = mUserPaddingEnd;
22611                     } else {
22612                         mUserPaddingLeft = mUserPaddingLeftInitial;
22613                     }
22614                     break;
22615                 case LAYOUT_DIRECTION_LTR:
22616                 default:
22617                     if (mUserPaddingStart != UNDEFINED_PADDING) {
22618                         mUserPaddingLeft = mUserPaddingStart;
22619                     } else {
22620                         mUserPaddingLeft = mUserPaddingLeftInitial;
22621                     }
22622                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
22623                         mUserPaddingRight = mUserPaddingEnd;
22624                     } else {
22625                         mUserPaddingRight = mUserPaddingRightInitial;
22626                     }
22627             }
22628 
22629             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
22630         }
22631 
22632         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
22633         onRtlPropertiesChanged(resolvedLayoutDirection);
22634 
22635         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
22636     }
22637 
22638     /**
22639      * Reset the resolved layout direction.
22640      *
22641      * @hide
22642      */
22643     @TestApi
resetResolvedPadding()22644     public void resetResolvedPadding() {
22645         resetResolvedPaddingInternal();
22646     }
22647 
22648     /**
22649      * Used when we only want to reset *this* view's padding and not trigger overrides
22650      * in ViewGroup that reset children too.
22651      */
resetResolvedPaddingInternal()22652     void resetResolvedPaddingInternal() {
22653         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
22654     }
22655 
22656     /**
22657      * This is called when the view is detached from a window.  At this point it
22658      * no longer has a surface for drawing.
22659      *
22660      * @see #onAttachedToWindow()
22661      */
22662     @CallSuper
onDetachedFromWindow()22663     protected void onDetachedFromWindow() {
22664     }
22665 
22666     /**
22667      * This is a framework-internal mirror of onDetachedFromWindow() that's called
22668      * after onDetachedFromWindow().
22669      *
22670      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
22671      * The super method should be called at the end of the overridden method to ensure
22672      * subclasses are destroyed first
22673      *
22674      * @hide
22675      */
22676     @CallSuper
22677     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDetachedFromWindowInternal()22678     protected void onDetachedFromWindowInternal() {
22679         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
22680         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
22681         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
22682 
22683         removeUnsetPressCallback();
22684         removeLongPressCallback();
22685         removePerformClickCallback();
22686         clearAccessibilityThrottles();
22687         stopNestedScroll();
22688 
22689         // Anything that started animating right before detach should already
22690         // be in its final state when re-attached.
22691         jumpDrawablesToCurrentState();
22692 
22693         destroyDrawingCache();
22694 
22695         cleanupDraw();
22696         mCurrentAnimation = null;
22697 
22698         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
22699             removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
22700             removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
22701             hideTooltip();
22702         }
22703 
22704         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
22705 
22706         if (mBackgroundRenderNode != null) {
22707             mBackgroundRenderNode.forceEndAnimators();
22708         }
22709         mRenderNode.forceEndAnimators();
22710     }
22711 
cleanupDraw()22712     private void cleanupDraw() {
22713         resetDisplayList();
22714         if (mAttachInfo != null) {
22715             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
22716         }
22717     }
22718 
invalidateInheritedLayoutMode(int layoutModeOfRoot)22719     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
22720     }
22721 
22722     /**
22723      * @return The number of times this view has been attached to a window
22724      */
getWindowAttachCount()22725     protected int getWindowAttachCount() {
22726         return mWindowAttachCount;
22727     }
22728 
22729     /**
22730      * Retrieve a unique token identifying the window this view is attached to.
22731      * @return Return the window's token for use in
22732      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
22733      * This token maybe null if this view is not attached to a window.
22734      * @see #isAttachedToWindow() for current window attach state
22735      * @see OnAttachStateChangeListener to listen to window attach/detach state changes
22736      */
getWindowToken()22737     public IBinder getWindowToken() {
22738         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
22739     }
22740 
22741     /**
22742      * Retrieve the {@link WindowId} for the window this view is
22743      * currently attached to.
22744      */
getWindowId()22745     public WindowId getWindowId() {
22746         AttachInfo ai = mAttachInfo;
22747         if (ai == null) {
22748             return null;
22749         }
22750         if (ai.mWindowId == null) {
22751             try {
22752                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
22753                 if (ai.mIWindowId != null) {
22754                     ai.mWindowId = new WindowId(ai.mIWindowId);
22755                 }
22756             } catch (RemoteException e) {
22757             }
22758         }
22759         return ai.mWindowId;
22760     }
22761 
22762     /**
22763      * Retrieve a unique token identifying the top-level "real" window of
22764      * the window that this view is attached to.  That is, this is like
22765      * {@link #getWindowToken}, except if the window this view in is a panel
22766      * window (attached to another containing window), then the token of
22767      * the containing window is returned instead.
22768      *
22769      * @return Returns the associated window token, either
22770      * {@link #getWindowToken()} or the containing window's token.
22771      */
getApplicationWindowToken()22772     public IBinder getApplicationWindowToken() {
22773         AttachInfo ai = mAttachInfo;
22774         if (ai != null) {
22775             IBinder appWindowToken = ai.mPanelParentWindowToken;
22776             if (appWindowToken == null) {
22777                 appWindowToken = ai.mWindowToken;
22778             }
22779             return appWindowToken;
22780         }
22781         return null;
22782     }
22783 
22784     /**
22785      * Gets the logical display to which the view's window has been attached.
22786      *
22787      * @return The logical display, or null if the view is not currently attached to a window.
22788      */
getDisplay()22789     public Display getDisplay() {
22790         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
22791     }
22792 
22793     /**
22794      * Retrieve private session object this view hierarchy is using to
22795      * communicate with the window manager.
22796      * @return the session object to communicate with the window manager
22797      */
22798     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()22799     /*package*/ IWindowSession getWindowSession() {
22800         return mAttachInfo != null ? mAttachInfo.mSession : null;
22801     }
22802 
22803     /**
22804      * Return the window this view is currently attached to.
22805      * @hide
22806      */
getWindow()22807     protected IWindow getWindow() {
22808         return mAttachInfo != null ? mAttachInfo.mWindow : null;
22809     }
22810 
22811     /**
22812      * Return the visibility value of the least visible component passed.
22813      */
combineVisibility(int vis1, int vis2)22814     int combineVisibility(int vis1, int vis2) {
22815         // This works because VISIBLE < INVISIBLE < GONE.
22816         return Math.max(vis1, vis2);
22817     }
22818 
22819     private boolean mShouldFakeFocus = false;
22820 
22821     /**
22822      * Fake send a focus event after attaching to window.
22823      * See {@link android.view.ViewRootImpl#dispatchCompatFakeFocus()} for details.
22824      * @hide
22825      */
fakeFocusAfterAttachingToWindow()22826     public void fakeFocusAfterAttachingToWindow() {
22827         mShouldFakeFocus = true;
22828     }
22829 
22830     /**
22831      * @param info the {@link android.view.View.AttachInfo} to associated with
22832      *        this view
22833      */
22834     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)22835     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
22836         mAttachInfo = info;
22837         if (mOverlay != null) {
22838             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
22839         }
22840         mWindowAttachCount++;
22841         // We will need to evaluate the drawable state at least once.
22842         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
22843         if (mFloatingTreeObserver != null) {
22844             info.mTreeObserver.merge(mFloatingTreeObserver);
22845             mFloatingTreeObserver = null;
22846         }
22847 
22848         registerPendingFrameMetricsObservers();
22849 
22850         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
22851             mAttachInfo.mScrollContainers.add(this);
22852             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
22853         }
22854         // Transfer all pending runnables.
22855         if (mRunQueue != null) {
22856             mRunQueue.executeActions(info.mHandler);
22857             mRunQueue = null;
22858         }
22859         performCollectViewAttributes(mAttachInfo, visibility);
22860         onAttachedToWindow();
22861 
22862         ListenerInfo li = mListenerInfo;
22863         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
22864                 li != null ? li.mOnAttachStateChangeListeners : null;
22865         if (listeners != null && listeners.size() > 0) {
22866             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
22867             // perform the dispatching. The iterator is a safe guard against listeners that
22868             // could mutate the list by calling the various add/remove methods. This prevents
22869             // the array from being modified while we iterate it.
22870             for (OnAttachStateChangeListener listener : listeners) {
22871                 listener.onViewAttachedToWindow(this);
22872             }
22873         }
22874 
22875         int vis = info.mWindowVisibility;
22876         if (vis != GONE) {
22877             onWindowVisibilityChanged(vis);
22878             if (isShown()) {
22879                 // Calling onVisibilityAggregated directly here since the subtree will also
22880                 // receive dispatchAttachedToWindow and this same call
22881                 onVisibilityAggregated(vis == VISIBLE);
22882             }
22883         }
22884 
22885         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
22886         // As all views in the subtree will already receive dispatchAttachedToWindow
22887         // traversing the subtree again here is not desired.
22888         onVisibilityChanged(this, visibility);
22889 
22890         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
22891             // If nobody has evaluated the drawable state yet, then do it now.
22892             refreshDrawableState();
22893         }
22894         needGlobalAttributesUpdate(false);
22895 
22896         notifyEnterOrExitForAutoFillIfNeeded(true);
22897         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
22898 
22899         if (mShouldFakeFocus) {
22900             getViewRootImpl().dispatchCompatFakeFocus();
22901             mShouldFakeFocus = false;
22902         }
22903     }
22904 
22905     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()22906     void dispatchDetachedFromWindow() {
22907         AttachInfo info = mAttachInfo;
22908         if (info != null) {
22909             int vis = info.mWindowVisibility;
22910             if (vis != GONE) {
22911                 onWindowVisibilityChanged(GONE);
22912                 if (isShown()) {
22913                     // Invoking onVisibilityAggregated directly here since the subtree
22914                     // will also receive detached from window
22915                     onVisibilityAggregated(false);
22916                 } else {
22917                     notifyAutofillManagerViewVisibilityChanged(false);
22918                 }
22919             }
22920         }
22921 
22922         onDetachedFromWindow();
22923         onDetachedFromWindowInternal();
22924 
22925         if (info != null) {
22926             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
22927         }
22928 
22929         ListenerInfo li = mListenerInfo;
22930         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
22931                 li != null ? li.mOnAttachStateChangeListeners : null;
22932         if (listeners != null && listeners.size() > 0) {
22933             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
22934             // perform the dispatching. The iterator is a safe guard against listeners that
22935             // could mutate the list by calling the various add/remove methods. This prevents
22936             // the array from being modified while we iterate it.
22937             for (OnAttachStateChangeListener listener : listeners) {
22938                 listener.onViewDetachedFromWindow(this);
22939             }
22940         }
22941 
22942         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
22943             mAttachInfo.mScrollContainers.remove(this);
22944             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
22945         }
22946 
22947         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
22948         updateSensitiveViewsCountIfNeeded(false);
22949 
22950         mAttachInfo = null;
22951         if (mOverlay != null) {
22952             mOverlay.getOverlayView().dispatchDetachedFromWindow();
22953         }
22954 
22955         notifyEnterOrExitForAutoFillIfNeeded(false);
22956 
22957         if (info != null && !collectPreferKeepClearRects().isEmpty()) {
22958             info.mViewRootImpl.updateKeepClearRectsForView(this);
22959         }
22960     }
22961 
22962     /**
22963      * Cancel any deferred high-level input events that were previously posted to the event queue.
22964      *
22965      * <p>Many views post high-level events such as click handlers to the event queue
22966      * to run deferred in order to preserve a desired user experience - clearing visible
22967      * pressed states before executing, etc. This method will abort any events of this nature
22968      * that are currently in flight.</p>
22969      *
22970      * <p>Custom views that generate their own high-level deferred input events should override
22971      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
22972      *
22973      * <p>This will also cancel pending input events for any child views.</p>
22974      *
22975      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
22976      * This will not impact newer events posted after this call that may occur as a result of
22977      * lower-level input events still waiting in the queue. If you are trying to prevent
22978      * double-submitted  events for the duration of some sort of asynchronous transaction
22979      * you should also take other steps to protect against unexpected double inputs e.g. calling
22980      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
22981      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
22982      */
cancelPendingInputEvents()22983     public final void cancelPendingInputEvents() {
22984         dispatchCancelPendingInputEvents();
22985     }
22986 
22987     /**
22988      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
22989      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
22990      */
dispatchCancelPendingInputEvents()22991     void dispatchCancelPendingInputEvents() {
22992         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
22993         onCancelPendingInputEvents();
22994         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
22995             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
22996                     " did not call through to super.onCancelPendingInputEvents()");
22997         }
22998     }
22999 
23000     /**
23001      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
23002      * a parent view.
23003      *
23004      * <p>This method is responsible for removing any pending high-level input events that were
23005      * posted to the event queue to run later. Custom view classes that post their own deferred
23006      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
23007      * {@link android.os.Handler} should override this method, call
23008      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
23009      * </p>
23010      */
onCancelPendingInputEvents()23011     public void onCancelPendingInputEvents() {
23012         removePerformClickCallback();
23013         cancelLongPress();
23014         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
23015     }
23016 
23017     /**
23018      * Store this view hierarchy's frozen state into the given container.
23019      *
23020      * @param container The SparseArray in which to save the view's state.
23021      *
23022      * @see #restoreHierarchyState(android.util.SparseArray)
23023      * @see #dispatchSaveInstanceState(android.util.SparseArray)
23024      * @see #onSaveInstanceState()
23025      */
saveHierarchyState(SparseArray<Parcelable> container)23026     public void saveHierarchyState(SparseArray<Parcelable> container) {
23027         dispatchSaveInstanceState(container);
23028     }
23029 
23030     /**
23031      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
23032      * this view and its children. May be overridden to modify how freezing happens to a
23033      * view's children; for example, some views may want to not store state for their children.
23034      *
23035      * @param container The SparseArray in which to save the view's state.
23036      *
23037      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
23038      * @see #saveHierarchyState(android.util.SparseArray)
23039      * @see #onSaveInstanceState()
23040      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)23041     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
23042         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
23043             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
23044             Parcelable state = onSaveInstanceState();
23045             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
23046                 throw new IllegalStateException(
23047                         "Derived class did not call super.onSaveInstanceState()");
23048             }
23049             if (state != null) {
23050                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
23051                 // + ": " + state);
23052                 container.put(mID, state);
23053             }
23054         }
23055     }
23056 
23057     /**
23058      * Hook allowing a view to generate a representation of its internal state
23059      * that can later be used to create a new instance with that same state.
23060      * This state should only contain information that is not persistent or can
23061      * not be reconstructed later. For example, you will never store your
23062      * current position on screen because that will be computed again when a
23063      * new instance of the view is placed in its view hierarchy.
23064      * <p>
23065      * Some examples of things you may store here: the current cursor position
23066      * in a text view (but usually not the text itself since that is stored in a
23067      * content provider or other persistent storage), the currently selected
23068      * item in a list view.
23069      *
23070      * @return Returns a Parcelable object containing the view's current dynamic
23071      *         state, or null if there is nothing interesting to save.
23072      * @see #onRestoreInstanceState(Parcelable)
23073      * @see #saveHierarchyState(SparseArray)
23074      * @see #dispatchSaveInstanceState(SparseArray)
23075      * @see #setSaveEnabled(boolean)
23076      */
23077     @CallSuper
onSaveInstanceState()23078     @Nullable protected Parcelable onSaveInstanceState() {
23079         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
23080         if (mStartActivityRequestWho != null || isAutofilled()
23081                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
23082             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
23083 
23084             if (mStartActivityRequestWho != null) {
23085                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
23086             }
23087 
23088             if (isAutofilled()) {
23089                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
23090             }
23091 
23092             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
23093                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
23094             }
23095 
23096             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
23097             state.mIsAutofilled = isAutofilled();
23098             state.mHideHighlight = hideAutofillHighlight();
23099             state.mAutofillViewId = mAutofillViewId;
23100             return state;
23101         }
23102         return BaseSavedState.EMPTY_STATE;
23103     }
23104 
23105     /**
23106      * Restore this view hierarchy's frozen state from the given container.
23107      *
23108      * @param container The SparseArray which holds previously frozen states.
23109      *
23110      * @see #saveHierarchyState(android.util.SparseArray)
23111      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
23112      * @see #onRestoreInstanceState(android.os.Parcelable)
23113      */
restoreHierarchyState(SparseArray<Parcelable> container)23114     public void restoreHierarchyState(SparseArray<Parcelable> container) {
23115         dispatchRestoreInstanceState(container);
23116     }
23117 
23118     /**
23119      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
23120      * state for this view and its children. May be overridden to modify how restoring
23121      * happens to a view's children; for example, some views may want to not store state
23122      * for their children.
23123      *
23124      * @param container The SparseArray which holds previously saved state.
23125      *
23126      * @see #dispatchSaveInstanceState(android.util.SparseArray)
23127      * @see #restoreHierarchyState(android.util.SparseArray)
23128      * @see #onRestoreInstanceState(android.os.Parcelable)
23129      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)23130     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
23131         if (mID != NO_ID) {
23132             Parcelable state = container.get(mID);
23133             if (state != null) {
23134                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
23135                 // + ": " + state);
23136                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
23137                 onRestoreInstanceState(state);
23138                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
23139                     throw new IllegalStateException(
23140                             "Derived class did not call super.onRestoreInstanceState()");
23141                 }
23142             }
23143         }
23144     }
23145 
23146     /**
23147      * Hook allowing a view to re-apply a representation of its internal state that had previously
23148      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
23149      * null state.
23150      *
23151      * @param state The frozen state that had previously been returned by
23152      *        {@link #onSaveInstanceState}.
23153      *
23154      * @see #onSaveInstanceState()
23155      * @see #restoreHierarchyState(android.util.SparseArray)
23156      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
23157      */
23158     @CallSuper
onRestoreInstanceState(Parcelable state)23159     protected void onRestoreInstanceState(Parcelable state) {
23160         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
23161         if (state != null && !(state instanceof AbsSavedState)) {
23162             throw new IllegalArgumentException("Wrong state class, expecting View State but "
23163                     + "received " + state.getClass().toString() + " instead. This usually happens "
23164                     + "when two views of different type have the same id in the same hierarchy. "
23165                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
23166                     + "other views do not use the same id.");
23167         }
23168         if (state != null && state instanceof BaseSavedState) {
23169             BaseSavedState baseState = (BaseSavedState) state;
23170 
23171             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
23172                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
23173             }
23174             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
23175                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
23176             }
23177             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
23178                 // It can happen that views have the same view id and the restoration path will not
23179                 // be able to distinguish between them. The autofill id needs to be unique though.
23180                 // Hence prevent the same autofill view id from being restored multiple times.
23181                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
23182 
23183                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
23184                     // Ignore when view already set it through setAutofillId();
23185                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
23186                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
23187                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
23188                                 + " it to " + mAutofillId);
23189                     }
23190                 } else {
23191                     mAutofillViewId = baseState.mAutofillViewId;
23192                     mAutofillId = null; // will be set on demand by getAutofillId()
23193                 }
23194             }
23195         }
23196     }
23197 
23198     /**
23199      * <p>Return the time at which the drawing of the view hierarchy started.</p>
23200      *
23201      * @return the drawing start time in milliseconds
23202      */
getDrawingTime()23203     public long getDrawingTime() {
23204         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
23205     }
23206 
23207     /**
23208      * <p>Enables or disables the duplication of the parent's state into this view. When
23209      * duplication is enabled, this view gets its drawable state from its parent rather
23210      * than from its own internal properties.</p>
23211      *
23212      * <p>Note: in the current implementation, setting this property to true after the
23213      * view was added to a ViewGroup might have no effect at all. This property should
23214      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
23215      *
23216      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
23217      * property is enabled, an exception will be thrown.</p>
23218      *
23219      * <p>Note: if the child view uses and updates additional states which are unknown to the
23220      * parent, these states should not be affected by this method.</p>
23221      *
23222      * @param enabled True to enable duplication of the parent's drawable state, false
23223      *                to disable it.
23224      *
23225      * @see #getDrawableState()
23226      * @see #isDuplicateParentStateEnabled()
23227      */
setDuplicateParentStateEnabled(boolean enabled)23228     public void setDuplicateParentStateEnabled(boolean enabled) {
23229         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
23230     }
23231 
23232     /**
23233      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
23234      *
23235      * @return True if this view's drawable state is duplicated from the parent,
23236      *         false otherwise
23237      *
23238      * @see #getDrawableState()
23239      * @see #setDuplicateParentStateEnabled(boolean)
23240      */
23241     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()23242     public boolean isDuplicateParentStateEnabled() {
23243         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
23244     }
23245 
23246     /**
23247      * <p>Specifies the type of layer backing this view. The layer can be
23248      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
23249      * {@link #LAYER_TYPE_HARDWARE}.</p>
23250      *
23251      * <p>A layer is associated with an optional {@link android.graphics.Paint}
23252      * instance that controls how the layer is composed on screen. The following
23253      * properties of the paint are taken into account when composing the layer:</p>
23254      * <ul>
23255      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
23256      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
23257      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
23258      * </ul>
23259      *
23260      * <p>If this view has an alpha value set to < 1.0 by calling
23261      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
23262      * by this view's alpha value.</p>
23263      *
23264      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
23265      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
23266      * for more information on when and how to use layers.</p>
23267      *
23268      * @param layerType The type of layer to use with this view, must be one of
23269      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
23270      *        {@link #LAYER_TYPE_HARDWARE}
23271      * @param paint The paint used to compose the layer. This argument is optional
23272      *        and can be null. It is ignored when the layer type is
23273      *        {@link #LAYER_TYPE_NONE}
23274      *
23275      * @see #getLayerType()
23276      * @see #LAYER_TYPE_NONE
23277      * @see #LAYER_TYPE_SOFTWARE
23278      * @see #LAYER_TYPE_HARDWARE
23279      * @see #setAlpha(float)
23280      *
23281      * @attr ref android.R.styleable#View_layerType
23282      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)23283     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
23284         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
23285             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
23286                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
23287         }
23288 
23289         boolean typeChanged = mRenderNode.setLayerType(layerType);
23290 
23291         if (!typeChanged) {
23292             setLayerPaint(paint);
23293             return;
23294         }
23295 
23296         if (layerType != LAYER_TYPE_SOFTWARE) {
23297             // Destroy any previous software drawing cache if present
23298             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
23299             // drawing cache created in View#draw when drawing to a SW canvas.
23300             destroyDrawingCache();
23301         }
23302 
23303         mLayerType = layerType;
23304         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
23305         mRenderNode.setLayerPaint(mLayerPaint);
23306 
23307         // draw() behaves differently if we are on a layer, so we need to
23308         // invalidate() here
23309         invalidateParentCaches();
23310         invalidate(true);
23311     }
23312 
23313     /**
23314      * Configure the {@link android.graphics.RenderEffect} to apply to this View.
23315      * This will apply a visual effect to the results of the View before it is drawn. For example if
23316      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
23317      * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
23318      * when this View is drawn.
23319      * @param renderEffect to be applied to the View. Passing null clears the previously configured
23320      *                     {@link RenderEffect}
23321      */
setRenderEffect(@ullable RenderEffect renderEffect)23322     public void setRenderEffect(@Nullable RenderEffect renderEffect) {
23323         if (mRenderNode.setRenderEffect(renderEffect)) {
23324             invalidateViewProperty(true, true);
23325         }
23326     }
23327 
23328     /**
23329      * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of this
23330      * View. This will apply a visual effect to the result of the backdrop contents of this View
23331      * before it is drawn. For example if
23332      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
23333      * is provided, the previous content behind this View will be blurred before this View is drawn.
23334      * @param renderEffect to be applied to the View. Passing null clears the previously configured
23335      *                     {@link RenderEffect}
23336      * @hide
23337      */
setBackdropRenderEffect(@ullable RenderEffect renderEffect)23338     public void setBackdropRenderEffect(@Nullable RenderEffect renderEffect) {
23339         if (mRenderNode.setBackdropRenderEffect(renderEffect)) {
23340             invalidateViewProperty(true, true);
23341         }
23342     }
23343 
23344     /**
23345      * Updates the {@link Paint} object used with the current layer (used only if the current
23346      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
23347      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
23348      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
23349      * ensure that the view gets redrawn immediately.
23350      *
23351      * <p>A layer is associated with an optional {@link android.graphics.Paint}
23352      * instance that controls how the layer is composed on screen. The following
23353      * properties of the paint are taken into account when composing the layer:</p>
23354      * <ul>
23355      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
23356      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
23357      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
23358      * </ul>
23359      *
23360      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
23361      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
23362      *
23363      * @param paint The paint used to compose the layer. This argument is optional
23364      *        and can be null. It is ignored when the layer type is
23365      *        {@link #LAYER_TYPE_NONE}
23366      *
23367      * @see #setLayerType(int, android.graphics.Paint)
23368      */
setLayerPaint(@ullable Paint paint)23369     public void setLayerPaint(@Nullable Paint paint) {
23370         int layerType = getLayerType();
23371         if (layerType != LAYER_TYPE_NONE) {
23372             mLayerPaint = paint;
23373             if (layerType == LAYER_TYPE_HARDWARE) {
23374                 if (mRenderNode.setLayerPaint(paint)) {
23375                     invalidateViewProperty(false, false);
23376                 }
23377             } else {
23378                 invalidate();
23379             }
23380         }
23381     }
23382 
23383     /**
23384      * Indicates what type of layer is currently associated with this view. By default
23385      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
23386      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
23387      * for more information on the different types of layers.
23388      *
23389      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
23390      *         {@link #LAYER_TYPE_HARDWARE}
23391      *
23392      * @see #setLayerType(int, android.graphics.Paint)
23393      * @see #buildLayer()
23394      * @see #LAYER_TYPE_NONE
23395      * @see #LAYER_TYPE_SOFTWARE
23396      * @see #LAYER_TYPE_HARDWARE
23397      */
23398     @InspectableProperty(enumMapping = {
23399             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
23400             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
23401             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
23402     })
23403     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
23404             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
23405             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
23406             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
23407     })
23408     @LayerType
getLayerType()23409     public int getLayerType() {
23410         return mLayerType;
23411     }
23412 
23413     /**
23414      * Forces this view's layer to be created and this view to be rendered
23415      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
23416      * invoking this method will have no effect.
23417      *
23418      * This method can for instance be used to render a view into its layer before
23419      * starting an animation. If this view is complex, rendering into the layer
23420      * before starting the animation will avoid skipping frames.
23421      *
23422      * @throws IllegalStateException If this view is not attached to a window
23423      *
23424      * @see #setLayerType(int, android.graphics.Paint)
23425      */
buildLayer()23426     public void buildLayer() {
23427         if (mLayerType == LAYER_TYPE_NONE) return;
23428 
23429         final AttachInfo attachInfo = mAttachInfo;
23430         if (attachInfo == null) {
23431             throw new IllegalStateException("This view must be attached to a window first");
23432         }
23433 
23434         if (getWidth() == 0 || getHeight() == 0) {
23435             return;
23436         }
23437 
23438         switch (mLayerType) {
23439             case LAYER_TYPE_HARDWARE:
23440                 updateDisplayListIfDirty();
23441                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
23442                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
23443                 }
23444                 break;
23445             case LAYER_TYPE_SOFTWARE:
23446                 buildDrawingCache(true);
23447                 break;
23448         }
23449     }
23450 
23451     /**
23452      * Determines whether an unprocessed input event is available on the window.
23453      *
23454      * This is only a performance hint (a.k.a. the Input Hint) and may return false negative
23455      * results.  Callers should not rely on availability of the input event based on the return
23456      * value of this method.
23457      *
23458      * The Input Hint functionality is experimental, and can be removed in the future OS releases.
23459      *
23460      * This method only returns nontrivial results on a View that is attached to a Window. Such View
23461      * can be acquired using `Activity.getWindow().getDecorView()`, and only after the view
23462      * hierarchy is attached (via {@link android.app.Activity#setContentView(android.view.View)}).
23463      *
23464      * In multi-window mode the View can provide the Input Hint only for the window it is attached
23465      * to. Therefore, checking input availability for the whole application would require asking
23466      * for the hint from more than one View.
23467      *
23468      * The initial implementation does not return false positives, but callers should not rely on
23469      * it: false positives may occur in future OS releases.
23470      *
23471      * @hide
23472      */
probablyHasInput()23473     public boolean probablyHasInput() {
23474         ViewRootImpl viewRootImpl = getViewRootImpl();
23475         if (viewRootImpl == null) {
23476             return false;
23477         }
23478         return viewRootImpl.probablyHasInput();
23479     }
23480 
23481     /**
23482      * Destroys all hardware rendering resources. This method is invoked
23483      * when the system needs to reclaim resources. Upon execution of this
23484      * method, you should free any OpenGL resources created by the view.
23485      *
23486      * Note: you <strong>must</strong> call
23487      * <code>super.destroyHardwareResources()</code> when overriding
23488      * this method.
23489      *
23490      * @hide
23491      */
23492     @CallSuper
23493     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
destroyHardwareResources()23494     protected void destroyHardwareResources() {
23495         if (mOverlay != null) {
23496             mOverlay.getOverlayView().destroyHardwareResources();
23497         }
23498         if (mGhostView != null) {
23499             mGhostView.destroyHardwareResources();
23500         }
23501     }
23502 
23503     /**
23504      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
23505      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
23506      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
23507      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
23508      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
23509      * null.</p>
23510      *
23511      * <p>Enabling the drawing cache is similar to
23512      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
23513      * acceleration is turned off. When hardware acceleration is turned on, enabling the
23514      * drawing cache has no effect on rendering because the system uses a different mechanism
23515      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
23516      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
23517      * for information on how to enable software and hardware layers.</p>
23518      *
23519      * <p>This API can be used to manually generate
23520      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
23521      * {@link #getDrawingCache()}.</p>
23522      *
23523      * @param enabled true to enable the drawing cache, false otherwise
23524      *
23525      * @see #isDrawingCacheEnabled()
23526      * @see #getDrawingCache()
23527      * @see #buildDrawingCache()
23528      * @see #setLayerType(int, android.graphics.Paint)
23529      *
23530      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23531      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23532      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23533      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23534      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23535      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23536      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23537      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23538      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23539      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23540      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23541      * reports or unit testing the {@link PixelCopy} API is recommended.
23542      */
23543     @Deprecated
setDrawingCacheEnabled(boolean enabled)23544     public void setDrawingCacheEnabled(boolean enabled) {
23545         mCachingFailed = false;
23546         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
23547     }
23548 
23549     /**
23550      * <p>Indicates whether the drawing cache is enabled for this view.</p>
23551      *
23552      * @return true if the drawing cache is enabled
23553      *
23554      * @see #setDrawingCacheEnabled(boolean)
23555      * @see #getDrawingCache()
23556      *
23557      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23558      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23559      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23560      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23561      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23562      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23563      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23564      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23565      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23566      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23567      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23568      * reports or unit testing the {@link PixelCopy} API is recommended.
23569      */
23570     @Deprecated
23571     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()23572     public boolean isDrawingCacheEnabled() {
23573         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
23574     }
23575 
23576     /**
23577      * Debugging utility which recursively outputs the dirty state of a view and its
23578      * descendants.
23579      *
23580      * @hide
23581      */
23582     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)23583     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
23584         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
23585                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
23586                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
23587                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
23588                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
23589         if (clear) {
23590             mPrivateFlags &= clearMask;
23591         }
23592         if (this instanceof ViewGroup) {
23593             ViewGroup parent = (ViewGroup) this;
23594             final int count = parent.getChildCount();
23595             for (int i = 0; i < count; i++) {
23596                 final View child = parent.getChildAt(i);
23597                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
23598             }
23599         }
23600     }
23601 
23602     /**
23603      * This method is used by ViewGroup to cause its children to restore or recreate their
23604      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
23605      * to recreate its own display list, which would happen if it went through the normal
23606      * draw/dispatchDraw mechanisms.
23607      *
23608      * @hide
23609      */
dispatchGetDisplayList()23610     protected void dispatchGetDisplayList() {}
23611 
23612     /**
23613      * A view that is not attached or hardware accelerated cannot create a display list.
23614      * This method checks these conditions and returns the appropriate result.
23615      *
23616      * @return true if view has the ability to create a display list, false otherwise.
23617      *
23618      * @hide
23619      */
canHaveDisplayList()23620     public boolean canHaveDisplayList() {
23621         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
23622     }
23623 
23624     /**
23625      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
23626      * @hide
23627      */
23628     @NonNull
23629     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateDisplayListIfDirty()23630     public RenderNode updateDisplayListIfDirty() {
23631         final RenderNode renderNode = mRenderNode;
23632         if (!canHaveDisplayList()) {
23633             // can't populate RenderNode, don't try
23634             return renderNode;
23635         }
23636 
23637         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
23638                 || !renderNode.hasDisplayList()
23639                 || (mRecreateDisplayList)) {
23640             // Don't need to recreate the display list, just need to tell our
23641             // children to restore/recreate theirs
23642             if (renderNode.hasDisplayList()
23643                     && !mRecreateDisplayList) {
23644                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
23645                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23646                 dispatchGetDisplayList();
23647 
23648                 return renderNode; // no work needed
23649             }
23650 
23651             // If we got here, we're recreating it. Mark it as such to ensure that
23652             // we copy in child display lists into ours in drawChild()
23653             mRecreateDisplayList = true;
23654 
23655             int width = mRight - mLeft;
23656             int height = mBottom - mTop;
23657             int layerType = getLayerType();
23658 
23659             // Hacky hack: Reset any stretch effects as those are applied during the draw pass
23660             // instead of being "stateful" like other RenderNode properties
23661             renderNode.clearStretch();
23662 
23663             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
23664 
23665             try {
23666                 if (layerType == LAYER_TYPE_SOFTWARE) {
23667                     buildDrawingCache(true);
23668                     Bitmap cache = getDrawingCache(true);
23669                     if (cache != null) {
23670                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
23671                     }
23672                 } else {
23673                     computeScroll();
23674 
23675                     canvas.translate(-mScrollX, -mScrollY);
23676                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
23677                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23678 
23679                     mPrivateFlags4 |= PFLAG4_HAS_DRAWN;
23680 
23681                     // Fast path for layouts with no backgrounds
23682                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
23683                         dispatchDraw(canvas);
23684                         drawAutofilledHighlight(canvas);
23685                         if (mOverlay != null && !mOverlay.isEmpty()) {
23686                             mOverlay.getOverlayView().draw(canvas);
23687                         }
23688                         if (isShowingLayoutBounds()) {
23689                             debugDrawFocus(canvas);
23690                         }
23691                     } else {
23692                         draw(canvas);
23693                     }
23694                 }
23695 
23696                 // For VRR to vote the preferred frame rate
23697                 if (sToolkitSetFrameRateReadOnlyFlagValue
23698                         && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
23699                     votePreferredFrameRate();
23700                 }
23701             } finally {
23702                 renderNode.endRecording();
23703                 setDisplayListProperties(renderNode);
23704             }
23705         } else {
23706             if ((mPrivateFlags4 & PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION)
23707                     == PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION) {
23708                 // For VRR to vote the preferred frame rate
23709                 if (sToolkitSetFrameRateReadOnlyFlagValue
23710                         && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
23711                     votePreferredFrameRate();
23712                 }
23713                 mPrivateFlags4 &= ~PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
23714             }
23715             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
23716             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23717         }
23718         mPrivateFlags4 &= ~PFLAG4_HAS_MOVED;
23719         mFrameContentVelocity = -1;
23720         return renderNode;
23721     }
23722 
23723     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resetDisplayList()23724     private void resetDisplayList() {
23725         mRenderNode.discardDisplayList();
23726         if (mBackgroundRenderNode != null) {
23727             mBackgroundRenderNode.discardDisplayList();
23728         }
23729     }
23730 
23731     /**
23732      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
23733      *
23734      * @return A non-scaled bitmap representing this view or null if cache is disabled.
23735      *
23736      * @see #getDrawingCache(boolean)
23737      *
23738      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23739      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23740      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23741      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23742      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23743      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23744      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23745      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23746      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23747      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23748      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23749      * reports or unit testing the {@link PixelCopy} API is recommended.
23750      */
23751     @Deprecated
getDrawingCache()23752     public Bitmap getDrawingCache() {
23753         return getDrawingCache(false);
23754     }
23755 
23756     /**
23757      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
23758      * is null when caching is disabled. If caching is enabled and the cache is not ready,
23759      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
23760      * draw from the cache when the cache is enabled. To benefit from the cache, you must
23761      * request the drawing cache by calling this method and draw it on screen if the
23762      * returned bitmap is not null.</p>
23763      *
23764      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
23765      * this method will create a bitmap of the same size as this view. Because this bitmap
23766      * will be drawn scaled by the parent ViewGroup, the result on screen might show
23767      * scaling artifacts. To avoid such artifacts, you should call this method by setting
23768      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
23769      * size than the view. This implies that your application must be able to handle this
23770      * size.</p>
23771      *
23772      * @param autoScale Indicates whether the generated bitmap should be scaled based on
23773      *        the current density of the screen when the application is in compatibility
23774      *        mode.
23775      *
23776      * @return A bitmap representing this view or null if cache is disabled.
23777      *
23778      * @see #setDrawingCacheEnabled(boolean)
23779      * @see #isDrawingCacheEnabled()
23780      * @see #buildDrawingCache(boolean)
23781      * @see #destroyDrawingCache()
23782      *
23783      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23784      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23785      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23786      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23787      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23788      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23789      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23790      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23791      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23792      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23793      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23794      * reports or unit testing the {@link PixelCopy} API is recommended.
23795      */
23796     @Deprecated
getDrawingCache(boolean autoScale)23797     public Bitmap getDrawingCache(boolean autoScale) {
23798         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
23799             return null;
23800         }
23801         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
23802             buildDrawingCache(autoScale);
23803         }
23804         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
23805     }
23806 
23807     /**
23808      * <p>Frees the resources used by the drawing cache. If you call
23809      * {@link #buildDrawingCache()} manually without calling
23810      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
23811      * should cleanup the cache with this method afterwards.</p>
23812      *
23813      * @see #setDrawingCacheEnabled(boolean)
23814      * @see #buildDrawingCache()
23815      * @see #getDrawingCache()
23816      *
23817      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23818      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23819      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23820      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23821      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23822      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23823      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23824      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23825      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23826      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23827      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23828      * reports or unit testing the {@link PixelCopy} API is recommended.
23829      */
23830     @Deprecated
destroyDrawingCache()23831     public void destroyDrawingCache() {
23832         if (mDrawingCache != null) {
23833             mDrawingCache.recycle();
23834             mDrawingCache = null;
23835         }
23836         if (mUnscaledDrawingCache != null) {
23837             mUnscaledDrawingCache.recycle();
23838             mUnscaledDrawingCache = null;
23839         }
23840     }
23841 
23842     /**
23843      * Setting a solid background color for the drawing cache's bitmaps will improve
23844      * performance and memory usage. Note, though that this should only be used if this
23845      * view will always be drawn on top of a solid color.
23846      *
23847      * @param color The background color to use for the drawing cache's bitmap
23848      *
23849      * @see #setDrawingCacheEnabled(boolean)
23850      * @see #buildDrawingCache()
23851      * @see #getDrawingCache()
23852      *
23853      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23854      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23855      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23856      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23857      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23858      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23859      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23860      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23861      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23862      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23863      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23864      * reports or unit testing the {@link PixelCopy} API is recommended.
23865      */
23866     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)23867     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
23868         if (color != mDrawingCacheBackgroundColor) {
23869             mDrawingCacheBackgroundColor = color;
23870             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
23871         }
23872     }
23873 
23874     /**
23875      * @see #setDrawingCacheBackgroundColor(int)
23876      *
23877      * @return The background color to used for the drawing cache's bitmap
23878      *
23879      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23880      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23881      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23882      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23883      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23884      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23885      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23886      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23887      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23888      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23889      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23890      * reports or unit testing the {@link PixelCopy} API is recommended.
23891      */
23892     @Deprecated
23893     @ColorInt
getDrawingCacheBackgroundColor()23894     public int getDrawingCacheBackgroundColor() {
23895         return mDrawingCacheBackgroundColor;
23896     }
23897 
23898     /**
23899      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
23900      *
23901      * @see #buildDrawingCache(boolean)
23902      *
23903      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23904      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23905      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23906      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23907      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23908      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23909      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23910      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23911      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23912      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23913      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23914      * reports or unit testing the {@link PixelCopy} API is recommended.
23915      */
23916     @Deprecated
buildDrawingCache()23917     public void buildDrawingCache() {
23918         buildDrawingCache(false);
23919     }
23920 
23921     /**
23922      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
23923      *
23924      * <p>If you call {@link #buildDrawingCache()} manually without calling
23925      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
23926      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
23927      *
23928      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
23929      * this method will create a bitmap of the same size as this view. Because this bitmap
23930      * will be drawn scaled by the parent ViewGroup, the result on screen might show
23931      * scaling artifacts. To avoid such artifacts, you should call this method by setting
23932      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
23933      * size than the view. This implies that your application must be able to handle this
23934      * size.</p>
23935      *
23936      * <p>You should avoid calling this method when hardware acceleration is enabled. If
23937      * you do not need the drawing cache bitmap, calling this method will increase memory
23938      * usage and cause the view to be rendered in software once, thus negatively impacting
23939      * performance.</p>
23940      *
23941      * @see #getDrawingCache()
23942      * @see #destroyDrawingCache()
23943      *
23944      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23945      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23946      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23947      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23948      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23949      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23950      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23951      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23952      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23953      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23954      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23955      * reports or unit testing the {@link PixelCopy} API is recommended.
23956      */
23957     @Deprecated
buildDrawingCache(boolean autoScale)23958     public void buildDrawingCache(boolean autoScale) {
23959         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
23960                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
23961             if (Trace.isTagEnabled(TRACE_TAG_VIEW)) {
23962                 Trace.traceBegin(TRACE_TAG_VIEW,
23963                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
23964             }
23965             try {
23966                 buildDrawingCacheImpl(autoScale);
23967             } finally {
23968                 Trace.traceEnd(TRACE_TAG_VIEW);
23969             }
23970         }
23971     }
23972 
23973     /**
23974      * private, internal implementation of buildDrawingCache, used to enable tracing
23975      */
buildDrawingCacheImpl(boolean autoScale)23976     private void buildDrawingCacheImpl(boolean autoScale) {
23977         mCachingFailed = false;
23978 
23979         int width = mRight - mLeft;
23980         int height = mBottom - mTop;
23981 
23982         final AttachInfo attachInfo = mAttachInfo;
23983         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
23984 
23985         if (autoScale && scalingRequired) {
23986             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
23987             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
23988         }
23989 
23990         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
23991         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
23992         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
23993 
23994         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
23995         final long drawingCacheSize =
23996                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
23997         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
23998             if (width > 0 && height > 0) {
23999                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
24000                         + " too large to fit into a software layer (or drawing cache), needs "
24001                         + projectedBitmapSize + " bytes, only "
24002                         + drawingCacheSize + " available");
24003             }
24004             destroyDrawingCache();
24005             mCachingFailed = true;
24006             return;
24007         }
24008 
24009         boolean clear = true;
24010         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
24011 
24012         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
24013             Bitmap.Config quality;
24014             if (!opaque) {
24015                 // Never pick ARGB_4444 because it looks awful
24016                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
24017                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
24018                     case DRAWING_CACHE_QUALITY_AUTO:
24019                     case DRAWING_CACHE_QUALITY_LOW:
24020                     case DRAWING_CACHE_QUALITY_HIGH:
24021                     default:
24022                         quality = Bitmap.Config.ARGB_8888;
24023                         break;
24024                 }
24025             } else {
24026                 // Optimization for translucent windows
24027                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
24028                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
24029             }
24030 
24031             // Try to cleanup memory
24032             if (bitmap != null) bitmap.recycle();
24033 
24034             try {
24035                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
24036                         width, height, quality);
24037                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
24038                 if (autoScale) {
24039                     mDrawingCache = bitmap;
24040                 } else {
24041                     mUnscaledDrawingCache = bitmap;
24042                 }
24043                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
24044             } catch (OutOfMemoryError e) {
24045                 // If there is not enough memory to create the bitmap cache, just
24046                 // ignore the issue as bitmap caches are not required to draw the
24047                 // view hierarchy
24048                 if (autoScale) {
24049                     mDrawingCache = null;
24050                 } else {
24051                     mUnscaledDrawingCache = null;
24052                 }
24053                 mCachingFailed = true;
24054                 return;
24055             }
24056 
24057             clear = drawingCacheBackgroundColor != 0;
24058         }
24059 
24060         Canvas canvas;
24061         if (attachInfo != null) {
24062             canvas = attachInfo.mCanvas;
24063             if (canvas == null) {
24064                 canvas = new Canvas();
24065             }
24066             canvas.setBitmap(bitmap);
24067             // Temporarily clobber the cached Canvas in case one of our children
24068             // is also using a drawing cache. Without this, the children would
24069             // steal the canvas by attaching their own bitmap to it and bad, bad
24070             // thing would happen (invisible views, corrupted drawings, etc.)
24071             attachInfo.mCanvas = null;
24072         } else {
24073             // This case should hopefully never or seldom happen
24074             canvas = new Canvas(bitmap);
24075         }
24076 
24077         if (clear) {
24078             bitmap.eraseColor(drawingCacheBackgroundColor);
24079         }
24080 
24081         computeScroll();
24082         final int restoreCount = canvas.save();
24083 
24084         if (autoScale && scalingRequired) {
24085             final float scale = attachInfo.mApplicationScale;
24086             canvas.scale(scale, scale);
24087         }
24088 
24089         canvas.translate(-mScrollX, -mScrollY);
24090 
24091         mPrivateFlags |= PFLAG_DRAWN;
24092         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
24093                 mLayerType != LAYER_TYPE_NONE) {
24094             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
24095         }
24096 
24097         // Fast path for layouts with no backgrounds
24098         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
24099             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24100             dispatchDraw(canvas);
24101             drawAutofilledHighlight(canvas);
24102             if (mOverlay != null && !mOverlay.isEmpty()) {
24103                 mOverlay.getOverlayView().draw(canvas);
24104             }
24105         } else {
24106             draw(canvas);
24107         }
24108 
24109         canvas.restoreToCount(restoreCount);
24110         canvas.setBitmap(null);
24111 
24112         if (attachInfo != null) {
24113             // Restore the cached Canvas for our siblings
24114             attachInfo.mCanvas = canvas;
24115         }
24116     }
24117 
24118     /**
24119      * Create a snapshot of the view into a bitmap.  We should probably make
24120      * some form of this public, but should think about the API.
24121      *
24122      * @hide
24123      */
24124     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)24125     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
24126         int width = mRight - mLeft;
24127         int height = mBottom - mTop;
24128 
24129         final AttachInfo attachInfo = mAttachInfo;
24130         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
24131         width = (int) ((width * scale) + 0.5f);
24132         height = (int) ((height * scale) + 0.5f);
24133 
24134         Canvas oldCanvas = null;
24135         try {
24136             Canvas canvas = canvasProvider.getCanvas(this,
24137                     width > 0 ? width : 1, height > 0 ? height : 1);
24138 
24139             if (attachInfo != null) {
24140                 oldCanvas = attachInfo.mCanvas;
24141                 // Temporarily clobber the cached Canvas in case one of our children
24142                 // is also using a drawing cache. Without this, the children would
24143                 // steal the canvas by attaching their own bitmap to it and bad, bad
24144                 // things would happen (invisible views, corrupted drawings, etc.)
24145                 attachInfo.mCanvas = null;
24146             }
24147 
24148             computeScroll();
24149             final int restoreCount = canvas.save();
24150             canvas.scale(scale, scale);
24151             canvas.translate(-mScrollX, -mScrollY);
24152 
24153             // Temporarily remove the dirty mask
24154             int flags = mPrivateFlags;
24155             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24156 
24157             // Fast path for layouts with no backgrounds
24158             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
24159                 dispatchDraw(canvas);
24160                 drawAutofilledHighlight(canvas);
24161                 if (mOverlay != null && !mOverlay.isEmpty()) {
24162                     mOverlay.getOverlayView().draw(canvas);
24163                 }
24164             } else {
24165                 draw(canvas);
24166             }
24167 
24168             mPrivateFlags = flags;
24169             canvas.restoreToCount(restoreCount);
24170             return canvasProvider.createBitmap();
24171         } finally {
24172             if (oldCanvas != null) {
24173                 attachInfo.mCanvas = oldCanvas;
24174             }
24175         }
24176     }
24177 
24178     /**
24179      * Indicates whether this View is currently in edit mode. A View is usually
24180      * in edit mode when displayed within a developer tool. For instance, if
24181      * this View is being drawn by a visual user interface builder, this method
24182      * should return true.
24183      *
24184      * Subclasses should check the return value of this method to provide
24185      * different behaviors if their normal behavior might interfere with the
24186      * host environment. For instance: the class spawns a thread in its
24187      * constructor, the drawing code relies on device-specific features, etc.
24188      *
24189      * This method is usually checked in the drawing code of custom widgets.
24190      *
24191      * @return True if this View is in edit mode, false otherwise.
24192      */
isInEditMode()24193     public boolean isInEditMode() {
24194         return false;
24195     }
24196 
24197     /**
24198      * If the View draws content inside its padding and enables fading edges,
24199      * it needs to support padding offsets. Padding offsets are added to the
24200      * fading edges to extend the length of the fade so that it covers pixels
24201      * drawn inside the padding.
24202      *
24203      * Subclasses of this class should override this method if they need
24204      * to draw content inside the padding.
24205      *
24206      * @return True if padding offset must be applied, false otherwise.
24207      *
24208      * @see #getLeftPaddingOffset()
24209      * @see #getRightPaddingOffset()
24210      * @see #getTopPaddingOffset()
24211      * @see #getBottomPaddingOffset()
24212      *
24213      * @since CURRENT
24214      */
isPaddingOffsetRequired()24215     protected boolean isPaddingOffsetRequired() {
24216         return false;
24217     }
24218 
24219     /**
24220      * Amount by which to extend the left fading region. Called only when
24221      * {@link #isPaddingOffsetRequired()} returns true.
24222      *
24223      * @return The left padding offset in pixels.
24224      *
24225      * @see #isPaddingOffsetRequired()
24226      *
24227      * @since CURRENT
24228      */
getLeftPaddingOffset()24229     protected int getLeftPaddingOffset() {
24230         return 0;
24231     }
24232 
24233     /**
24234      * Amount by which to extend the right fading region. Called only when
24235      * {@link #isPaddingOffsetRequired()} returns true.
24236      *
24237      * @return The right padding offset in pixels.
24238      *
24239      * @see #isPaddingOffsetRequired()
24240      *
24241      * @since CURRENT
24242      */
getRightPaddingOffset()24243     protected int getRightPaddingOffset() {
24244         return 0;
24245     }
24246 
24247     /**
24248      * Amount by which to extend the top fading region. Called only when
24249      * {@link #isPaddingOffsetRequired()} returns true.
24250      *
24251      * @return The top padding offset in pixels.
24252      *
24253      * @see #isPaddingOffsetRequired()
24254      *
24255      * @since CURRENT
24256      */
getTopPaddingOffset()24257     protected int getTopPaddingOffset() {
24258         return 0;
24259     }
24260 
24261     /**
24262      * Amount by which to extend the bottom fading region. Called only when
24263      * {@link #isPaddingOffsetRequired()} returns true.
24264      *
24265      * @return The bottom padding offset in pixels.
24266      *
24267      * @see #isPaddingOffsetRequired()
24268      *
24269      * @since CURRENT
24270      */
getBottomPaddingOffset()24271     protected int getBottomPaddingOffset() {
24272         return 0;
24273     }
24274 
24275     /**
24276      * @hide
24277      * @param offsetRequired
24278      */
getFadeTop(boolean offsetRequired)24279     protected int getFadeTop(boolean offsetRequired) {
24280         int top = mPaddingTop;
24281         if (offsetRequired) top += getTopPaddingOffset();
24282         return top;
24283     }
24284 
24285     /**
24286      * @hide
24287      * @param offsetRequired
24288      */
getFadeHeight(boolean offsetRequired)24289     protected int getFadeHeight(boolean offsetRequired) {
24290         int padding = mPaddingTop;
24291         if (offsetRequired) padding += getTopPaddingOffset();
24292         return mBottom - mTop - mPaddingBottom - padding;
24293     }
24294 
24295     /**
24296      * <p>Indicates whether this view is attached to a hardware accelerated
24297      * window or not.</p>
24298      *
24299      * <p>Even if this method returns true, it does not mean that every call
24300      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
24301      * accelerated {@link android.graphics.Canvas}. For instance, if this view
24302      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
24303      * window is hardware accelerated,
24304      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
24305      * return false, and this method will return true.</p>
24306      *
24307      * @return True if the view is attached to a window and the window is
24308      *         hardware accelerated; false in any other case.
24309      */
24310     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()24311     public boolean isHardwareAccelerated() {
24312         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
24313     }
24314 
24315     /**
24316      * Sets a rectangular area on this view to which the view will be clipped
24317      * when it is drawn. Setting the value to null will remove the clip bounds
24318      * and the view will draw normally, using its full bounds.
24319      *
24320      * @param clipBounds The rectangular area, in the local coordinates of
24321      * this view, to which future drawing operations will be clipped.
24322      */
setClipBounds(Rect clipBounds)24323     public void setClipBounds(Rect clipBounds) {
24324         if (clipBounds == mClipBounds
24325                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
24326             return;
24327         }
24328         if (clipBounds != null) {
24329             if (mClipBounds == null) {
24330                 mClipBounds = new Rect(clipBounds);
24331             } else {
24332                 mClipBounds.set(clipBounds);
24333             }
24334         } else {
24335             mClipBounds = null;
24336         }
24337         mRenderNode.setClipRect(mClipBounds);
24338         invalidateViewProperty(false, false);
24339     }
24340 
24341     /**
24342      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
24343      *
24344      * @return A copy of the current clip bounds if clip bounds are set,
24345      * otherwise null.
24346      */
getClipBounds()24347     public Rect getClipBounds() {
24348         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
24349     }
24350 
24351 
24352     /**
24353      * Populates an output rectangle with the clip bounds of the view,
24354      * returning {@code true} if successful or {@code false} if the view's
24355      * clip bounds are {@code null}.
24356      *
24357      * @param outRect rectangle in which to place the clip bounds of the view
24358      * @return {@code true} if successful or {@code false} if the view's
24359      *         clip bounds are {@code null}
24360      */
getClipBounds(Rect outRect)24361     public boolean getClipBounds(Rect outRect) {
24362         if (mClipBounds != null) {
24363             outRect.set(mClipBounds);
24364             return true;
24365         }
24366         return false;
24367     }
24368 
24369     /**
24370      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
24371      * case of an active Animation being run on the view.
24372      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)24373     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
24374             Animation a, boolean scalingRequired) {
24375         Transformation invalidationTransform;
24376         final int flags = parent.mGroupFlags;
24377         final boolean initialized = a.isInitialized();
24378         if (!initialized) {
24379             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
24380             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
24381             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
24382             onAnimationStart();
24383         }
24384 
24385         final Transformation t = parent.getChildTransformation();
24386         boolean more = a.getTransformation(drawingTime, t, 1f);
24387         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
24388             if (parent.mInvalidationTransformation == null) {
24389                 parent.mInvalidationTransformation = new Transformation();
24390             }
24391             invalidationTransform = parent.mInvalidationTransformation;
24392             a.getTransformation(drawingTime, invalidationTransform, 1f);
24393         } else {
24394             invalidationTransform = t;
24395         }
24396 
24397         if (more) {
24398             if (!a.willChangeBounds()) {
24399                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
24400                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
24401                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
24402                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
24403                     // The child need to draw an animation, potentially offscreen, so
24404                     // make sure we do not cancel invalidate requests
24405                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
24406                     parent.invalidate(mLeft, mTop, mRight, mBottom);
24407                 }
24408             } else {
24409                 if (parent.mInvalidateRegion == null) {
24410                     parent.mInvalidateRegion = new RectF();
24411                 }
24412                 final RectF region = parent.mInvalidateRegion;
24413                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
24414                         invalidationTransform);
24415 
24416                 // The child need to draw an animation, potentially offscreen, so
24417                 // make sure we do not cancel invalidate requests
24418                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
24419 
24420                 final int left = mLeft + (int) region.left;
24421                 final int top = mTop + (int) region.top;
24422                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
24423                         top + (int) (region.height() + .5f));
24424             }
24425         }
24426         return more;
24427     }
24428 
24429     /**
24430      * This method is called by getDisplayList() when a display list is recorded for a View.
24431      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
24432      */
setDisplayListProperties(RenderNode renderNode)24433     void setDisplayListProperties(RenderNode renderNode) {
24434         if (renderNode != null) {
24435             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
24436             renderNode.setClipToBounds(mParent instanceof ViewGroup
24437                     && ((ViewGroup) mParent).getClipChildren());
24438 
24439             float alpha = 1;
24440             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
24441                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
24442                 ViewGroup parentVG = (ViewGroup) mParent;
24443                 final Transformation t = parentVG.getChildTransformation();
24444                 if (parentVG.getChildStaticTransformation(this, t)) {
24445                     final int transformType = t.getTransformationType();
24446                     if (transformType != Transformation.TYPE_IDENTITY) {
24447                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
24448                             alpha = t.getAlpha();
24449                         }
24450                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
24451                             renderNode.setStaticMatrix(t.getMatrix());
24452                         }
24453                     }
24454                 }
24455             }
24456             if (mTransformationInfo != null) {
24457                 alpha *= getFinalAlpha();
24458                 if (alpha < 1) {
24459                     final int multipliedAlpha = (int) (255 * alpha);
24460                     if (onSetAlpha(multipliedAlpha)) {
24461                         alpha = 1;
24462                     }
24463                 }
24464                 renderNode.setAlpha(alpha);
24465             } else if (alpha < 1) {
24466                 renderNode.setAlpha(alpha);
24467             }
24468         }
24469     }
24470 
24471     /**
24472      * If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
24473      *
24474      * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
24475      * HW accelerated, it can't handle drawing RenderNodes.
24476      *
24477      * @hide
24478      */
drawsWithRenderNode(@onNull Canvas canvas)24479     protected final boolean drawsWithRenderNode(@NonNull Canvas canvas) {
24480         return mAttachInfo != null
24481                 && mAttachInfo.mHardwareAccelerated
24482                 && canvas.isHardwareAccelerated();
24483     }
24484 
24485     /**
24486      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
24487      *
24488      * This is where the View specializes rendering behavior based on layer type,
24489      * and hardware acceleration.
24490      */
draw(@onNull Canvas canvas, ViewGroup parent, long drawingTime)24491     boolean draw(@NonNull Canvas canvas, ViewGroup parent, long drawingTime) {
24492 
24493         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
24494 
24495         boolean drawingWithRenderNode = drawsWithRenderNode(canvas);
24496 
24497         boolean more = false;
24498         final boolean childHasIdentityMatrix = hasIdentityMatrix();
24499         final int parentFlags = parent.mGroupFlags;
24500 
24501         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
24502             parent.getChildTransformation().clear();
24503             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24504         }
24505 
24506         Transformation transformToApply = null;
24507         boolean concatMatrix = false;
24508         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
24509         final Animation a = getAnimation();
24510         if (a != null) {
24511             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
24512             concatMatrix = a.willChangeTransformationMatrix();
24513             if (concatMatrix) {
24514                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
24515             }
24516             transformToApply = parent.getChildTransformation();
24517         } else {
24518             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
24519                 // No longer animating: clear out old animation matrix
24520                 mRenderNode.setAnimationMatrix(null);
24521                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
24522             }
24523             if (!drawingWithRenderNode
24524                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
24525                 final Transformation t = parent.getChildTransformation();
24526                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
24527                 if (hasTransform) {
24528                     final int transformType = t.getTransformationType();
24529                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
24530                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
24531                 }
24532             }
24533         }
24534 
24535         concatMatrix |= !childHasIdentityMatrix;
24536 
24537         // Sets the flag as early as possible to allow draw() implementations
24538         // to call invalidate() successfully when doing animations
24539         mPrivateFlags |= PFLAG_DRAWN;
24540 
24541         if (!concatMatrix &&
24542                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
24543                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
24544                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
24545                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
24546             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
24547             return more;
24548         }
24549         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
24550 
24551         if (hardwareAcceleratedCanvas) {
24552             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
24553             // retain the flag's value temporarily in the mRecreateDisplayList flag
24554             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
24555             mPrivateFlags &= ~PFLAG_INVALIDATED;
24556         }
24557 
24558         RenderNode renderNode = null;
24559         Bitmap cache = null;
24560         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
24561         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
24562              if (layerType != LAYER_TYPE_NONE) {
24563                  // If not drawing with RenderNode, treat HW layers as SW
24564                  layerType = LAYER_TYPE_SOFTWARE;
24565                  buildDrawingCache(true);
24566             }
24567             cache = getDrawingCache(true);
24568         }
24569 
24570         if (drawingWithRenderNode) {
24571             // Delay getting the display list until animation-driven alpha values are
24572             // set up and possibly passed on to the view
24573             renderNode = updateDisplayListIfDirty();
24574             if (!renderNode.hasDisplayList()) {
24575                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
24576                 // to getDisplayList(), the display list will be marked invalid and we should not
24577                 // try to use it again.
24578                 renderNode = null;
24579                 drawingWithRenderNode = false;
24580             }
24581         }
24582 
24583         int sx = 0;
24584         int sy = 0;
24585         if (!drawingWithRenderNode) {
24586             computeScroll();
24587             sx = mScrollX;
24588             sy = mScrollY;
24589         }
24590 
24591         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
24592         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
24593 
24594         int restoreTo = -1;
24595         if (!drawingWithRenderNode || transformToApply != null) {
24596             restoreTo = canvas.save();
24597         }
24598         if (offsetForScroll) {
24599             canvas.translate(mLeft - sx, mTop - sy);
24600         } else {
24601             if (!drawingWithRenderNode) {
24602                 canvas.translate(mLeft, mTop);
24603             }
24604             if (scalingRequired) {
24605                 if (drawingWithRenderNode) {
24606                     // TODO: Might not need this if we put everything inside the DL
24607                     restoreTo = canvas.save();
24608                 }
24609                 // mAttachInfo cannot be null, otherwise scalingRequired == false
24610                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
24611                 canvas.scale(scale, scale);
24612             }
24613         }
24614 
24615         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
24616         if (transformToApply != null
24617                 || alpha < 1
24618                 || !hasIdentityMatrix()
24619                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
24620             if (transformToApply != null || !childHasIdentityMatrix) {
24621                 int transX = 0;
24622                 int transY = 0;
24623 
24624                 if (offsetForScroll) {
24625                     transX = -sx;
24626                     transY = -sy;
24627                 }
24628 
24629                 if (transformToApply != null) {
24630                     if (concatMatrix) {
24631                         if (drawingWithRenderNode) {
24632                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
24633                         } else {
24634                             // Undo the scroll translation, apply the transformation matrix,
24635                             // then redo the scroll translate to get the correct result.
24636                             canvas.translate(-transX, -transY);
24637                             canvas.concat(transformToApply.getMatrix());
24638                             canvas.translate(transX, transY);
24639                         }
24640                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24641                     }
24642 
24643                     float transformAlpha = transformToApply.getAlpha();
24644                     if (transformAlpha < 1) {
24645                         alpha *= transformAlpha;
24646                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24647                     }
24648                 }
24649 
24650                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
24651                     canvas.translate(-transX, -transY);
24652                     canvas.concat(getMatrix());
24653                     canvas.translate(transX, transY);
24654                 }
24655             }
24656 
24657             // Deal with alpha if it is or used to be <1
24658             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
24659                 if (alpha < 1) {
24660                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
24661                 } else {
24662                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
24663                 }
24664                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24665                 if (!drawingWithDrawingCache) {
24666                     final int multipliedAlpha = (int) (255 * alpha);
24667                     if (!onSetAlpha(multipliedAlpha)) {
24668                         if (drawingWithRenderNode) {
24669                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
24670                         } else if (layerType == LAYER_TYPE_NONE) {
24671                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
24672                                     multipliedAlpha);
24673                         }
24674                     } else {
24675                         // Alpha is handled by the child directly, clobber the layer's alpha
24676                         mPrivateFlags |= PFLAG_ALPHA_SET;
24677                     }
24678                 }
24679             }
24680         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
24681             onSetAlpha(255);
24682             mPrivateFlags &= ~PFLAG_ALPHA_SET;
24683         }
24684 
24685         if (!drawingWithRenderNode) {
24686             // apply clips directly, since RenderNode won't do it for this draw
24687             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
24688                 if (offsetForScroll) {
24689                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
24690                 } else {
24691                     if (!scalingRequired || cache == null) {
24692                         canvas.clipRect(0, 0, getWidth(), getHeight());
24693                     } else {
24694                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
24695                     }
24696                 }
24697             }
24698 
24699             if (mClipBounds != null) {
24700                 // clip bounds ignore scroll
24701                 canvas.clipRect(mClipBounds);
24702             }
24703         }
24704 
24705         if (!drawingWithDrawingCache) {
24706             if (drawingWithRenderNode) {
24707                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24708                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
24709             } else {
24710                 // Fast path for layouts with no backgrounds
24711                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
24712                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24713                     dispatchDraw(canvas);
24714                 } else {
24715                     draw(canvas);
24716                 }
24717             }
24718         } else if (cache != null) {
24719             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24720             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
24721                 // no layer paint, use temporary paint to draw bitmap
24722                 Paint cachePaint = parent.mCachePaint;
24723                 if (cachePaint == null) {
24724                     cachePaint = new Paint();
24725                     cachePaint.setDither(false);
24726                     parent.mCachePaint = cachePaint;
24727                 }
24728                 cachePaint.setAlpha((int) (alpha * 255));
24729                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
24730             } else {
24731                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
24732                 int layerPaintAlpha = mLayerPaint.getAlpha();
24733                 if (alpha < 1) {
24734                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
24735                 }
24736                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
24737                 if (alpha < 1) {
24738                     mLayerPaint.setAlpha(layerPaintAlpha);
24739                 }
24740             }
24741         }
24742 
24743         if (restoreTo >= 0) {
24744             canvas.restoreToCount(restoreTo);
24745         }
24746 
24747         if (a != null && !more) {
24748             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
24749                 onSetAlpha(255);
24750             }
24751             parent.finishAnimatingView(this, a);
24752         }
24753 
24754         if (more && hardwareAcceleratedCanvas) {
24755             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
24756                 // alpha animations should cause the child to recreate its display list
24757                 invalidate(true);
24758             }
24759         }
24760 
24761         mRecreateDisplayList = false;
24762 
24763         return more;
24764     }
24765 
getDebugPaint()24766     static Paint getDebugPaint() {
24767         if (sDebugPaint == null) {
24768             sDebugPaint = new Paint();
24769             sDebugPaint.setAntiAlias(false);
24770         }
24771         return sDebugPaint;
24772     }
24773 
dipsToPixels(int dips)24774     final int dipsToPixels(int dips) {
24775         float scale = getContext().getResources().getDisplayMetrics().density;
24776         return (int) (dips * scale + 0.5f);
24777     }
24778 
debugDrawFocus(@onNull Canvas canvas)24779     private void debugDrawFocus(@NonNull Canvas canvas) {
24780         if (isFocused()) {
24781             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
24782             final int l = mScrollX;
24783             final int r = l + mRight - mLeft;
24784             final int t = mScrollY;
24785             final int b = t + mBottom - mTop;
24786 
24787             final Paint paint = getDebugPaint();
24788             paint.setColor(DEBUG_CORNERS_COLOR);
24789 
24790             // Draw squares in corners.
24791             paint.setStyle(Paint.Style.FILL);
24792             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
24793             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
24794             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
24795             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
24796 
24797             // Draw big X across the view.
24798             paint.setStyle(Paint.Style.STROKE);
24799             canvas.drawLine(l, t, r, b, paint);
24800             canvas.drawLine(l, b, r, t, paint);
24801         }
24802     }
24803 
24804     /**
24805      * Manually render this view (and all of its children) to the given Canvas.
24806      * The view must have already done a full layout before this function is
24807      * called.  When implementing a view, implement
24808      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
24809      * If you do need to override this method, call the superclass version.
24810      *
24811      * @param canvas The Canvas to which the View is rendered.
24812      */
24813     @CallSuper
draw(@onNull Canvas canvas)24814     public void draw(@NonNull Canvas canvas) {
24815         final int privateFlags = mPrivateFlags;
24816         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
24817 
24818         /*
24819          * Draw traversal performs several drawing steps which must be executed
24820          * in the appropriate order:
24821          *
24822          *      1. Draw the background
24823          *      2. If necessary, save the canvas' layers to prepare for fading
24824          *      3. Draw view's content
24825          *      4. Draw children
24826          *      5. If necessary, draw the fading edges and restore layers
24827          *      6. Draw decorations (scrollbars for instance)
24828          *      7. If necessary, draw the default focus highlight
24829          */
24830 
24831         // Step 1, draw the background, if needed
24832         int saveCount;
24833 
24834         drawBackground(canvas);
24835 
24836         // skip step 2 & 5 if possible (common case)
24837         final int viewFlags = mViewFlags;
24838         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
24839         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
24840         if (!verticalEdges && !horizontalEdges) {
24841             // Step 3, draw the content
24842             onDraw(canvas);
24843 
24844             // Step 4, draw the children
24845             dispatchDraw(canvas);
24846 
24847             drawAutofilledHighlight(canvas);
24848 
24849             // Overlay is part of the content and draws beneath Foreground
24850             if (mOverlay != null && !mOverlay.isEmpty()) {
24851                 mOverlay.getOverlayView().dispatchDraw(canvas);
24852             }
24853 
24854             // Step 6, draw decorations (foreground, scrollbars)
24855             onDrawForeground(canvas);
24856 
24857             // Step 7, draw the default focus highlight
24858             drawDefaultFocusHighlight(canvas);
24859 
24860             if (isShowingLayoutBounds()) {
24861                 debugDrawFocus(canvas);
24862             }
24863 
24864             // we're done...
24865             return;
24866         }
24867 
24868         /*
24869          * Here we do the full fledged routine...
24870          * (this is an uncommon case where speed matters less,
24871          * this is why we repeat some of the tests that have been
24872          * done above)
24873          */
24874 
24875         boolean drawTop = false;
24876         boolean drawBottom = false;
24877         boolean drawLeft = false;
24878         boolean drawRight = false;
24879 
24880         float topFadeStrength = 0.0f;
24881         float bottomFadeStrength = 0.0f;
24882         float leftFadeStrength = 0.0f;
24883         float rightFadeStrength = 0.0f;
24884 
24885         // Step 2, save the canvas' layers
24886         int paddingLeft = mPaddingLeft;
24887 
24888         final boolean offsetRequired = isPaddingOffsetRequired();
24889         if (offsetRequired) {
24890             paddingLeft += getLeftPaddingOffset();
24891         }
24892 
24893         int left = mScrollX + paddingLeft;
24894         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
24895         int top = mScrollY + getFadeTop(offsetRequired);
24896         int bottom = top + getFadeHeight(offsetRequired);
24897 
24898         if (offsetRequired) {
24899             right += getRightPaddingOffset();
24900             bottom += getBottomPaddingOffset();
24901         }
24902 
24903         final ScrollabilityCache scrollabilityCache = mScrollCache;
24904         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
24905         int length = (int) fadeHeight;
24906 
24907         // clip the fade length if top and bottom fades overlap
24908         // overlapping fades produce odd-looking artifacts
24909         if (verticalEdges && (top + length > bottom - length)) {
24910             length = (bottom - top) / 2;
24911         }
24912 
24913         // also clip horizontal fades if necessary
24914         if (horizontalEdges && (left + length > right - length)) {
24915             length = (right - left) / 2;
24916         }
24917 
24918         if (verticalEdges) {
24919             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
24920             drawTop = topFadeStrength * fadeHeight > 1.0f;
24921             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
24922             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
24923         }
24924 
24925         if (horizontalEdges) {
24926             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
24927             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
24928             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
24929             drawRight = rightFadeStrength * fadeHeight > 1.0f;
24930         }
24931 
24932         saveCount = canvas.getSaveCount();
24933         int topSaveCount = -1;
24934         int bottomSaveCount = -1;
24935         int leftSaveCount = -1;
24936         int rightSaveCount = -1;
24937 
24938         int solidColor = getSolidColor();
24939         if (solidColor == 0) {
24940             if (drawTop) {
24941                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
24942             }
24943 
24944             if (drawBottom) {
24945                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
24946             }
24947 
24948             if (drawLeft) {
24949                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
24950             }
24951 
24952             if (drawRight) {
24953                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
24954             }
24955         } else {
24956             scrollabilityCache.setFadeColor(solidColor);
24957         }
24958 
24959         // Step 3, draw the content
24960         onDraw(canvas);
24961 
24962         // Step 4, draw the children
24963         dispatchDraw(canvas);
24964 
24965         // Step 5, draw the fade effect and restore layers
24966         final Paint p = scrollabilityCache.paint;
24967         final Matrix matrix = scrollabilityCache.matrix;
24968         final Shader fade = scrollabilityCache.shader;
24969 
24970         // must be restored in the reverse order that they were saved
24971         if (drawRight) {
24972             matrix.setScale(1, fadeHeight * rightFadeStrength);
24973             matrix.postRotate(90);
24974             matrix.postTranslate(right, top);
24975             fade.setLocalMatrix(matrix);
24976             p.setShader(fade);
24977             if (solidColor == 0) {
24978                 canvas.restoreUnclippedLayer(rightSaveCount, p);
24979 
24980             } else {
24981                 canvas.drawRect(right - length, top, right, bottom, p);
24982             }
24983         }
24984 
24985         if (drawLeft) {
24986             matrix.setScale(1, fadeHeight * leftFadeStrength);
24987             matrix.postRotate(-90);
24988             matrix.postTranslate(left, top);
24989             fade.setLocalMatrix(matrix);
24990             p.setShader(fade);
24991             if (solidColor == 0) {
24992                 canvas.restoreUnclippedLayer(leftSaveCount, p);
24993             } else {
24994                 canvas.drawRect(left, top, left + length, bottom, p);
24995             }
24996         }
24997 
24998         if (drawBottom) {
24999             matrix.setScale(1, fadeHeight * bottomFadeStrength);
25000             matrix.postRotate(180);
25001             matrix.postTranslate(left, bottom);
25002             fade.setLocalMatrix(matrix);
25003             p.setShader(fade);
25004             if (solidColor == 0) {
25005                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
25006             } else {
25007                 canvas.drawRect(left, bottom - length, right, bottom, p);
25008             }
25009         }
25010 
25011         if (drawTop) {
25012             matrix.setScale(1, fadeHeight * topFadeStrength);
25013             matrix.postTranslate(left, top);
25014             fade.setLocalMatrix(matrix);
25015             p.setShader(fade);
25016             if (solidColor == 0) {
25017                 canvas.restoreUnclippedLayer(topSaveCount, p);
25018             } else {
25019                 canvas.drawRect(left, top, right, top + length, p);
25020             }
25021         }
25022 
25023         canvas.restoreToCount(saveCount);
25024 
25025         drawAutofilledHighlight(canvas);
25026 
25027         // Overlay is part of the content and draws beneath Foreground
25028         if (mOverlay != null && !mOverlay.isEmpty()) {
25029             mOverlay.getOverlayView().dispatchDraw(canvas);
25030         }
25031 
25032         // Step 6, draw decorations (foreground, scrollbars)
25033         onDrawForeground(canvas);
25034 
25035         // Step 7, draw the default focus highlight
25036         drawDefaultFocusHighlight(canvas);
25037 
25038         if (isShowingLayoutBounds()) {
25039             debugDrawFocus(canvas);
25040         }
25041     }
25042 
25043     /**
25044      * Draws the background onto the specified canvas.
25045      *
25046      * @param canvas Canvas on which to draw the background
25047      */
25048     @UnsupportedAppUsage
drawBackground(@onNull Canvas canvas)25049     private void drawBackground(@NonNull Canvas canvas) {
25050         final Drawable background = mBackground;
25051         if (background == null) {
25052             return;
25053         }
25054 
25055         setBackgroundBounds();
25056 
25057         // Attempt to use a display list if requested.
25058         if (canvas.isHardwareAccelerated() && mAttachInfo != null
25059                 && mAttachInfo.mThreadedRenderer != null) {
25060             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
25061 
25062             final RenderNode renderNode = mBackgroundRenderNode;
25063             if (renderNode != null && renderNode.hasDisplayList()) {
25064                 setBackgroundRenderNodeProperties(renderNode);
25065                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
25066                 return;
25067             }
25068         }
25069 
25070         final int scrollX = mScrollX;
25071         final int scrollY = mScrollY;
25072         if ((scrollX | scrollY) == 0) {
25073             background.draw(canvas);
25074         } else {
25075             canvas.translate(scrollX, scrollY);
25076             background.draw(canvas);
25077             canvas.translate(-scrollX, -scrollY);
25078         }
25079     }
25080 
25081     /**
25082      * Sets the correct background bounds and rebuilds the outline, if needed.
25083      * <p/>
25084      * This is called by LayoutLib.
25085      */
setBackgroundBounds()25086     void setBackgroundBounds() {
25087         if (mBackgroundSizeChanged && mBackground != null) {
25088             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
25089             mBackgroundSizeChanged = false;
25090             rebuildOutline();
25091         }
25092     }
25093 
setBackgroundRenderNodeProperties(RenderNode renderNode)25094     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
25095         renderNode.setTranslationX(mScrollX);
25096         renderNode.setTranslationY(mScrollY);
25097     }
25098 
25099     /**
25100      * Creates a new display list or updates the existing display list for the
25101      * specified Drawable.
25102      *
25103      * @param drawable Drawable for which to create a display list
25104      * @param renderNode Existing RenderNode, or {@code null}
25105      * @return A valid display list for the specified drawable
25106      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)25107     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
25108         if (renderNode == null) {
25109             renderNode = RenderNode.create(drawable.getClass().getName(),
25110                     new ViewAnimationHostBridge(this));
25111             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
25112         }
25113 
25114         final Rect bounds = drawable.getBounds();
25115         final int width = bounds.width();
25116         final int height = bounds.height();
25117 
25118         // Hacky hack: Reset any stretch effects as those are applied during the draw pass
25119         // instead of being "stateful" like other RenderNode properties
25120         renderNode.clearStretch();
25121 
25122         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
25123 
25124         // Reverse left/top translation done by drawable canvas, which will
25125         // instead be applied by rendernode's LTRB bounds below. This way, the
25126         // drawable's bounds match with its rendernode bounds and its content
25127         // will lie within those bounds in the rendernode tree.
25128         canvas.translate(-bounds.left, -bounds.top);
25129 
25130         try {
25131             drawable.draw(canvas);
25132         } finally {
25133             renderNode.endRecording();
25134         }
25135 
25136         // Set up drawable properties that are view-independent.
25137         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
25138         renderNode.setProjectBackwards(drawable.isProjected());
25139         renderNode.setProjectionReceiver(true);
25140         renderNode.setClipToBounds(false);
25141         return renderNode;
25142     }
25143 
25144     /**
25145      * Returns the overlay for this view, creating it if it does not yet exist.
25146      * Adding drawables to the overlay will cause them to be displayed whenever
25147      * the view itself is redrawn. Objects in the overlay should be actively
25148      * managed: remove them when they should not be displayed anymore. The
25149      * overlay will always have the same size as its host view.
25150      *
25151      * <p>Note: Overlays do not currently work correctly with {@link
25152      * SurfaceView} or {@link TextureView}; contents in overlays for these
25153      * types of views may not display correctly.</p>
25154      *
25155      * @return The ViewOverlay object for this view.
25156      * @see ViewOverlay
25157      */
getOverlay()25158     public ViewOverlay getOverlay() {
25159         if (mOverlay == null) {
25160             mOverlay = new ViewOverlay(mContext, this);
25161         }
25162         return mOverlay;
25163     }
25164 
25165     /**
25166      * Override this if your view is known to always be drawn on top of a solid color background,
25167      * and needs to draw fading edges. Returning a non-zero color enables the view system to
25168      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
25169      * should be set to 0xFF.
25170      *
25171      * @see #setVerticalFadingEdgeEnabled(boolean)
25172      * @see #setHorizontalFadingEdgeEnabled(boolean)
25173      *
25174      * @return The known solid color background for this view, or 0 if the color may vary
25175      */
25176     @ViewDebug.ExportedProperty(category = "drawing")
25177     @InspectableProperty
25178     @ColorInt
getSolidColor()25179     public int getSolidColor() {
25180         return 0;
25181     }
25182 
25183     /**
25184      * Build a human readable string representation of the specified view flags.
25185      *
25186      * @param flags the view flags to convert to a string
25187      * @return a String representing the supplied flags
25188      */
printFlags(int flags)25189     private static String printFlags(int flags) {
25190         String output = "";
25191         int numFlags = 0;
25192         if ((flags & FOCUSABLE) == FOCUSABLE) {
25193             output += "TAKES_FOCUS";
25194             numFlags++;
25195         }
25196 
25197         switch (flags & VISIBILITY_MASK) {
25198         case INVISIBLE:
25199             if (numFlags > 0) {
25200                 output += " ";
25201             }
25202             output += "INVISIBLE";
25203             // USELESS HERE numFlags++;
25204             break;
25205         case GONE:
25206             if (numFlags > 0) {
25207                 output += " ";
25208             }
25209             output += "GONE";
25210             // USELESS HERE numFlags++;
25211             break;
25212         default:
25213             break;
25214         }
25215         return output;
25216     }
25217 
25218     /**
25219      * Build a human readable string representation of the specified private
25220      * view flags.
25221      *
25222      * @param privateFlags the private view flags to convert to a string
25223      * @return a String representing the supplied flags
25224      */
printPrivateFlags(int privateFlags)25225     private static String printPrivateFlags(int privateFlags) {
25226         String output = "";
25227         int numFlags = 0;
25228 
25229         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
25230             output += "WANTS_FOCUS";
25231             numFlags++;
25232         }
25233 
25234         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
25235             if (numFlags > 0) {
25236                 output += " ";
25237             }
25238             output += "FOCUSED";
25239             numFlags++;
25240         }
25241 
25242         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
25243             if (numFlags > 0) {
25244                 output += " ";
25245             }
25246             output += "SELECTED";
25247             numFlags++;
25248         }
25249 
25250         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
25251             if (numFlags > 0) {
25252                 output += " ";
25253             }
25254             output += "IS_ROOT_NAMESPACE";
25255             numFlags++;
25256         }
25257 
25258         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
25259             if (numFlags > 0) {
25260                 output += " ";
25261             }
25262             output += "HAS_BOUNDS";
25263             numFlags++;
25264         }
25265 
25266         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
25267             if (numFlags > 0) {
25268                 output += " ";
25269             }
25270             output += "DRAWN";
25271             // USELESS HERE numFlags++;
25272         }
25273         return output;
25274     }
25275 
25276     /**
25277      * <p>Indicates whether or not this view's layout will be requested during
25278      * the next hierarchy layout pass.</p>
25279      *
25280      * @return true if the layout will be forced during next layout pass
25281      */
isLayoutRequested()25282     public boolean isLayoutRequested() {
25283         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
25284     }
25285 
25286     /**
25287      * Return true if o is a ViewGroup that is laying out using optical bounds.
25288      * @hide
25289      */
isLayoutModeOptical(Object o)25290     public static boolean isLayoutModeOptical(Object o) {
25291         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
25292     }
25293 
25294     /**
25295      * Enable measure/layout debugging on traces.
25296      *
25297      * @see Trace
25298      * @hide
25299      */
setTraceLayoutSteps(boolean traceLayoutSteps)25300     public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
25301         sTraceLayoutSteps = traceLayoutSteps;
25302     }
25303 
25304     /**
25305      * Enable request layout tracing classes with {@code s} simple name.
25306      * <p>
25307      * When set, a {@link Trace} instant event and a log with the stacktrace is emitted every
25308      * time a requestLayout of a class matching {@code s} name happens.
25309      * This applies only to views attached from this point onwards.
25310      *
25311      * @see Trace#instant(long, String)
25312      * @hide
25313      */
setTracedRequestLayoutClassClass(String s)25314     public static void setTracedRequestLayoutClassClass(String s) {
25315         sTraceRequestLayoutClass = s;
25316     }
25317 
setOpticalFrame(int left, int top, int right, int bottom)25318     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
25319         Insets parentInsets = mParent instanceof View ?
25320                 ((View) mParent).getOpticalInsets() : Insets.NONE;
25321         Insets childInsets = getOpticalInsets();
25322         return setFrame(
25323                 left   + parentInsets.left - childInsets.left,
25324                 top    + parentInsets.top  - childInsets.top,
25325                 right  + parentInsets.left + childInsets.right,
25326                 bottom + parentInsets.top  + childInsets.bottom);
25327     }
25328 
25329     /**
25330      * Assign a size and position to a view and all of its
25331      * descendants
25332      *
25333      * <p>This is the second phase of the layout mechanism.
25334      * (The first is measuring). In this phase, each parent calls
25335      * layout on all of its children to position them.
25336      * This is typically done using the child measurements
25337      * that were stored in the measure pass().</p>
25338      *
25339      * <p>Derived classes should not override this method.
25340      * Derived classes with children should override
25341      * onLayout. In that method, they should
25342      * call layout on each of their children.</p>
25343      *
25344      * @param l Left position, relative to parent
25345      * @param t Top position, relative to parent
25346      * @param r Right position, relative to parent
25347      * @param b Bottom position, relative to parent
25348      */
25349     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)25350     public void layout(int l, int t, int r, int b) {
25351         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
25352             if (isTraversalTracingEnabled()) {
25353                 Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
25354             }
25355             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
25356             if (isTraversalTracingEnabled()) {
25357                 Trace.endSection();
25358             }
25359             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25360         }
25361 
25362         int oldL = mLeft;
25363         int oldT = mTop;
25364         int oldB = mBottom;
25365         int oldR = mRight;
25366 
25367         boolean changed = isLayoutModeOptical(mParent) ?
25368                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
25369 
25370         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
25371             if (isTraversalTracingEnabled()) {
25372                 Trace.beginSection(mTracingStrings.onLayout);
25373             }
25374             onLayout(changed, l, t, r, b);
25375             if (isTraversalTracingEnabled()) {
25376                 Trace.endSection();
25377             }
25378 
25379             if (shouldDrawRoundScrollbar()) {
25380                 if(mRoundScrollbarRenderer == null) {
25381                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
25382                 }
25383             } else {
25384                 mRoundScrollbarRenderer = null;
25385             }
25386 
25387             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
25388 
25389             ListenerInfo li = mListenerInfo;
25390             if (li != null && li.mOnLayoutChangeListeners != null) {
25391                 ArrayList<OnLayoutChangeListener> listenersCopy =
25392                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
25393                 int numListeners = listenersCopy.size();
25394                 for (int i = 0; i < numListeners; ++i) {
25395                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
25396                 }
25397             }
25398         }
25399 
25400         final boolean wasLayoutValid = isLayoutValid();
25401 
25402         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
25403         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
25404 
25405         if (!wasLayoutValid && isFocused()) {
25406             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
25407             if (canTakeFocus()) {
25408                 // We have a robust focus, so parents should no longer be wanting focus.
25409                 clearParentsWantFocus();
25410             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
25411                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
25412                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
25413                 // and thus the safest action is to clear focus here.
25414                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
25415                 clearParentsWantFocus();
25416             } else if (!hasParentWantsFocus()) {
25417                 // original requestFocus was likely on this view directly, so just clear focus
25418                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
25419             }
25420             // otherwise, we let parents handle re-assigning focus during their layout passes.
25421         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
25422             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
25423             View focused = findFocus();
25424             if (focused != null) {
25425                 // Try to restore focus as close as possible to our starting focus.
25426                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
25427                     // Give up and clear focus once we've reached the top-most parent which wants
25428                     // focus.
25429                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
25430                 }
25431             }
25432         }
25433 
25434         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
25435             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
25436             notifyEnterOrExitForAutoFillIfNeeded(true);
25437         }
25438 
25439         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
25440     }
25441 
hasParentWantsFocus()25442     private boolean hasParentWantsFocus() {
25443         ViewParent parent = mParent;
25444         while (parent instanceof ViewGroup) {
25445             ViewGroup pv = (ViewGroup) parent;
25446             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
25447                 return true;
25448             }
25449             parent = pv.mParent;
25450         }
25451         return false;
25452     }
25453 
25454     /**
25455      * Called from layout when this view should
25456      * assign a size and position to each of its children.
25457      *
25458      * Derived classes with children should override
25459      * this method and call layout on each of
25460      * their children.
25461      * @param changed This is a new size or position for this view
25462      * @param left Left position, relative to parent
25463      * @param top Top position, relative to parent
25464      * @param right Right position, relative to parent
25465      * @param bottom Bottom position, relative to parent
25466      */
onLayout(boolean changed, int left, int top, int right, int bottom)25467     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
25468     }
25469 
25470     /**
25471      * Assign a size and position to this view.
25472      *
25473      * This is called from layout.
25474      *
25475      * @param left Left position, relative to parent
25476      * @param top Top position, relative to parent
25477      * @param right Right position, relative to parent
25478      * @param bottom Bottom position, relative to parent
25479      * @return true if the new size and position are different than the
25480      *         previous ones
25481      * {@hide}
25482      */
25483     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)25484     protected boolean setFrame(int left, int top, int right, int bottom) {
25485         boolean changed = false;
25486 
25487         if (DBG) {
25488             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
25489                     + right + "," + bottom + ")");
25490         }
25491 
25492         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
25493             changed = true;
25494 
25495             // Remember our drawn bit
25496             int drawn = mPrivateFlags & PFLAG_DRAWN;
25497 
25498             int oldWidth = mRight - mLeft;
25499             int oldHeight = mBottom - mTop;
25500             int newWidth = right - left;
25501             int newHeight = bottom - top;
25502             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
25503 
25504             // Invalidate our old position
25505             invalidate(sizeChanged);
25506 
25507             mLeft = left;
25508             mTop = top;
25509             mRight = right;
25510             mBottom = bottom;
25511             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
25512 
25513             mPrivateFlags |= PFLAG_HAS_BOUNDS;
25514 
25515 
25516             if (sizeChanged) {
25517                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
25518             }
25519 
25520             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
25521                 // If we are visible, force the DRAWN bit to on so that
25522                 // this invalidate will go through (at least to our parent).
25523                 // This is because someone may have invalidated this view
25524                 // before this call to setFrame came in, thereby clearing
25525                 // the DRAWN bit.
25526                 mPrivateFlags |= PFLAG_DRAWN;
25527                 invalidate(sizeChanged);
25528                 // parent display list may need to be recreated based on a change in the bounds
25529                 // of any child
25530                 invalidateParentCaches();
25531             }
25532 
25533             // Reset drawn bit to original value (invalidate turns it off)
25534             mPrivateFlags |= drawn;
25535 
25536             mBackgroundSizeChanged = true;
25537             mDefaultFocusHighlightSizeChanged = true;
25538             if (mForegroundInfo != null) {
25539                 mForegroundInfo.mBoundsChanged = true;
25540             }
25541 
25542             notifySubtreeAccessibilityStateChangedIfNeeded();
25543         }
25544         return changed;
25545     }
25546 
25547     /**
25548      * Assign a size and position to this view.
25549      *
25550      * This method is meant to be used in animations only as it applies this position and size
25551      * for the view only temporary and it can be changed back at any time by the layout.
25552      *
25553      * @param left Left position, relative to parent
25554      * @param top Top position, relative to parent
25555      * @param right Right position, relative to parent
25556      * @param bottom Bottom position, relative to parent
25557      *
25558      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
25559      */
setLeftTopRightBottom(int left, int top, int right, int bottom)25560     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
25561         setFrame(left, top, right, bottom);
25562     }
25563 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)25564     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
25565         if (mAttachInfo != null && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
25566             boolean isSmall;
25567             if (sToolkitFrameRateSmallUsesPercentReadOnlyFlagValue) {
25568                 int size = newWidth * newHeight;
25569                 float percent = size / mAttachInfo.mDisplayPixelCount;
25570                 isSmall = percent <= FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD;
25571             } else {
25572                 float density = mAttachInfo.mDensity;
25573                 int narrowSize = (int) (density * FRAME_RATE_NARROW_SIZE_DP);
25574                 int smallSize = (int) (density * FRAME_RATE_SQUARE_SMALL_SIZE_DP);
25575                 isSmall = newWidth <= narrowSize || newHeight <= narrowSize
25576                         || (newWidth <= smallSize && newHeight <= smallSize);
25577             }
25578             if (isSmall) {
25579                 int category = sToolkitFrameRateBySizeReadOnlyFlagValue
25580                         ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
25581                 mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_SMALL;
25582             } else {
25583                 int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
25584                         ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
25585                 mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_LARGE;
25586             }
25587         }
25588 
25589         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
25590         if (mOverlay != null) {
25591             mOverlay.getOverlayView().setRight(newWidth);
25592             mOverlay.getOverlayView().setBottom(newHeight);
25593         }
25594         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
25595         // backtracking" of requestFocus during layout, so don't touch focus here.
25596         if (!sCanFocusZeroSized && isLayoutValid()
25597                 // Don't touch focus if animating
25598                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
25599             if (newWidth <= 0 || newHeight <= 0) {
25600                 if (hasFocus()) {
25601                     clearFocus();
25602                     if (mParent instanceof ViewGroup) {
25603                         ((ViewGroup) mParent).clearFocusedInCluster();
25604                     }
25605                 }
25606                 clearAccessibilityFocus();
25607             } else if (oldWidth <= 0 || oldHeight <= 0) {
25608                 if (mParent != null && canTakeFocus()) {
25609                     mParent.focusableViewAvailable(this);
25610                 }
25611             }
25612         }
25613         rebuildOutline();
25614         if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
25615             setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
25616         }
25617     }
25618 
25619     /**
25620      * Finalize inflating a view from XML.  This is called as the last phase
25621      * of inflation, after all child views have been added.
25622      *
25623      * <p>Even if the subclass overrides onFinishInflate, they should always be
25624      * sure to call the super method, so that we get called.
25625      */
25626     @CallSuper
onFinishInflate()25627     protected void onFinishInflate() {
25628     }
25629 
25630     /**
25631      * Returns the resources associated with this view.
25632      *
25633      * @return Resources object.
25634      */
getResources()25635     public Resources getResources() {
25636         return mResources;
25637     }
25638 
25639     /**
25640      * Invalidates the specified Drawable.
25641      *
25642      * @param drawable the drawable to invalidate
25643      */
25644     @Override
invalidateDrawable(@onNull Drawable drawable)25645     public void invalidateDrawable(@NonNull Drawable drawable) {
25646         if (verifyDrawable(drawable)) {
25647             final Rect dirty = drawable.getDirtyBounds();
25648             final int scrollX = mScrollX;
25649             final int scrollY = mScrollY;
25650 
25651             invalidate(dirty.left + scrollX, dirty.top + scrollY,
25652                     dirty.right + scrollX, dirty.bottom + scrollY);
25653             rebuildOutline();
25654         }
25655     }
25656 
25657     /**
25658      * Schedules an action on a drawable to occur at a specified time.
25659      *
25660      * @param who the recipient of the action
25661      * @param what the action to run on the drawable
25662      * @param when the time at which the action must occur. Uses the
25663      *        {@link SystemClock#uptimeMillis} timebase.
25664      */
25665     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)25666     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
25667         if (verifyDrawable(who) && what != null) {
25668             final long delay = when - SystemClock.uptimeMillis();
25669             if (mAttachInfo != null) {
25670                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
25671                         Choreographer.CALLBACK_ANIMATION, what, who,
25672                         Choreographer.subtractFrameDelay(delay));
25673             } else {
25674                 // Postpone the runnable until we know
25675                 // on which thread it needs to run.
25676                 getRunQueue().postDelayed(what, delay);
25677             }
25678         }
25679     }
25680 
25681     /**
25682      * Cancels a scheduled action on a drawable.
25683      *
25684      * @param who the recipient of the action
25685      * @param what the action to cancel
25686      */
25687     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)25688     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
25689         if (verifyDrawable(who) && what != null) {
25690             if (mAttachInfo != null) {
25691                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
25692                         Choreographer.CALLBACK_ANIMATION, what, who);
25693             }
25694             getRunQueue().removeCallbacks(what);
25695         }
25696     }
25697 
25698     /**
25699      * Unschedule any events associated with the given Drawable.  This can be
25700      * used when selecting a new Drawable into a view, so that the previous
25701      * one is completely unscheduled.
25702      *
25703      * @param who The Drawable to unschedule.
25704      *
25705      * @see #drawableStateChanged
25706      */
unscheduleDrawable(Drawable who)25707     public void unscheduleDrawable(Drawable who) {
25708         if (mAttachInfo != null && who != null) {
25709             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
25710                     Choreographer.CALLBACK_ANIMATION, null, who);
25711         }
25712     }
25713 
25714     /**
25715      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
25716      * that the View directionality can and will be resolved before its Drawables.
25717      *
25718      * Will call {@link View#onResolveDrawables} when resolution is done.
25719      *
25720      * @hide
25721      */
resolveDrawables()25722     protected void resolveDrawables() {
25723         // Drawables resolution may need to happen before resolving the layout direction (which is
25724         // done only during the measure() call).
25725         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
25726         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
25727         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
25728         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
25729         // direction to be resolved as its resolved value will be the same as its raw value.
25730         if (!isLayoutDirectionResolved() &&
25731                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
25732             return;
25733         }
25734 
25735         final int layoutDirection = isLayoutDirectionResolved() ?
25736                 getLayoutDirection() : getRawLayoutDirection();
25737 
25738         if (mBackground != null) {
25739             mBackground.setLayoutDirection(layoutDirection);
25740         }
25741         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
25742             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
25743         }
25744         if (mDefaultFocusHighlight != null) {
25745             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
25746         }
25747         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
25748         onResolveDrawables(layoutDirection);
25749     }
25750 
areDrawablesResolved()25751     boolean areDrawablesResolved() {
25752         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
25753     }
25754 
25755     /**
25756      * Called when layout direction has been resolved.
25757      *
25758      * The default implementation does nothing.
25759      *
25760      * @param layoutDirection The resolved layout direction.
25761      *
25762      * @see #LAYOUT_DIRECTION_LTR
25763      * @see #LAYOUT_DIRECTION_RTL
25764      *
25765      * @hide
25766      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)25767     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
25768     }
25769 
25770     /**
25771      * @hide
25772      */
25773     @TestApi
resetResolvedDrawables()25774     protected void resetResolvedDrawables() {
25775         resetResolvedDrawablesInternal();
25776     }
25777 
resetResolvedDrawablesInternal()25778     void resetResolvedDrawablesInternal() {
25779         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
25780     }
25781 
25782     /**
25783      * If your view subclass is displaying its own Drawable objects, it should
25784      * override this function and return true for any Drawable it is
25785      * displaying.  This allows animations for those drawables to be
25786      * scheduled.
25787      *
25788      * <p>Be sure to call through to the super class when overriding this
25789      * function.
25790      *
25791      * @param who The Drawable to verify.  Return true if it is one you are
25792      *            displaying, else return the result of calling through to the
25793      *            super class.
25794      *
25795      * @return boolean If true then the Drawable is being displayed in the
25796      *         view; else false and it is not allowed to animate.
25797      *
25798      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
25799      * @see #drawableStateChanged()
25800      */
25801     @CallSuper
verifyDrawable(@onNull Drawable who)25802     protected boolean verifyDrawable(@NonNull Drawable who) {
25803         // Avoid verifying the scroll bar drawable so that we don't end up in
25804         // an invalidation loop. This effectively prevents the scroll bar
25805         // drawable from triggering invalidations and scheduling runnables.
25806         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
25807                 || (mDefaultFocusHighlight == who);
25808     }
25809 
25810     /**
25811      * This function is called whenever the state of the view changes in such
25812      * a way that it impacts the state of drawables being shown.
25813      * <p>
25814      * If the View has a StateListAnimator, it will also be called to run necessary state
25815      * change animations.
25816      * <p>
25817      * Be sure to call through to the superclass when overriding this function.
25818      *
25819      * @see Drawable#setState(int[])
25820      */
25821     @CallSuper
drawableStateChanged()25822     protected void drawableStateChanged() {
25823         final int[] state = getDrawableState();
25824         boolean changed = false;
25825 
25826         final Drawable bg = mBackground;
25827         if (bg != null && bg.isStateful()) {
25828             changed |= bg.setState(state);
25829         }
25830 
25831         final Drawable hl = mDefaultFocusHighlight;
25832         if (hl != null && hl.isStateful()) {
25833             changed |= hl.setState(state);
25834         }
25835 
25836         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
25837         if (fg != null && fg.isStateful()) {
25838             changed |= fg.setState(state);
25839         }
25840 
25841         if (mScrollCache != null) {
25842             final Drawable scrollBar = mScrollCache.scrollBar;
25843             if (scrollBar != null && scrollBar.isStateful()) {
25844                 changed |= scrollBar.setState(state)
25845                         && mScrollCache.state != ScrollabilityCache.OFF;
25846             }
25847         }
25848 
25849         if (mStateListAnimator != null) {
25850             mStateListAnimator.setState(state);
25851         }
25852 
25853         if (!isAggregatedVisible()) {
25854             // If we're not visible, skip any animated changes
25855             jumpDrawablesToCurrentState();
25856         }
25857 
25858         if (changed) {
25859             invalidate();
25860         }
25861     }
25862 
25863     /**
25864      * This function is called whenever the view hotspot changes and needs to
25865      * be propagated to drawables or child views managed by the view.
25866      * <p>
25867      * Dispatching to child views is handled by
25868      * {@link #dispatchDrawableHotspotChanged(float, float)}.
25869      * <p>
25870      * Be sure to call through to the superclass when overriding this function.
25871      *
25872      * @param x hotspot x coordinate
25873      * @param y hotspot y coordinate
25874      */
25875     @CallSuper
drawableHotspotChanged(float x, float y)25876     public void drawableHotspotChanged(float x, float y) {
25877         if (mBackground != null) {
25878             mBackground.setHotspot(x, y);
25879         }
25880         if (mDefaultFocusHighlight != null) {
25881             mDefaultFocusHighlight.setHotspot(x, y);
25882         }
25883         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
25884             mForegroundInfo.mDrawable.setHotspot(x, y);
25885         }
25886 
25887         dispatchDrawableHotspotChanged(x, y);
25888     }
25889 
25890     /**
25891      * Dispatches drawableHotspotChanged to all of this View's children.
25892      *
25893      * @param x hotspot x coordinate
25894      * @param y hotspot y coordinate
25895      * @see #drawableHotspotChanged(float, float)
25896      */
dispatchDrawableHotspotChanged(float x, float y)25897     public void dispatchDrawableHotspotChanged(float x, float y) {
25898     }
25899 
25900     /**
25901      * Call this to force a view to update its drawable state. This will cause
25902      * drawableStateChanged to be called on this view. Views that are interested
25903      * in the new state should call getDrawableState.
25904      *
25905      * @see #drawableStateChanged
25906      * @see #getDrawableState
25907      */
refreshDrawableState()25908     public void refreshDrawableState() {
25909         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
25910         drawableStateChanged();
25911 
25912         ViewParent parent = mParent;
25913         if (parent != null) {
25914             parent.childDrawableStateChanged(this);
25915         }
25916     }
25917 
25918     /**
25919      * Create a default focus highlight if it doesn't exist.
25920      * @return a default focus highlight.
25921      */
getDefaultFocusHighlightDrawable()25922     private Drawable getDefaultFocusHighlightDrawable() {
25923         if (mDefaultFocusHighlightCache == null) {
25924             if (mContext != null) {
25925                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
25926                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
25927                 mDefaultFocusHighlightCache = ta.getDrawable(0);
25928                 ta.recycle();
25929             }
25930         }
25931         return mDefaultFocusHighlightCache;
25932     }
25933 
25934     /**
25935      * Set the current default focus highlight.
25936      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
25937      */
setDefaultFocusHighlight(Drawable highlight)25938     private void setDefaultFocusHighlight(Drawable highlight) {
25939         mDefaultFocusHighlight = highlight;
25940         mDefaultFocusHighlightSizeChanged = true;
25941         if (highlight != null) {
25942             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
25943                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
25944             }
25945             highlight.setLayoutDirection(getLayoutDirection());
25946             if (highlight.isStateful()) {
25947                 highlight.setState(getDrawableState());
25948             }
25949             if (isAttachedToWindow()) {
25950                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
25951             }
25952             // Set callback last, since the view may still be initializing.
25953             highlight.setCallback(this);
25954         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
25955                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
25956             mPrivateFlags |= PFLAG_SKIP_DRAW;
25957         }
25958         invalidate();
25959     }
25960 
25961     /**
25962      * Check whether we need to draw a default focus highlight when this view gets focused,
25963      * which requires:
25964      * <ul>
25965      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
25966      *         is not defined.</li>
25967      *     <li>This view is not in touch mode.</li>
25968      *     <li>This view doesn't opt out for a default focus highlight, via
25969      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
25970      *     <li>This view is attached to window.</li>
25971      * </ul>
25972      * @return {@code true} if a default focus highlight is needed.
25973      * @hide
25974      */
25975     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)25976     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
25977         final boolean lackFocusState = (background == null || !background.isStateful()
25978                 || !background.hasFocusStateSpecified())
25979                 && (foreground == null || !foreground.isStateful()
25980                 || !foreground.hasFocusStateSpecified());
25981         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
25982                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
25983     }
25984 
25985     /**
25986      * When this view is focused, switches on/off the default focused highlight.
25987      * <p>
25988      * This always happens when this view is focused, and only at this moment the default focus
25989      * highlight can be visible.
25990      */
switchDefaultFocusHighlight()25991     private void switchDefaultFocusHighlight() {
25992         if (isFocused()) {
25993             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
25994                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
25995             final boolean active = mDefaultFocusHighlight != null;
25996             if (needed && !active) {
25997                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
25998             } else if (!needed && active) {
25999                 // The highlight is no longer needed, so tear it down.
26000                 setDefaultFocusHighlight(null);
26001             }
26002         }
26003     }
26004 
26005     /**
26006      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
26007      * @param canvas the canvas where we're drawing the highlight.
26008      */
drawDefaultFocusHighlight(@onNull Canvas canvas)26009     private void drawDefaultFocusHighlight(@NonNull Canvas canvas) {
26010         if (mDefaultFocusHighlight != null && isFocused()) {
26011             if (mDefaultFocusHighlightSizeChanged) {
26012                 mDefaultFocusHighlightSizeChanged = false;
26013                 final int l = mScrollX;
26014                 final int r = l + mRight - mLeft;
26015                 final int t = mScrollY;
26016                 final int b = t + mBottom - mTop;
26017                 mDefaultFocusHighlight.setBounds(l, t, r, b);
26018             }
26019             mDefaultFocusHighlight.draw(canvas);
26020         }
26021     }
26022 
26023     /**
26024      * Return an array of resource IDs of the drawable states representing the
26025      * current state of the view.
26026      *
26027      * @return The current drawable state
26028      *
26029      * @see Drawable#setState(int[])
26030      * @see #drawableStateChanged()
26031      * @see #onCreateDrawableState(int)
26032      */
getDrawableState()26033     public final int[] getDrawableState() {
26034         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
26035             return mDrawableState;
26036         } else {
26037             mDrawableState = onCreateDrawableState(0);
26038             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
26039             return mDrawableState;
26040         }
26041     }
26042 
26043     /**
26044      * Generate the new {@link android.graphics.drawable.Drawable} state for
26045      * this view. This is called by the view
26046      * system when the cached Drawable state is determined to be invalid.  To
26047      * retrieve the current state, you should use {@link #getDrawableState}.
26048      *
26049      * @param extraSpace if non-zero, this is the number of extra entries you
26050      * would like in the returned array in which you can place your own
26051      * states.
26052      *
26053      * @return Returns an array holding the current {@link Drawable} state of
26054      * the view.
26055      *
26056      * @see #mergeDrawableStates(int[], int[])
26057      */
onCreateDrawableState(int extraSpace)26058     protected int[] onCreateDrawableState(int extraSpace) {
26059         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
26060                 mParent instanceof View) {
26061             return ((View) mParent).onCreateDrawableState(extraSpace);
26062         }
26063 
26064         int[] drawableState;
26065 
26066         int privateFlags = mPrivateFlags;
26067 
26068         int viewStateIndex = 0;
26069         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
26070         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
26071         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
26072         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
26073         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
26074         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
26075         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
26076             // This is set if HW acceleration is requested, even if the current
26077             // process doesn't allow it.  This is just to allow app preview
26078             // windows to better match their app.
26079             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
26080         }
26081         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
26082 
26083         final int privateFlags2 = mPrivateFlags2;
26084         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
26085             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
26086         }
26087         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
26088             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
26089         }
26090 
26091         drawableState = StateSet.get(viewStateIndex);
26092 
26093         //noinspection ConstantIfStatement
26094         if (false) {
26095             Log.i("View", "drawableStateIndex=" + viewStateIndex);
26096             Log.i("View", toString()
26097                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
26098                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
26099                     + " fo=" + hasFocus()
26100                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
26101                     + " wf=" + hasWindowFocus()
26102                     + ": " + Arrays.toString(drawableState));
26103         }
26104 
26105         if (extraSpace == 0) {
26106             return drawableState;
26107         }
26108 
26109         final int[] fullState;
26110         if (drawableState != null) {
26111             fullState = new int[drawableState.length + extraSpace];
26112             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
26113         } else {
26114             fullState = new int[extraSpace];
26115         }
26116 
26117         return fullState;
26118     }
26119 
26120     /**
26121      * Merge your own state values in <var>additionalState</var> into the base
26122      * state values <var>baseState</var> that were returned by
26123      * {@link #onCreateDrawableState(int)}.
26124      *
26125      * @param baseState The base state values returned by
26126      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
26127      * own additional state values.
26128      *
26129      * @param additionalState The additional state values you would like
26130      * added to <var>baseState</var>; this array is not modified.
26131      *
26132      * @return As a convenience, the <var>baseState</var> array you originally
26133      * passed into the function is returned.
26134      *
26135      * @see #onCreateDrawableState(int)
26136      */
mergeDrawableStates(int[] baseState, int[] additionalState)26137     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
26138         final int N = baseState.length;
26139         int i = N - 1;
26140         while (i >= 0 && baseState[i] == 0) {
26141             i--;
26142         }
26143         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
26144         return baseState;
26145     }
26146 
26147     /**
26148      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
26149      * on all Drawable objects associated with this view.
26150      * <p>
26151      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
26152      * attached to this view.
26153      */
26154     @CallSuper
jumpDrawablesToCurrentState()26155     public void jumpDrawablesToCurrentState() {
26156         if (mBackground != null) {
26157             mBackground.jumpToCurrentState();
26158         }
26159         if (mStateListAnimator != null) {
26160             mStateListAnimator.jumpToCurrentState();
26161         }
26162         if (mDefaultFocusHighlight != null) {
26163             mDefaultFocusHighlight.jumpToCurrentState();
26164         }
26165         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
26166             mForegroundInfo.mDrawable.jumpToCurrentState();
26167         }
26168     }
26169 
26170     /**
26171      * Sets the background color for this view.
26172      * @param color the color of the background
26173      */
26174     @RemotableViewMethod
setBackgroundColor(@olorInt int color)26175     public void setBackgroundColor(@ColorInt int color) {
26176         if (mBackground instanceof ColorDrawable) {
26177             ((ColorDrawable) mBackground.mutate()).setColor(color);
26178             computeOpaqueFlags();
26179             mBackgroundResource = 0;
26180         } else {
26181             setBackground(new ColorDrawable(color));
26182         }
26183     }
26184 
26185     /**
26186      * Set the background to a given resource. The resource should refer to
26187      * a Drawable object or 0 to remove the background.
26188      * @param resid The identifier of the resource.
26189      *
26190      * @attr ref android.R.styleable#View_background
26191      */
26192     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)26193     public void setBackgroundResource(@DrawableRes int resid) {
26194         if (resid != 0 && resid == mBackgroundResource) {
26195             return;
26196         }
26197 
26198         Drawable d = null;
26199         if (resid != 0) {
26200             d = mContext.getDrawable(resid);
26201         }
26202         setBackground(d);
26203 
26204         mBackgroundResource = resid;
26205     }
26206 
26207     /**
26208      * Set the background to a given Drawable, or remove the background. If the
26209      * background has padding, this View's padding is set to the background's
26210      * padding. However, when a background is removed, this View's padding isn't
26211      * touched. If setting the padding is desired, please use
26212      * {@link #setPadding(int, int, int, int)}.
26213      *
26214      * @param background The Drawable to use as the background, or null to remove the
26215      *        background
26216      */
setBackground(Drawable background)26217     public void setBackground(Drawable background) {
26218         //noinspection deprecation
26219         setBackgroundDrawable(background);
26220     }
26221 
26222     /**
26223      * @deprecated use {@link #setBackground(Drawable)} instead
26224      */
26225     @Deprecated
setBackgroundDrawable(Drawable background)26226     public void setBackgroundDrawable(Drawable background) {
26227         computeOpaqueFlags();
26228 
26229         if (background == mBackground) {
26230             return;
26231         }
26232 
26233         boolean requestLayout = false;
26234 
26235         mBackgroundResource = 0;
26236 
26237         /*
26238          * Regardless of whether we're setting a new background or not, we want
26239          * to clear the previous drawable. setVisible first while we still have the callback set.
26240          */
26241         if (mBackground != null) {
26242             if (isAttachedToWindow()) {
26243                 mBackground.setVisible(false, false);
26244             }
26245             mBackground.setCallback(null);
26246             unscheduleDrawable(mBackground);
26247         }
26248 
26249         if (background != null) {
26250             Rect padding = sThreadLocal.get();
26251             if (padding == null) {
26252                 padding = new Rect();
26253                 sThreadLocal.set(padding);
26254             }
26255             resetResolvedDrawablesInternal();
26256             background.setLayoutDirection(getLayoutDirection());
26257             if (background.getPadding(padding)) {
26258                 resetResolvedPaddingInternal();
26259                 switch (background.getLayoutDirection()) {
26260                     case LAYOUT_DIRECTION_RTL:
26261                         mUserPaddingLeftInitial = padding.right;
26262                         mUserPaddingRightInitial = padding.left;
26263                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
26264                         break;
26265                     case LAYOUT_DIRECTION_LTR:
26266                     default:
26267                         mUserPaddingLeftInitial = padding.left;
26268                         mUserPaddingRightInitial = padding.right;
26269                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
26270                 }
26271                 mLeftPaddingDefined = false;
26272                 mRightPaddingDefined = false;
26273             }
26274 
26275             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
26276             // if it has a different minimum size, we should layout again
26277             if (mBackground == null
26278                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
26279                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
26280                 requestLayout = true;
26281             }
26282 
26283             // Set mBackground before we set this as the callback and start making other
26284             // background drawable state change calls. In particular, the setVisible call below
26285             // can result in drawables attempting to start animations or otherwise invalidate,
26286             // which requires the view set as the callback (us) to recognize the drawable as
26287             // belonging to it as per verifyDrawable.
26288             mBackground = background;
26289             if (background.isStateful()) {
26290                 background.setState(getDrawableState());
26291             }
26292             if (isAttachedToWindow()) {
26293                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
26294             }
26295 
26296             applyBackgroundTint();
26297 
26298             // Set callback last, since the view may still be initializing.
26299             background.setCallback(this);
26300 
26301             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
26302                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
26303                 requestLayout = true;
26304             }
26305         } else {
26306             /* Remove the background */
26307             mBackground = null;
26308             if ((mViewFlags & WILL_NOT_DRAW) != 0
26309                     && (mDefaultFocusHighlight == null)
26310                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
26311                 mPrivateFlags |= PFLAG_SKIP_DRAW;
26312             }
26313 
26314             /*
26315              * When the background is set, we try to apply its padding to this
26316              * View. When the background is removed, we don't touch this View's
26317              * padding. This is noted in the Javadocs. Hence, we don't need to
26318              * requestLayout(), the invalidate() below is sufficient.
26319              */
26320 
26321             // The old background's minimum size could have affected this
26322             // View's layout, so let's requestLayout
26323             requestLayout = true;
26324         }
26325 
26326         computeOpaqueFlags();
26327 
26328         if (requestLayout) {
26329             requestLayout();
26330         }
26331 
26332         mBackgroundSizeChanged = true;
26333         invalidate(true);
26334         invalidateOutline();
26335     }
26336 
26337     /**
26338      * Gets the background drawable
26339      *
26340      * @return The drawable used as the background for this view, if any.
26341      *
26342      * @see #setBackground(Drawable)
26343      *
26344      * @attr ref android.R.styleable#View_background
26345      */
26346     @InspectableProperty
getBackground()26347     public Drawable getBackground() {
26348         return mBackground;
26349     }
26350 
26351     /**
26352      * Applies a tint to the background drawable. Does not modify the current tint
26353      * mode, which is {@link BlendMode#SRC_IN} by default.
26354      * <p>
26355      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
26356      * mutate the drawable and apply the specified tint and tint mode using
26357      * {@link Drawable#setTintList(ColorStateList)}.
26358      *
26359      * @param tint the tint to apply, may be {@code null} to clear tint
26360      *
26361      * @attr ref android.R.styleable#View_backgroundTint
26362      * @see #getBackgroundTintList()
26363      * @see Drawable#setTintList(ColorStateList)
26364      */
26365     @RemotableViewMethod
setBackgroundTintList(@ullable ColorStateList tint)26366     public void setBackgroundTintList(@Nullable ColorStateList tint) {
26367         if (mBackgroundTint == null) {
26368             mBackgroundTint = new TintInfo();
26369         }
26370         mBackgroundTint.mTintList = tint;
26371         mBackgroundTint.mHasTintList = true;
26372 
26373         applyBackgroundTint();
26374     }
26375 
26376     /**
26377      * Return the tint applied to the background drawable, if specified.
26378      *
26379      * @return the tint applied to the background drawable
26380      * @attr ref android.R.styleable#View_backgroundTint
26381      * @see #setBackgroundTintList(ColorStateList)
26382      */
26383     @InspectableProperty(name = "backgroundTint")
26384     @Nullable
getBackgroundTintList()26385     public ColorStateList getBackgroundTintList() {
26386         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
26387     }
26388 
26389     /**
26390      * Specifies the blending mode used to apply the tint specified by
26391      * {@link #setBackgroundTintList(ColorStateList)}} to the background
26392      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
26393      *
26394      * @param tintMode the blending mode used to apply the tint, may be
26395      *                 {@code null} to clear tint
26396      * @attr ref android.R.styleable#View_backgroundTintMode
26397      * @see #getBackgroundTintMode()
26398      * @see Drawable#setTintMode(PorterDuff.Mode)
26399      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)26400     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
26401         BlendMode mode = null;
26402         if (tintMode != null) {
26403             mode = BlendMode.fromValue(tintMode.nativeInt);
26404         }
26405 
26406         setBackgroundTintBlendMode(mode);
26407     }
26408 
26409     /**
26410      * Specifies the blending mode used to apply the tint specified by
26411      * {@link #setBackgroundTintList(ColorStateList)}} to the background
26412      * drawable. The default mode is {@link BlendMode#SRC_IN}.
26413      *
26414      * @param blendMode the blending mode used to apply the tint, may be
26415      *                 {@code null} to clear tint
26416      * @attr ref android.R.styleable#View_backgroundTintMode
26417      * @see #getBackgroundTintMode()
26418      * @see Drawable#setTintBlendMode(BlendMode)
26419      */
26420     @RemotableViewMethod
setBackgroundTintBlendMode(@ullable BlendMode blendMode)26421     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
26422         if (mBackgroundTint == null) {
26423             mBackgroundTint = new TintInfo();
26424         }
26425 
26426         mBackgroundTint.mBlendMode = blendMode;
26427         mBackgroundTint.mHasTintMode = true;
26428 
26429         applyBackgroundTint();
26430     }
26431 
26432     /**
26433      * Return the blending mode used to apply the tint to the background
26434      * drawable, if specified.
26435      *
26436      * @return the blending mode used to apply the tint to the background
26437      *         drawable
26438      * @attr ref android.R.styleable#View_backgroundTintMode
26439      * @see #setBackgroundTintBlendMode(BlendMode)
26440      *
26441      */
26442     @Nullable
26443     @InspectableProperty
getBackgroundTintMode()26444     public PorterDuff.Mode getBackgroundTintMode() {
26445         PorterDuff.Mode porterDuffMode;
26446         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
26447             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
26448         } else {
26449             porterDuffMode = null;
26450         }
26451         return porterDuffMode;
26452     }
26453 
26454     /**
26455      * Return the blending mode used to apply the tint to the background
26456      * drawable, if specified.
26457      *
26458      * @return the blending mode used to apply the tint to the background
26459      *         drawable, null if no blend has previously been configured
26460      * @attr ref android.R.styleable#View_backgroundTintMode
26461      * @see #setBackgroundTintBlendMode(BlendMode)
26462      */
getBackgroundTintBlendMode()26463     public @Nullable BlendMode getBackgroundTintBlendMode() {
26464         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
26465     }
26466 
applyBackgroundTint()26467     private void applyBackgroundTint() {
26468         if (mBackground != null && mBackgroundTint != null) {
26469             final TintInfo tintInfo = mBackgroundTint;
26470             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
26471                 mBackground = mBackground.mutate();
26472 
26473                 if (tintInfo.mHasTintList) {
26474                     mBackground.setTintList(tintInfo.mTintList);
26475                 }
26476 
26477                 if (tintInfo.mHasTintMode) {
26478                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
26479                 }
26480 
26481                 // The drawable (or one of its children) may not have been
26482                 // stateful before applying the tint, so let's try again.
26483                 if (mBackground.isStateful()) {
26484                     mBackground.setState(getDrawableState());
26485                 }
26486             }
26487         }
26488     }
26489 
26490     /**
26491      * Returns the drawable used as the foreground of this View. The
26492      * foreground drawable, if non-null, is always drawn on top of the view's content.
26493      *
26494      * @return a Drawable or null if no foreground was set
26495      *
26496      * @see #onDrawForeground(Canvas)
26497      */
26498     @InspectableProperty
getForeground()26499     public Drawable getForeground() {
26500         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
26501     }
26502 
26503     /**
26504      * Supply a Drawable that is to be rendered on top of all of the content in the view.
26505      *
26506      * @param foreground the Drawable to be drawn on top of the children
26507      *
26508      * @attr ref android.R.styleable#View_foreground
26509      */
setForeground(Drawable foreground)26510     public void setForeground(Drawable foreground) {
26511         if (mForegroundInfo == null) {
26512             if (foreground == null) {
26513                 // Nothing to do.
26514                 return;
26515             }
26516             mForegroundInfo = new ForegroundInfo();
26517         }
26518 
26519         if (foreground == mForegroundInfo.mDrawable) {
26520             // Nothing to do
26521             return;
26522         }
26523 
26524         if (mForegroundInfo.mDrawable != null) {
26525             if (isAttachedToWindow()) {
26526                 mForegroundInfo.mDrawable.setVisible(false, false);
26527             }
26528             mForegroundInfo.mDrawable.setCallback(null);
26529             unscheduleDrawable(mForegroundInfo.mDrawable);
26530         }
26531 
26532         mForegroundInfo.mDrawable = foreground;
26533         mForegroundInfo.mBoundsChanged = true;
26534         if (foreground != null) {
26535             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
26536                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
26537             }
26538             foreground.setLayoutDirection(getLayoutDirection());
26539             if (foreground.isStateful()) {
26540                 foreground.setState(getDrawableState());
26541             }
26542             applyForegroundTint();
26543             if (isAttachedToWindow()) {
26544                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
26545             }
26546             // Set callback last, since the view may still be initializing.
26547             foreground.setCallback(this);
26548         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
26549                 && (mDefaultFocusHighlight == null)) {
26550             mPrivateFlags |= PFLAG_SKIP_DRAW;
26551         }
26552         requestLayout();
26553         invalidate();
26554     }
26555 
26556     /**
26557      * Magic bit used to support features of framework-internal window decor implementation details.
26558      * This used to live exclusively in FrameLayout.
26559      *
26560      * @return true if the foreground should draw inside the padding region or false
26561      *         if it should draw inset by the view's padding
26562      * @hide internal use only; only used by FrameLayout and internal screen layouts.
26563      */
isForegroundInsidePadding()26564     public boolean isForegroundInsidePadding() {
26565         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
26566     }
26567 
26568     /**
26569      * Describes how the foreground is positioned.
26570      *
26571      * @return foreground gravity.
26572      *
26573      * @see #setForegroundGravity(int)
26574      *
26575      * @attr ref android.R.styleable#View_foregroundGravity
26576      */
26577     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()26578     public int getForegroundGravity() {
26579         return mForegroundInfo != null ? mForegroundInfo.mGravity
26580                 : Gravity.START | Gravity.TOP;
26581     }
26582 
26583     /**
26584      * Describes how the foreground is positioned. Defaults to START and TOP.
26585      *
26586      * @param gravity see {@link android.view.Gravity}
26587      *
26588      * @see #getForegroundGravity()
26589      *
26590      * @attr ref android.R.styleable#View_foregroundGravity
26591      */
setForegroundGravity(int gravity)26592     public void setForegroundGravity(int gravity) {
26593         if (mForegroundInfo == null) {
26594             mForegroundInfo = new ForegroundInfo();
26595         }
26596 
26597         if (mForegroundInfo.mGravity != gravity) {
26598             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
26599                 gravity |= Gravity.START;
26600             }
26601 
26602             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
26603                 gravity |= Gravity.TOP;
26604             }
26605 
26606             mForegroundInfo.mGravity = gravity;
26607             requestLayout();
26608         }
26609     }
26610 
26611     /**
26612      * Applies a tint to the foreground drawable. Does not modify the current tint
26613      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
26614      * <p>
26615      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
26616      * mutate the drawable and apply the specified tint and tint mode using
26617      * {@link Drawable#setTintList(ColorStateList)}.
26618      *
26619      * @param tint the tint to apply, may be {@code null} to clear tint
26620      *
26621      * @attr ref android.R.styleable#View_foregroundTint
26622      * @see #getForegroundTintList()
26623      * @see Drawable#setTintList(ColorStateList)
26624      */
26625     @RemotableViewMethod
setForegroundTintList(@ullable ColorStateList tint)26626     public void setForegroundTintList(@Nullable ColorStateList tint) {
26627         if (mForegroundInfo == null) {
26628             mForegroundInfo = new ForegroundInfo();
26629         }
26630         if (mForegroundInfo.mTintInfo == null) {
26631             mForegroundInfo.mTintInfo = new TintInfo();
26632         }
26633         mForegroundInfo.mTintInfo.mTintList = tint;
26634         mForegroundInfo.mTintInfo.mHasTintList = true;
26635 
26636         applyForegroundTint();
26637     }
26638 
26639     /**
26640      * Return the tint applied to the foreground drawable, if specified.
26641      *
26642      * @return the tint applied to the foreground drawable
26643      * @attr ref android.R.styleable#View_foregroundTint
26644      * @see #setForegroundTintList(ColorStateList)
26645      */
26646     @InspectableProperty(name = "foregroundTint")
26647     @Nullable
getForegroundTintList()26648     public ColorStateList getForegroundTintList() {
26649         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
26650                 ? mForegroundInfo.mTintInfo.mTintList : null;
26651     }
26652 
26653     /**
26654      * Specifies the blending mode used to apply the tint specified by
26655      * {@link #setForegroundTintList(ColorStateList)}} to the background
26656      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
26657      *
26658      * @param tintMode the blending mode used to apply the tint, may be
26659      *                 {@code null} to clear tint
26660      * @attr ref android.R.styleable#View_foregroundTintMode
26661      * @see #getForegroundTintMode()
26662      * @see Drawable#setTintMode(PorterDuff.Mode)
26663      *
26664      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)26665     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
26666         BlendMode mode = null;
26667         if (tintMode != null) {
26668             mode = BlendMode.fromValue(tintMode.nativeInt);
26669         }
26670         setForegroundTintBlendMode(mode);
26671     }
26672 
26673     /**
26674      * Specifies the blending mode used to apply the tint specified by
26675      * {@link #setForegroundTintList(ColorStateList)}} to the background
26676      * drawable. The default mode is {@link BlendMode#SRC_IN}.
26677      *
26678      * @param blendMode the blending mode used to apply the tint, may be
26679      *                 {@code null} to clear tint
26680      * @attr ref android.R.styleable#View_foregroundTintMode
26681      * @see #getForegroundTintMode()
26682      * @see Drawable#setTintBlendMode(BlendMode)
26683      */
26684     @RemotableViewMethod
setForegroundTintBlendMode(@ullable BlendMode blendMode)26685     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
26686         if (mForegroundInfo == null) {
26687             mForegroundInfo = new ForegroundInfo();
26688         }
26689         if (mForegroundInfo.mTintInfo == null) {
26690             mForegroundInfo.mTintInfo = new TintInfo();
26691         }
26692         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
26693         mForegroundInfo.mTintInfo.mHasTintMode = true;
26694 
26695         applyForegroundTint();
26696     }
26697 
26698     /**
26699      * Return the blending mode used to apply the tint to the foreground
26700      * drawable, if specified.
26701      *
26702      * @return the blending mode used to apply the tint to the foreground
26703      *         drawable
26704      * @attr ref android.R.styleable#View_foregroundTintMode
26705      * @see #setForegroundTintMode(PorterDuff.Mode)
26706      */
26707     @InspectableProperty
26708     @Nullable
getForegroundTintMode()26709     public PorterDuff.Mode getForegroundTintMode() {
26710         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
26711                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
26712         if (blendMode != null) {
26713             return BlendMode.blendModeToPorterDuffMode(blendMode);
26714         } else {
26715             return null;
26716         }
26717     }
26718 
26719     /**
26720      * Return the blending mode used to apply the tint to the foreground
26721      * drawable, if specified.
26722      *
26723      * @return the blending mode used to apply the tint to the foreground
26724      *         drawable
26725      * @attr ref android.R.styleable#View_foregroundTintMode
26726      * @see #setForegroundTintBlendMode(BlendMode)
26727      *
26728      */
getForegroundTintBlendMode()26729     public @Nullable BlendMode getForegroundTintBlendMode() {
26730         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
26731                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
26732     }
26733 
applyForegroundTint()26734     private void applyForegroundTint() {
26735         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
26736                 && mForegroundInfo.mTintInfo != null) {
26737             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
26738             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
26739                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
26740 
26741                 if (tintInfo.mHasTintList) {
26742                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
26743                 }
26744 
26745                 if (tintInfo.mHasTintMode) {
26746                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
26747                 }
26748 
26749                 // The drawable (or one of its children) may not have been
26750                 // stateful before applying the tint, so let's try again.
26751                 if (mForegroundInfo.mDrawable.isStateful()) {
26752                     mForegroundInfo.mDrawable.setState(getDrawableState());
26753                 }
26754             }
26755         }
26756     }
26757 
26758     /**
26759      * Get the drawable to be overlayed when a view is autofilled
26760      *
26761      * @return The drawable
26762      *
26763      * @throws IllegalStateException if the drawable could not be found.
26764      */
getAutofilledDrawable()26765     @Nullable private Drawable getAutofilledDrawable() {
26766         if (mAttachInfo == null) {
26767             return null;
26768         }
26769         // Lazily load the isAutofilled drawable.
26770         if (mAttachInfo.mAutofilledDrawable == null) {
26771             Context rootContext = getRootView().getContext();
26772             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
26773             int attributeResourceId = a.getResourceId(0, 0);
26774             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
26775             a.recycle();
26776         }
26777 
26778         return mAttachInfo.mAutofilledDrawable;
26779     }
26780 
26781     /**
26782      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
26783      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
26784      *
26785      * @param canvas The canvas to draw on
26786      */
drawAutofilledHighlight(@onNull Canvas canvas)26787     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
26788         if (isAutofilled() && !hideAutofillHighlight()) {
26789             Drawable autofilledHighlight = getAutofilledDrawable();
26790 
26791             if (autofilledHighlight != null) {
26792                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
26793                 autofilledHighlight.draw(canvas);
26794             }
26795         }
26796     }
26797 
26798     /**
26799      * Draw any foreground content for this view.
26800      *
26801      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
26802      * drawable or other view-specific decorations. The foreground is drawn on top of the
26803      * primary view content.</p>
26804      *
26805      * @param canvas canvas to draw into
26806      */
onDrawForeground(@onNull Canvas canvas)26807     public void onDrawForeground(@NonNull Canvas canvas) {
26808         onDrawScrollIndicators(canvas);
26809         onDrawScrollBars(canvas);
26810 
26811         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
26812         if (foreground != null) {
26813             if (mForegroundInfo.mBoundsChanged) {
26814                 mForegroundInfo.mBoundsChanged = false;
26815                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
26816                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
26817 
26818                 if (mForegroundInfo.mInsidePadding) {
26819                     selfBounds.set(0, 0, getWidth(), getHeight());
26820                 } else {
26821                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
26822                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
26823                 }
26824 
26825                 final int ld = getLayoutDirection();
26826                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
26827                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
26828                 foreground.setBounds(overlayBounds);
26829             }
26830 
26831             foreground.draw(canvas);
26832         }
26833     }
26834 
26835     /**
26836      * Sets the padding. The view may add on the space required to display
26837      * the scrollbars, depending on the style and visibility of the scrollbars.
26838      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
26839      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
26840      * from the values set in this call.
26841      *
26842      * @attr ref android.R.styleable#View_padding
26843      * @attr ref android.R.styleable#View_paddingBottom
26844      * @attr ref android.R.styleable#View_paddingLeft
26845      * @attr ref android.R.styleable#View_paddingRight
26846      * @attr ref android.R.styleable#View_paddingTop
26847      * @param left the left padding in pixels
26848      * @param top the top padding in pixels
26849      * @param right the right padding in pixels
26850      * @param bottom the bottom padding in pixels
26851      */
setPadding(int left, int top, int right, int bottom)26852     public void setPadding(int left, int top, int right, int bottom) {
26853         resetResolvedPaddingInternal();
26854 
26855         mUserPaddingStart = UNDEFINED_PADDING;
26856         mUserPaddingEnd = UNDEFINED_PADDING;
26857 
26858         mUserPaddingLeftInitial = left;
26859         mUserPaddingRightInitial = right;
26860 
26861         mLeftPaddingDefined = true;
26862         mRightPaddingDefined = true;
26863 
26864         internalSetPadding(left, top, right, bottom);
26865     }
26866 
26867     /**
26868      * @hide
26869      */
26870     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)26871     protected void internalSetPadding(int left, int top, int right, int bottom) {
26872         mUserPaddingLeft = left;
26873         mUserPaddingRight = right;
26874         mUserPaddingBottom = bottom;
26875 
26876         final int viewFlags = mViewFlags;
26877         boolean changed = false;
26878 
26879         // Common case is there are no scroll bars.
26880         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
26881             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
26882                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
26883                         ? 0 : getVerticalScrollbarWidth();
26884                 switch (mVerticalScrollbarPosition) {
26885                     case SCROLLBAR_POSITION_DEFAULT:
26886                         if (isLayoutRtl()) {
26887                             left += offset;
26888                         } else {
26889                             right += offset;
26890                         }
26891                         break;
26892                     case SCROLLBAR_POSITION_RIGHT:
26893                         right += offset;
26894                         break;
26895                     case SCROLLBAR_POSITION_LEFT:
26896                         left += offset;
26897                         break;
26898                 }
26899             }
26900             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
26901                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
26902                         ? 0 : getHorizontalScrollbarHeight();
26903             }
26904         }
26905 
26906         if (mPaddingLeft != left) {
26907             changed = true;
26908             mPaddingLeft = left;
26909         }
26910         if (mPaddingTop != top) {
26911             changed = true;
26912             mPaddingTop = top;
26913         }
26914         if (mPaddingRight != right) {
26915             changed = true;
26916             mPaddingRight = right;
26917         }
26918         if (mPaddingBottom != bottom) {
26919             changed = true;
26920             mPaddingBottom = bottom;
26921         }
26922 
26923         if (changed) {
26924             requestLayout();
26925             invalidateOutline();
26926         }
26927     }
26928 
26929     /**
26930      * Sets the relative padding. The view may add on the space required to display
26931      * the scrollbars, depending on the style and visibility of the scrollbars.
26932      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
26933      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
26934      * from the values set in this call.
26935      *
26936      * @attr ref android.R.styleable#View_padding
26937      * @attr ref android.R.styleable#View_paddingBottom
26938      * @attr ref android.R.styleable#View_paddingStart
26939      * @attr ref android.R.styleable#View_paddingEnd
26940      * @attr ref android.R.styleable#View_paddingTop
26941      * @param start the start padding in pixels
26942      * @param top the top padding in pixels
26943      * @param end the end padding in pixels
26944      * @param bottom the bottom padding in pixels
26945      */
setPaddingRelative(int start, int top, int end, int bottom)26946     public void setPaddingRelative(int start, int top, int end, int bottom) {
26947         resetResolvedPaddingInternal();
26948 
26949         mUserPaddingStart = start;
26950         mUserPaddingEnd = end;
26951         mLeftPaddingDefined = true;
26952         mRightPaddingDefined = true;
26953 
26954         switch(getLayoutDirection()) {
26955             case LAYOUT_DIRECTION_RTL:
26956                 mUserPaddingLeftInitial = end;
26957                 mUserPaddingRightInitial = start;
26958                 internalSetPadding(end, top, start, bottom);
26959                 break;
26960             case LAYOUT_DIRECTION_LTR:
26961             default:
26962                 mUserPaddingLeftInitial = start;
26963                 mUserPaddingRightInitial = end;
26964                 internalSetPadding(start, top, end, bottom);
26965         }
26966     }
26967 
26968     /**
26969      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
26970      * resource ID of the source layout.
26971      *
26972      * @return The layout resource id if this view was inflated from XML, otherwise
26973      * {@link Resources#ID_NULL}.
26974      */
26975     @LayoutRes
getSourceLayoutResId()26976     public int getSourceLayoutResId() {
26977         return mSourceLayoutId;
26978     }
26979 
26980     /**
26981      * Returns the top padding of this view.
26982      *
26983      * @return the top padding in pixels
26984      */
26985     @InspectableProperty
getPaddingTop()26986     public int getPaddingTop() {
26987         return mPaddingTop;
26988     }
26989 
26990     /**
26991      * Returns the bottom padding of this view. If there are inset and enabled
26992      * scrollbars, this value may include the space required to display the
26993      * scrollbars as well.
26994      *
26995      * @return the bottom padding in pixels
26996      */
26997     @InspectableProperty
getPaddingBottom()26998     public int getPaddingBottom() {
26999         return mPaddingBottom;
27000     }
27001 
27002     /**
27003      * Returns the left padding of this view. If there are inset and enabled
27004      * scrollbars, this value may include the space required to display the
27005      * scrollbars as well.
27006      *
27007      * @return the left padding in pixels
27008      */
27009     @InspectableProperty
getPaddingLeft()27010     public int getPaddingLeft() {
27011         if (!isPaddingResolved()) {
27012             resolvePadding();
27013         }
27014         return mPaddingLeft;
27015     }
27016 
27017     /**
27018      * Returns the start padding of this view depending on its resolved layout direction.
27019      * If there are inset and enabled scrollbars, this value may include the space
27020      * required to display the scrollbars as well.
27021      *
27022      * @return the start padding in pixels
27023      */
getPaddingStart()27024     public int getPaddingStart() {
27025         if (!isPaddingResolved()) {
27026             resolvePadding();
27027         }
27028         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
27029                 mPaddingRight : mPaddingLeft;
27030     }
27031 
27032     /**
27033      * Returns the right padding of this view. If there are inset and enabled
27034      * scrollbars, this value may include the space required to display the
27035      * scrollbars as well.
27036      *
27037      * @return the right padding in pixels
27038      */
27039     @InspectableProperty
getPaddingRight()27040     public int getPaddingRight() {
27041         if (!isPaddingResolved()) {
27042             resolvePadding();
27043         }
27044         return mPaddingRight;
27045     }
27046 
27047     /**
27048      * Returns the end padding of this view depending on its resolved layout direction.
27049      * If there are inset and enabled scrollbars, this value may include the space
27050      * required to display the scrollbars as well.
27051      *
27052      * @return the end padding in pixels
27053      */
getPaddingEnd()27054     public int getPaddingEnd() {
27055         if (!isPaddingResolved()) {
27056             resolvePadding();
27057         }
27058         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
27059                 mPaddingLeft : mPaddingRight;
27060     }
27061 
27062     /**
27063      * Return if the padding has been set through relative values
27064      * {@link #setPaddingRelative(int, int, int, int)} or through
27065      * @attr ref android.R.styleable#View_paddingStart or
27066      * @attr ref android.R.styleable#View_paddingEnd
27067      *
27068      * @return true if the padding is relative or false if it is not.
27069      */
isPaddingRelative()27070     public boolean isPaddingRelative() {
27071         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
27072     }
27073 
computeOpticalInsets()27074     Insets computeOpticalInsets() {
27075         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
27076     }
27077 
27078     /**
27079      * @hide
27080      */
27081     @UnsupportedAppUsage
resetPaddingToInitialValues()27082     public void resetPaddingToInitialValues() {
27083         if (isRtlCompatibilityMode()) {
27084             mPaddingLeft = mUserPaddingLeftInitial;
27085             mPaddingRight = mUserPaddingRightInitial;
27086             return;
27087         }
27088         if (isLayoutRtl()) {
27089             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
27090             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
27091         } else {
27092             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
27093             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
27094         }
27095     }
27096 
27097     /**
27098      * @hide
27099      */
getOpticalInsets()27100     public Insets getOpticalInsets() {
27101         if (mLayoutInsets == null) {
27102             mLayoutInsets = computeOpticalInsets();
27103         }
27104         return mLayoutInsets;
27105     }
27106 
27107     /**
27108      * Set this view's optical insets.
27109      *
27110      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
27111      * property. Views that compute their own optical insets should call it as part of measurement.
27112      * This method does not request layout. If you are setting optical insets outside of
27113      * measure/layout itself you will want to call requestLayout() yourself.
27114      * </p>
27115      * @hide
27116      */
setOpticalInsets(Insets insets)27117     public void setOpticalInsets(Insets insets) {
27118         mLayoutInsets = insets;
27119     }
27120 
27121     /**
27122      * Changes the selection state of this view. A view can be selected or not.
27123      * Note that selection is not the same as focus. Views are typically
27124      * selected in the context of an AdapterView like ListView or GridView;
27125      * the selected view is the view that is highlighted.
27126      *
27127      * @param selected true if the view must be selected, false otherwise
27128      */
setSelected(boolean selected)27129     public void setSelected(boolean selected) {
27130         //noinspection DoubleNegation
27131         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
27132             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
27133             if (!selected) resetPressedState();
27134             invalidate(true);
27135             refreshDrawableState();
27136             dispatchSetSelected(selected);
27137             if (selected) {
27138                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
27139             } else {
27140                 notifyViewAccessibilityStateChangedIfNeeded(
27141                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
27142             }
27143         }
27144     }
27145 
27146     /**
27147      * Dispatch setSelected to all of this View's children.
27148      *
27149      * @see #setSelected(boolean)
27150      *
27151      * @param selected The new selected state
27152      */
dispatchSetSelected(boolean selected)27153     protected void dispatchSetSelected(boolean selected) {
27154     }
27155 
27156     /**
27157      * Indicates the selection state of this view.
27158      *
27159      * @return true if the view is selected, false otherwise
27160      */
27161     @ViewDebug.ExportedProperty
27162     @InspectableProperty(hasAttributeId = false)
isSelected()27163     public boolean isSelected() {
27164         return (mPrivateFlags & PFLAG_SELECTED) != 0;
27165     }
27166 
27167     /**
27168      * Changes the activated state of this view. A view can be activated or not.
27169      * Note that activation is not the same as selection.  Selection is
27170      * a transient property, representing the view (hierarchy) the user is
27171      * currently interacting with.  Activation is a longer-term state that the
27172      * user can move views in and out of.  For example, in a list view with
27173      * single or multiple selection enabled, the views in the current selection
27174      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
27175      * here.)  The activated state is propagated down to children of the view it
27176      * is set on.
27177      *
27178      * @param activated true if the view must be activated, false otherwise
27179      */
setActivated(boolean activated)27180     public void setActivated(boolean activated) {
27181         //noinspection DoubleNegation
27182         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
27183             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
27184             invalidate(true);
27185             refreshDrawableState();
27186             dispatchSetActivated(activated);
27187         }
27188     }
27189 
27190     /**
27191      * Dispatch setActivated to all of this View's children.
27192      *
27193      * @see #setActivated(boolean)
27194      *
27195      * @param activated The new activated state
27196      */
dispatchSetActivated(boolean activated)27197     protected void dispatchSetActivated(boolean activated) {
27198     }
27199 
27200     /**
27201      * Indicates the activation state of this view.
27202      *
27203      * @return true if the view is activated, false otherwise
27204      */
27205     @ViewDebug.ExportedProperty
27206     @InspectableProperty(hasAttributeId = false)
isActivated()27207     public boolean isActivated() {
27208         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
27209     }
27210 
27211     /**
27212      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
27213      * observer can be used to get notifications when global events, like
27214      * layout, happen.
27215      *
27216      * The returned ViewTreeObserver observer is not guaranteed to remain
27217      * valid for the lifetime of this View. If the caller of this method keeps
27218      * a long-lived reference to ViewTreeObserver, it should always check for
27219      * the return value of {@link ViewTreeObserver#isAlive()}.
27220      *
27221      * @return The ViewTreeObserver for this view's hierarchy.
27222      */
getViewTreeObserver()27223     public ViewTreeObserver getViewTreeObserver() {
27224         if (mAttachInfo != null) {
27225             return mAttachInfo.mTreeObserver;
27226         }
27227         if (mFloatingTreeObserver == null) {
27228             mFloatingTreeObserver = new ViewTreeObserver(mContext);
27229         }
27230         return mFloatingTreeObserver;
27231     }
27232 
27233     /**
27234      * <p>Finds the topmost view in the current view hierarchy.</p>
27235      *
27236      * @return the topmost view containing this view
27237      */
getRootView()27238     public View getRootView() {
27239         if (mAttachInfo != null) {
27240             final View v = mAttachInfo.mRootView;
27241             if (v != null) {
27242                 return v;
27243             }
27244         }
27245 
27246         View parent = this;
27247 
27248         while (parent.mParent instanceof View) {
27249             parent = (View) parent.mParent;
27250         }
27251 
27252         return parent;
27253     }
27254 
27255     /**
27256      * Transforms a motion event from view-local coordinates to on-screen
27257      * coordinates.
27258      *
27259      * @param ev the view-local motion event
27260      * @return false if the transformation could not be applied
27261      * @hide
27262      */
27263     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toGlobalMotionEvent(MotionEvent ev)27264     public boolean toGlobalMotionEvent(MotionEvent ev) {
27265         final AttachInfo info = mAttachInfo;
27266         if (info == null) {
27267             return false;
27268         }
27269 
27270         final Matrix m = info.mTmpMatrix;
27271         m.set(Matrix.IDENTITY_MATRIX);
27272         transformMatrixToGlobal(m);
27273         ev.transform(m);
27274         return true;
27275     }
27276 
27277     /**
27278      * Transforms a motion event from on-screen coordinates to view-local
27279      * coordinates.
27280      *
27281      * @param ev the on-screen motion event
27282      * @return false if the transformation could not be applied
27283      * @hide
27284      */
27285     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toLocalMotionEvent(MotionEvent ev)27286     public boolean toLocalMotionEvent(MotionEvent ev) {
27287         final AttachInfo info = mAttachInfo;
27288         if (info == null) {
27289             return false;
27290         }
27291 
27292         final Matrix m = info.mTmpMatrix;
27293         m.set(Matrix.IDENTITY_MATRIX);
27294         transformMatrixToLocal(m);
27295         ev.transform(m);
27296         return true;
27297     }
27298 
27299     /**
27300      * Modifies the input matrix such that it maps view-local coordinates to
27301      * on-screen coordinates.
27302      *
27303      * @param matrix input matrix to modify
27304      */
transformMatrixToGlobal(@onNull Matrix matrix)27305     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
27306         final ViewParent parent = mParent;
27307         if (parent instanceof View) {
27308             final View vp = (View) parent;
27309             vp.transformMatrixToGlobal(matrix);
27310             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
27311         } else if (parent instanceof ViewRootImpl) {
27312             final ViewRootImpl vr = (ViewRootImpl) parent;
27313             vr.transformMatrixToGlobal(matrix);
27314             matrix.preTranslate(0, -vr.mCurScrollY);
27315         }
27316 
27317         matrix.preTranslate(mLeft, mTop);
27318 
27319         if (!hasIdentityMatrix()) {
27320             matrix.preConcat(getMatrix());
27321         }
27322     }
27323 
27324     /**
27325      * Modifies the input matrix such that it maps on-screen coordinates to
27326      * view-local coordinates.
27327      *
27328      * @param matrix input matrix to modify
27329      */
transformMatrixToLocal(@onNull Matrix matrix)27330     public void transformMatrixToLocal(@NonNull Matrix matrix) {
27331         final ViewParent parent = mParent;
27332         if (parent instanceof View) {
27333             final View vp = (View) parent;
27334             vp.transformMatrixToLocal(matrix);
27335             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
27336         } else if (parent instanceof ViewRootImpl) {
27337             final ViewRootImpl vr = (ViewRootImpl) parent;
27338             vr.transformMatrixToLocal(matrix);
27339             matrix.postTranslate(0, vr.mCurScrollY);
27340         }
27341 
27342         matrix.postTranslate(-mLeft, -mTop);
27343 
27344         if (!hasIdentityMatrix()) {
27345             matrix.postConcat(getInverseMatrix());
27346         }
27347     }
27348 
27349     /**
27350      * @hide
27351      */
27352     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
27353             @ViewDebug.IntToString(from = 0, to = "x"),
27354             @ViewDebug.IntToString(from = 1, to = "y")
27355     })
27356     @UnsupportedAppUsage
getLocationOnScreen()27357     public int[] getLocationOnScreen() {
27358         int[] location = new int[2];
27359         getLocationOnScreen(location);
27360         return location;
27361     }
27362 
27363     /**
27364      * Gets the coordinates of this view in the coordinate space of the device
27365      * screen, irrespective of system decorations and whether the system is in
27366      * multi-window mode.
27367      *
27368      * <p>In multi-window mode, the coordinate space encompasses the entire
27369      * device screen, ignoring the bounds of the app window. For example, if the
27370      * view is in the bottom portion of a horizontal split screen, the top edge
27371      * of the screen&mdash;not the top edge of the window&mdash;is the origin
27372      * from which the y-coordinate is calculated.
27373      *
27374      * <p>In multiple-screen scenarios, the coordinate space can span screens.
27375      * For example, if the app is spanning both screens of a dual-screen device
27376      * and the view is located on the right-hand screen, the x-coordinate is
27377      * calculated from the left edge of the left-hand screen to the left edge of
27378      * the view. When the app is restricted to a single screen in a
27379      * multiple-screen environment, the coordinate space includes only the
27380      * screen on which the app is running.
27381      *
27382      * <p>After the method returns, the argument array contains the x and y
27383      * coordinates of the view relative to the view's left and top edges,
27384      * respectively.
27385      *
27386      * @param outLocation A two-element integer array in which the view
27387      *      coordinates are stored. The x-coordinate is at index 0; the
27388      *      y-coordinate, at index 1.
27389      */
getLocationOnScreen(@ize2) int[] outLocation)27390     public void getLocationOnScreen(@Size(2) int[] outLocation) {
27391         getLocationInWindow(outLocation);
27392 
27393         final AttachInfo info = mAttachInfo;
27394         if (info != null) {
27395             outLocation[0] += info.mWindowLeft;
27396             outLocation[1] += info.mWindowTop;
27397             // If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
27398             // applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
27399             info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
27400         }
27401     }
27402 
27403     /**
27404      * Gets the coordinates of this view in the coordinate space of the window
27405      * that contains the view, irrespective of system decorations.
27406      *
27407      * <p>In multi-window mode, the origin of the coordinate space is the
27408      * top left corner of the window that contains the view. In full screen
27409      * mode, the origin is the top left corner of the device screen.
27410      *
27411      * <p>In multiple-screen scenarios, if the app spans multiple screens, the
27412      * coordinate space also spans multiple screens. But if the app is
27413      * restricted to a single screen, the coordinate space includes only the
27414      * screen on which the app is running.
27415      *
27416      * <p>After the method returns, the argument array contains the x and y
27417      * coordinates of the view relative to the view's left and top edges,
27418      * respectively.
27419      *
27420      * @param outLocation A two-element integer array in which the view
27421      *      coordinates are stored. The x-coordinate is at index 0; the
27422      *      y-coordinate, at index 1.
27423      */
getLocationInWindow(@ize2) int[] outLocation)27424     public void getLocationInWindow(@Size(2) int[] outLocation) {
27425         if (outLocation == null || outLocation.length < 2) {
27426             throw new IllegalArgumentException("outLocation must be an array of two integers");
27427         }
27428 
27429         outLocation[0] = 0;
27430         outLocation[1] = 0;
27431 
27432         transformFromViewToWindowSpace(outLocation);
27433     }
27434 
27435     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)27436     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
27437         if (inOutLocation == null || inOutLocation.length < 2) {
27438             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
27439         }
27440 
27441         if (mAttachInfo == null) {
27442             // When the view is not attached to a window, this method does not make sense
27443             inOutLocation[0] = inOutLocation[1] = 0;
27444             return;
27445         }
27446 
27447         float position[] = mAttachInfo.mTmpTransformLocation;
27448         position[0] = inOutLocation[0];
27449         position[1] = inOutLocation[1];
27450 
27451         if (!hasIdentityMatrix()) {
27452             getMatrix().mapPoints(position);
27453         }
27454 
27455         position[0] += mLeft;
27456         position[1] += mTop;
27457 
27458         ViewParent viewParent = mParent;
27459         while (viewParent instanceof View) {
27460             final View view = (View) viewParent;
27461 
27462             position[0] -= view.mScrollX;
27463             position[1] -= view.mScrollY;
27464 
27465             if (!view.hasIdentityMatrix()) {
27466                 view.getMatrix().mapPoints(position);
27467             }
27468 
27469             position[0] += view.mLeft;
27470             position[1] += view.mTop;
27471 
27472             viewParent = view.mParent;
27473          }
27474 
27475         if (viewParent instanceof ViewRootImpl) {
27476             // *cough*
27477             final ViewRootImpl vr = (ViewRootImpl) viewParent;
27478             position[1] -= vr.mCurScrollY;
27479         }
27480 
27481         inOutLocation[0] = Math.round(position[0]);
27482         inOutLocation[1] = Math.round(position[1]);
27483     }
27484 
27485     /**
27486      * @param id the id of the view to be found
27487      * @return the view of the specified id, null if cannot be found
27488      * @hide
27489      */
findViewTraversal(@dRes int id)27490     protected <T extends View> T findViewTraversal(@IdRes int id) {
27491         if (id == mID) {
27492             return (T) this;
27493         }
27494         return null;
27495     }
27496 
27497     /**
27498      * @param tag the tag of the view to be found
27499      * @return the view of specified tag, null if cannot be found
27500      * @hide
27501      */
findViewWithTagTraversal(Object tag)27502     protected <T extends View> T findViewWithTagTraversal(Object tag) {
27503         if (tag != null && tag.equals(mTag)) {
27504             return (T) this;
27505         }
27506         return null;
27507     }
27508 
27509     /**
27510      * @param predicate The predicate to evaluate.
27511      * @param childToSkip If not null, ignores this child during the recursive traversal.
27512      * @return The first view that matches the predicate or null.
27513      * @hide
27514      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)27515     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
27516             View childToSkip) {
27517         if (predicate.test(this)) {
27518             return (T) this;
27519         }
27520         return null;
27521     }
27522 
27523     /**
27524      * Finds the first descendant view with the given ID, the view itself if
27525      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
27526      * (< 0) or there is no matching view in the hierarchy.
27527      * <p>
27528      * <strong>Note:</strong> In most cases -- depending on compiler support --
27529      * the resulting view is automatically cast to the target class type. If
27530      * the target class type is unconstrained, an explicit cast may be
27531      * necessary.
27532      *
27533      * @param id the ID to search for
27534      * @return a view with given ID if found, or {@code null} otherwise
27535      * @see View#requireViewById(int)
27536      */
27537     @Nullable
findViewById(@dRes int id)27538     public final <T extends View> T findViewById(@IdRes int id) {
27539         if (id == NO_ID) {
27540             return null;
27541         }
27542         return findViewTraversal(id);
27543     }
27544 
27545     /**
27546      * Finds the first descendant view with the given ID, the view itself if the ID matches
27547      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
27548      * matching view in the hierarchy.
27549      * <p>
27550      * <strong>Note:</strong> In most cases -- depending on compiler support --
27551      * the resulting view is automatically cast to the target class type. If
27552      * the target class type is unconstrained, an explicit cast may be
27553      * necessary.
27554      *
27555      * @param id the ID to search for
27556      * @return a view with given ID
27557      * @see View#findViewById(int)
27558      */
27559     @NonNull
requireViewById(@dRes int id)27560     public final <T extends View> T requireViewById(@IdRes int id) {
27561         T view = findViewById(id);
27562         if (view == null) {
27563             throw new IllegalArgumentException("ID does not reference a View inside this View");
27564         }
27565         return view;
27566     }
27567 
27568     /**
27569      * Performs the traversal to find a view by its unique and stable accessibility id.
27570      *
27571      * <strong>Note:</strong>This method does not stop at the root namespace
27572      * boundary since the user can touch the screen at an arbitrary location
27573      * potentially crossing the root namespace boundary which will send an
27574      * accessibility event to accessibility services and they should be able
27575      * to obtain the event source. Also accessibility ids are guaranteed to be
27576      * unique in the window.
27577      *
27578      * @param accessibilityId The accessibility id.
27579      * @return The found view.
27580      * @hide
27581      */
findViewByAccessibilityIdTraversal(int accessibilityId)27582     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
27583         if (getAccessibilityViewId() == accessibilityId) {
27584             return (T) this;
27585         }
27586         return null;
27587     }
27588 
27589     /**
27590      * Performs the traversal to find a view by its autofill id.
27591      *
27592      * <strong>Note:</strong>This method does not stop at the root namespace
27593      * boundary.
27594      *
27595      * @param autofillId The autofill id.
27596      * @return The found view.
27597      * @hide
27598      */
findViewByAutofillIdTraversal(int autofillId)27599     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
27600         if (getAutofillViewId() == autofillId) {
27601             return (T) this;
27602         }
27603         return null;
27604     }
27605 
27606     /**
27607      * Look for a child view with the given tag.  If this view has the given
27608      * tag, return this view.
27609      *
27610      * @param tag The tag to search for, using "tag.equals(getTag())".
27611      * @return The View that has the given tag in the hierarchy or null
27612      */
findViewWithTag(Object tag)27613     public final <T extends View> T findViewWithTag(Object tag) {
27614         if (tag == null) {
27615             return null;
27616         }
27617         return findViewWithTagTraversal(tag);
27618     }
27619 
27620     /**
27621      * Look for a child view that matches the specified predicate.
27622      * If this view matches the predicate, return this view.
27623      *
27624      * @param predicate The predicate to evaluate.
27625      * @return The first view that matches the predicate or null.
27626      * @hide
27627      */
findViewByPredicate(Predicate<View> predicate)27628     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
27629         return findViewByPredicateTraversal(predicate, null);
27630     }
27631 
27632     /**
27633      * Look for a child view that matches the specified predicate,
27634      * starting with the specified view and its descendents and then
27635      * recusively searching the ancestors and siblings of that view
27636      * until this view is reached.
27637      *
27638      * This method is useful in cases where the predicate does not match
27639      * a single unique view (perhaps multiple views use the same id)
27640      * and we are trying to find the view that is "closest" in scope to the
27641      * starting view.
27642      *
27643      * @param start The view to start from.
27644      * @param predicate The predicate to evaluate.
27645      * @return The first view that matches the predicate or null.
27646      * @hide
27647      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)27648     public final <T extends View> T findViewByPredicateInsideOut(
27649             View start, Predicate<View> predicate) {
27650         View childToSkip = null;
27651         for (;;) {
27652             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
27653             if (view != null || start == this) {
27654                 return view;
27655             }
27656 
27657             ViewParent parent = start.getParent();
27658             if (parent == null || !(parent instanceof View)) {
27659                 return null;
27660             }
27661 
27662             childToSkip = start;
27663             start = (View) parent;
27664         }
27665     }
27666 
27667     /**
27668      * Sets the identifier for this view. The identifier does not have to be
27669      * unique in this view's hierarchy. The identifier should be a positive
27670      * number.
27671      *
27672      * @see #NO_ID
27673      * @see #getId()
27674      * @see #findViewById(int)
27675      *
27676      * @param id a number used to identify the view
27677      *
27678      * @attr ref android.R.styleable#View_id
27679      */
setId(@dRes int id)27680     public void setId(@IdRes int id) {
27681         mID = id;
27682         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
27683             mID = generateViewId();
27684         }
27685     }
27686 
27687     /**
27688      * {@hide}
27689      *
27690      * @param isRoot true if the view belongs to the root namespace, false
27691      *        otherwise
27692      */
27693     @UnsupportedAppUsage
27694     @TestApi
setIsRootNamespace(boolean isRoot)27695     public void setIsRootNamespace(boolean isRoot) {
27696         if (isRoot) {
27697             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
27698         } else {
27699             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
27700         }
27701     }
27702 
27703     /**
27704      * {@hide}
27705      *
27706      * @return true if the view belongs to the root namespace, false otherwise
27707      */
27708     @UnsupportedAppUsage
isRootNamespace()27709     public boolean isRootNamespace() {
27710         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
27711     }
27712 
27713     /**
27714      * Returns this view's identifier.
27715      *
27716      * @return a positive integer used to identify the view or {@link #NO_ID}
27717      *         if the view has no ID
27718      *
27719      * @see #setId(int)
27720      * @see #findViewById(int)
27721      * @attr ref android.R.styleable#View_id
27722      */
27723     @IdRes
27724     @ViewDebug.CapturedViewProperty
27725     @InspectableProperty
getId()27726     public int getId() {
27727         return mID;
27728     }
27729 
27730     /**
27731      * Get the identifier used for this view by the drawing system.
27732      *
27733      * @see RenderNode#getUniqueId()
27734      * @return A long that uniquely identifies this view's drawing component
27735      */
getUniqueDrawingId()27736     public long getUniqueDrawingId() {
27737         return mRenderNode.getUniqueId();
27738     }
27739 
27740     /**
27741      * Returns this view's tag.
27742      *
27743      * @return the Object stored in this view as a tag, or {@code null} if not
27744      *         set
27745      *
27746      * @see #setTag(Object)
27747      * @see #getTag(int)
27748      */
27749     @ViewDebug.ExportedProperty
27750     @InspectableProperty
getTag()27751     public Object getTag() {
27752         return mTag;
27753     }
27754 
27755     /**
27756      * Sets the tag associated with this view. A tag can be used to mark
27757      * a view in its hierarchy and does not have to be unique within the
27758      * hierarchy. Tags can also be used to store data within a view without
27759      * resorting to another data structure.
27760      *
27761      * @param tag an Object to tag the view with
27762      *
27763      * @see #getTag()
27764      * @see #setTag(int, Object)
27765      */
setTag(final Object tag)27766     public void setTag(final Object tag) {
27767         mTag = tag;
27768     }
27769 
27770     /**
27771      * Returns the tag associated with this view and the specified key.
27772      *
27773      * @param key The key identifying the tag
27774      *
27775      * @return the Object stored in this view as a tag, or {@code null} if not
27776      *         set
27777      *
27778      * @see #setTag(int, Object)
27779      * @see #getTag()
27780      */
getTag(int key)27781     public Object getTag(int key) {
27782         if (mKeyedTags != null) return mKeyedTags.get(key);
27783         return null;
27784     }
27785 
27786     /**
27787      * Sets a tag associated with this view and a key. A tag can be used
27788      * to mark a view in its hierarchy and does not have to be unique within
27789      * the hierarchy. Tags can also be used to store data within a view
27790      * without resorting to another data structure.
27791      *
27792      * The specified key should be an id declared in the resources of the
27793      * application to ensure it is unique (see the <a
27794      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
27795      * Keys identified as belonging to
27796      * the Android framework or not associated with any package will cause
27797      * an {@link IllegalArgumentException} to be thrown.
27798      *
27799      * @param key The key identifying the tag
27800      * @param tag An Object to tag the view with
27801      *
27802      * @throws IllegalArgumentException If they specified key is not valid
27803      *
27804      * @see #setTag(Object)
27805      * @see #getTag(int)
27806      */
setTag(int key, final Object tag)27807     public void setTag(int key, final Object tag) {
27808         // If the package id is 0x00 or 0x01, it's either an undefined package
27809         // or a framework id
27810         if ((key >>> 24) < 2) {
27811             throw new IllegalArgumentException("The key must be an application-specific "
27812                     + "resource id.");
27813         }
27814 
27815         setKeyedTag(key, tag);
27816     }
27817 
27818     /**
27819      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
27820      * framework id.
27821      *
27822      * @hide
27823      */
27824     @UnsupportedAppUsage
setTagInternal(int key, Object tag)27825     public void setTagInternal(int key, Object tag) {
27826         if ((key >>> 24) != 0x1) {
27827             throw new IllegalArgumentException("The key must be a framework-specific "
27828                     + "resource id.");
27829         }
27830 
27831         setKeyedTag(key, tag);
27832     }
27833 
setKeyedTag(int key, Object tag)27834     private void setKeyedTag(int key, Object tag) {
27835         if (mKeyedTags == null) {
27836             mKeyedTags = new SparseArray<Object>(2);
27837         }
27838 
27839         mKeyedTags.put(key, tag);
27840     }
27841 
27842     /**
27843      * Prints information about this view in the log output, with the tag
27844      * {@link #VIEW_LOG_TAG}.
27845      *
27846      * @hide
27847      */
27848     @UnsupportedAppUsage
debug()27849     public void debug() {
27850         debug(0);
27851     }
27852 
27853     /**
27854      * Prints information about this view in the log output, with the tag
27855      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
27856      * indentation defined by the <code>depth</code>.
27857      *
27858      * @param depth the indentation level
27859      *
27860      * @hide
27861      */
27862     @UnsupportedAppUsage
debug(int depth)27863     protected void debug(int depth) {
27864         String output = debugIndent(depth - 1);
27865 
27866         output += "+ " + this;
27867         int id = getId();
27868         if (id != -1) {
27869             output += " (id=" + id + ")";
27870         }
27871         Object tag = getTag();
27872         if (tag != null) {
27873             output += " (tag=" + tag + ")";
27874         }
27875         Log.d(VIEW_LOG_TAG, output);
27876 
27877         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
27878             output = debugIndent(depth) + " FOCUSED";
27879             Log.d(VIEW_LOG_TAG, output);
27880         }
27881 
27882         output = debugIndent(depth);
27883         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
27884                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
27885                 + "} ";
27886         Log.d(VIEW_LOG_TAG, output);
27887 
27888         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
27889                 || mPaddingBottom != 0) {
27890             output = debugIndent(depth);
27891             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
27892                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
27893             Log.d(VIEW_LOG_TAG, output);
27894         }
27895 
27896         output = debugIndent(depth);
27897         output += "mMeasureWidth=" + mMeasuredWidth +
27898                 " mMeasureHeight=" + mMeasuredHeight;
27899         Log.d(VIEW_LOG_TAG, output);
27900 
27901         output = debugIndent(depth);
27902         if (mLayoutParams == null) {
27903             output += "BAD! no layout params";
27904         } else {
27905             output = mLayoutParams.debug(output);
27906         }
27907         Log.d(VIEW_LOG_TAG, output);
27908 
27909         output = debugIndent(depth);
27910         output += "flags={";
27911         output += View.printFlags(mViewFlags);
27912         output += "}";
27913         Log.d(VIEW_LOG_TAG, output);
27914 
27915         output = debugIndent(depth);
27916         output += "privateFlags={";
27917         output += View.printPrivateFlags(mPrivateFlags);
27918         output += "}";
27919         Log.d(VIEW_LOG_TAG, output);
27920     }
27921 
27922     /**
27923      * Creates a string of whitespaces used for indentation.
27924      *
27925      * @param depth the indentation level
27926      * @return a String containing (depth * 2 + 3) * 2 white spaces
27927      *
27928      * @hide
27929      */
debugIndent(int depth)27930     protected static String debugIndent(int depth) {
27931         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
27932         for (int i = 0; i < (depth * 2) + 3; i++) {
27933             spaces.append(' ').append(' ');
27934         }
27935         return spaces.toString();
27936     }
27937 
27938     /**
27939      * <p>Return the offset of the widget's text baseline from the widget's top
27940      * boundary. If this widget does not support baseline alignment, this
27941      * method returns -1. </p>
27942      *
27943      * @return the offset of the baseline within the widget's bounds or -1
27944      *         if baseline alignment is not supported
27945      */
27946     @ViewDebug.ExportedProperty(category = "layout")
27947     @InspectableProperty
getBaseline()27948     public int getBaseline() {
27949         return -1;
27950     }
27951 
27952     /**
27953      * Returns whether the view hierarchy is currently undergoing a layout pass. This
27954      * information is useful to avoid situations such as calling {@link #requestLayout()} during
27955      * a layout pass.
27956      *
27957      * @return whether the view hierarchy is currently undergoing a layout pass
27958      */
isInLayout()27959     public boolean isInLayout() {
27960         ViewRootImpl viewRoot = getViewRootImpl();
27961         return (viewRoot != null && viewRoot.isInLayout());
27962     }
27963 
27964     /** To be used only for debugging purposes. */
printStackStrace(String name)27965     private void printStackStrace(String name) {
27966         Log.d(VIEW_LOG_TAG, "---- ST:" + name);
27967 
27968         StringBuilder sb = new StringBuilder();
27969         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
27970         int startIndex = 1;
27971         int endIndex = Math.min(stackTraceElements.length, startIndex + 20); // max 20 entries.
27972         for (int i = startIndex; i < endIndex; i++) {
27973             StackTraceElement s = stackTraceElements[i];
27974             sb.append(s.getMethodName())
27975                     .append("(")
27976                     .append(s.getFileName())
27977                     .append(":")
27978                     .append(s.getLineNumber())
27979                     .append(") <- ");
27980         }
27981         Log.d(VIEW_LOG_TAG, name + ": " + sb);
27982     }
27983     /**
27984      * Call this when something has changed which has invalidated the
27985      * layout of this view. This will schedule a layout pass of the view
27986      * tree. This should not be called while the view hierarchy is currently in a layout
27987      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
27988      * end of the current layout pass (and then layout will run again) or after the current
27989      * frame is drawn and the next layout occurs.
27990      *
27991      * <p>Subclasses which override this method should call the superclass method to
27992      * handle possible request-during-layout errors correctly.</p>
27993      */
27994     @CallSuper
requestLayout()27995     public void requestLayout() {
27996         if (isRelayoutTracingEnabled()) {
27997             Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
27998                     mTracingStrings.classSimpleName);
27999             printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
28000         }
28001 
28002         if (mMeasureCache != null) mMeasureCache.clear();
28003 
28004         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
28005             // Only trigger request-during-layout logic if this is the view requesting it,
28006             // not the views in its parent hierarchy
28007             ViewRootImpl viewRoot = getViewRootImpl();
28008             if (viewRoot != null && viewRoot.isInLayout()) {
28009                 if (!viewRoot.requestLayoutDuringLayout(this)) {
28010                     return;
28011                 }
28012             }
28013             mAttachInfo.mViewRequestingLayout = this;
28014         }
28015 
28016         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
28017         mPrivateFlags |= PFLAG_INVALIDATED;
28018 
28019         if (mParent != null && !mParent.isLayoutRequested()) {
28020             mParent.requestLayout();
28021         }
28022         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
28023             mAttachInfo.mViewRequestingLayout = null;
28024         }
28025     }
28026 
28027     /**
28028      * Forces this view to be laid out during the next layout pass.
28029      * This method does not call requestLayout() or forceLayout()
28030      * on the parent.
28031      */
forceLayout()28032     public void forceLayout() {
28033         if (mMeasureCache != null) mMeasureCache.clear();
28034 
28035         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
28036         mPrivateFlags |= PFLAG_INVALIDATED;
28037     }
28038 
28039     /**
28040      * <p>
28041      * This is called to find out how big a view should be. The parent
28042      * supplies constraint information in the width and height parameters.
28043      * </p>
28044      *
28045      * <p>
28046      * The actual measurement work of a view is performed in
28047      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
28048      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
28049      * </p>
28050      *
28051      *
28052      * @param widthMeasureSpec Horizontal space requirements as imposed by the
28053      *        parent
28054      * @param heightMeasureSpec Vertical space requirements as imposed by the
28055      *        parent
28056      *
28057      * @see #onMeasure(int, int)
28058      */
measure(int widthMeasureSpec, int heightMeasureSpec)28059     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
28060         boolean optical = isLayoutModeOptical(this);
28061         if (optical != isLayoutModeOptical(mParent)) {
28062             Insets insets = getOpticalInsets();
28063             int oWidth  = insets.left + insets.right;
28064             int oHeight = insets.top  + insets.bottom;
28065             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
28066             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
28067         }
28068 
28069         // Suppress sign extension for the low bytes
28070         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
28071         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
28072 
28073         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
28074 
28075         // Optimize layout by avoiding an extra EXACTLY pass when the view is
28076         // already measured as the correct size. In API 23 and below, this
28077         // extra pass is required to make LinearLayout re-distribute weight.
28078         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
28079                 || heightMeasureSpec != mOldHeightMeasureSpec;
28080         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
28081                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
28082         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
28083                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
28084         final boolean needsLayout = specChanged
28085                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
28086 
28087         if (forceLayout || needsLayout) {
28088             // first clears the measured dimension flag
28089             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
28090 
28091             resolveRtlPropertiesIfNeeded();
28092 
28093             int cacheIndex;
28094             if (sUseMeasureCacheDuringForceLayoutFlagValue) {
28095                 cacheIndex =  mMeasureCache.indexOfKey(key);
28096             } else {
28097                 cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
28098             }
28099 
28100             if (cacheIndex < 0) {
28101                 if (isTraversalTracingEnabled()) {
28102                     Trace.beginSection(mTracingStrings.onMeasure);
28103                 }
28104                 if (android.os.Flags.adpfMeasureDuringInputEventBoost()) {
28105                     final boolean notifyRenderer = hasExpensiveMeasuresDuringInputEvent();
28106                     if (notifyRenderer) {
28107                         Trace.traceBegin(Trace.TRACE_TAG_VIEW,
28108                                 "CPU_LOAD_UP: " + "hasExpensiveMeasuresDuringInputEvent");
28109                         getViewRootImpl().notifyRendererOfExpensiveFrame();
28110                         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
28111                     }
28112                 }
28113                 // measure ourselves, this should set the measured dimension flag back
28114                 onMeasure(widthMeasureSpec, heightMeasureSpec);
28115                 if (isTraversalTracingEnabled()) {
28116                     Trace.endSection();
28117                 }
28118                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
28119             } else {
28120                 long value = mMeasureCache.valueAt(cacheIndex);
28121                 // Casting a long to int drops the high 32 bits, no mask needed
28122                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
28123                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
28124             }
28125 
28126             // flag not set, setMeasuredDimension() was not invoked, we raise
28127             // an exception to warn the developer
28128             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
28129                 throw new IllegalStateException("View with id " + getId() + ": "
28130                         + getClass().getName() + "#onMeasure() did not set the"
28131                         + " measured dimension by calling"
28132                         + " setMeasuredDimension()");
28133             }
28134 
28135             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
28136         }
28137 
28138         mOldWidthMeasureSpec = widthMeasureSpec;
28139         mOldHeightMeasureSpec = heightMeasureSpec;
28140 
28141         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
28142                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
28143     }
28144 
28145     /**
28146      * <p>
28147      * Measure the view and its content to determine the measured width and the
28148      * measured height. This method is invoked by {@link #measure(int, int)} and
28149      * should be overridden by subclasses to provide accurate and efficient
28150      * measurement of their contents.
28151      * </p>
28152      *
28153      * <p>
28154      * <strong>CONTRACT:</strong> When overriding this method, you
28155      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
28156      * measured width and height of this view. Failure to do so will trigger an
28157      * <code>IllegalStateException</code>, thrown by
28158      * {@link #measure(int, int)}. Calling the superclass'
28159      * {@link #onMeasure(int, int)} is a valid use.
28160      * </p>
28161      *
28162      * <p>
28163      * The base class implementation of measure defaults to the background size,
28164      * unless a larger size is allowed by the MeasureSpec. Subclasses should
28165      * override {@link #onMeasure(int, int)} to provide better measurements of
28166      * their content.
28167      * </p>
28168      *
28169      * <p>
28170      * If this method is overridden, it is the subclass's responsibility to make
28171      * sure the measured height and width are at least the view's minimum height
28172      * and width ({@link #getSuggestedMinimumHeight()} and
28173      * {@link #getSuggestedMinimumWidth()}).
28174      * </p>
28175      *
28176      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
28177      *                         The requirements are encoded with
28178      *                         {@link android.view.View.MeasureSpec}.
28179      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
28180      *                         The requirements are encoded with
28181      *                         {@link android.view.View.MeasureSpec}.
28182      *
28183      * @see #getMeasuredWidth()
28184      * @see #getMeasuredHeight()
28185      * @see #setMeasuredDimension(int, int)
28186      * @see #getSuggestedMinimumHeight()
28187      * @see #getSuggestedMinimumWidth()
28188      * @see android.view.View.MeasureSpec#getMode(int)
28189      * @see android.view.View.MeasureSpec#getSize(int)
28190      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)28191     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
28192         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
28193                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
28194     }
28195 
28196     /**
28197      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
28198      * measured width and measured height. Failing to do so will trigger an
28199      * exception at measurement time.</p>
28200      *
28201      * @param measuredWidth The measured width of this view.  May be a complex
28202      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28203      * {@link #MEASURED_STATE_TOO_SMALL}.
28204      * @param measuredHeight The measured height of this view.  May be a complex
28205      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28206      * {@link #MEASURED_STATE_TOO_SMALL}.
28207      */
setMeasuredDimension(int measuredWidth, int measuredHeight)28208     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
28209         boolean optical = isLayoutModeOptical(this);
28210         if (optical != isLayoutModeOptical(mParent)) {
28211             Insets insets = getOpticalInsets();
28212             int opticalWidth  = insets.left + insets.right;
28213             int opticalHeight = insets.top  + insets.bottom;
28214 
28215             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
28216             measuredHeight += optical ? opticalHeight : -opticalHeight;
28217         }
28218         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
28219     }
28220 
28221     /**
28222      * Sets the measured dimension without extra processing for things like optical bounds.
28223      * Useful for reapplying consistent values that have already been cooked with adjustments
28224      * for optical bounds, etc. such as those from the measurement cache.
28225      *
28226      * @param measuredWidth The measured width of this view.  May be a complex
28227      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28228      * {@link #MEASURED_STATE_TOO_SMALL}.
28229      * @param measuredHeight The measured height of this view.  May be a complex
28230      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28231      * {@link #MEASURED_STATE_TOO_SMALL}.
28232      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)28233     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
28234         mMeasuredWidth = measuredWidth;
28235         mMeasuredHeight = measuredHeight;
28236 
28237         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
28238     }
28239 
28240     /**
28241      * Merge two states as returned by {@link #getMeasuredState()}.
28242      * @param curState The current state as returned from a view or the result
28243      * of combining multiple views.
28244      * @param newState The new view state to combine.
28245      * @return Returns a new integer reflecting the combination of the two
28246      * states.
28247      */
combineMeasuredStates(int curState, int newState)28248     public static int combineMeasuredStates(int curState, int newState) {
28249         return curState | newState;
28250     }
28251 
28252     /**
28253      * Version of {@link #resolveSizeAndState(int, int, int)}
28254      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
28255      */
resolveSize(int size, int measureSpec)28256     public static int resolveSize(int size, int measureSpec) {
28257         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
28258     }
28259 
28260     /**
28261      * Utility to reconcile a desired size and state, with constraints imposed
28262      * by a MeasureSpec. Will take the desired size, unless a different size
28263      * is imposed by the constraints. The returned value is a compound integer,
28264      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
28265      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
28266      * resulting size is smaller than the size the view wants to be.
28267      *
28268      * @param size How big the view wants to be.
28269      * @param measureSpec Constraints imposed by the parent.
28270      * @param childMeasuredState Size information bit mask for the view's
28271      *                           children.
28272      * @return Size information bit mask as defined by
28273      *         {@link #MEASURED_SIZE_MASK} and
28274      *         {@link #MEASURED_STATE_TOO_SMALL}.
28275      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)28276     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
28277         final int specMode = MeasureSpec.getMode(measureSpec);
28278         final int specSize = MeasureSpec.getSize(measureSpec);
28279         final int result;
28280         switch (specMode) {
28281             case MeasureSpec.AT_MOST:
28282                 if (specSize < size) {
28283                     result = specSize | MEASURED_STATE_TOO_SMALL;
28284                 } else {
28285                     result = size;
28286                 }
28287                 break;
28288             case MeasureSpec.EXACTLY:
28289                 result = specSize;
28290                 break;
28291             case MeasureSpec.UNSPECIFIED:
28292             default:
28293                 result = size;
28294         }
28295         return result | (childMeasuredState & MEASURED_STATE_MASK);
28296     }
28297 
28298     /**
28299      * Utility to return a default size. Uses the supplied size if the
28300      * MeasureSpec imposed no constraints. Will get larger if allowed
28301      * by the MeasureSpec.
28302      *
28303      * @param size Default size for this view
28304      * @param measureSpec Constraints imposed by the parent
28305      * @return The size this view should be.
28306      */
getDefaultSize(int size, int measureSpec)28307     public static int getDefaultSize(int size, int measureSpec) {
28308         int result = size;
28309         int specMode = MeasureSpec.getMode(measureSpec);
28310         int specSize = MeasureSpec.getSize(measureSpec);
28311 
28312         switch (specMode) {
28313         case MeasureSpec.UNSPECIFIED:
28314             result = size;
28315             break;
28316         case MeasureSpec.AT_MOST:
28317         case MeasureSpec.EXACTLY:
28318             result = specSize;
28319             break;
28320         }
28321         return result;
28322     }
28323 
28324     /**
28325      * Returns the suggested minimum height that the view should use. This
28326      * returns the maximum of the view's minimum height
28327      * and the background's minimum height
28328      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
28329      * <p>
28330      * When being used in {@link #onMeasure(int, int)}, the caller should still
28331      * ensure the returned height is within the requirements of the parent.
28332      *
28333      * @return The suggested minimum height of the view.
28334      */
getSuggestedMinimumHeight()28335     protected int getSuggestedMinimumHeight() {
28336         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
28337 
28338     }
28339 
28340     /**
28341      * Returns the suggested minimum width that the view should use. This
28342      * returns the maximum of the view's minimum width
28343      * and the background's minimum width
28344      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
28345      * <p>
28346      * When being used in {@link #onMeasure(int, int)}, the caller should still
28347      * ensure the returned width is within the requirements of the parent.
28348      *
28349      * @return The suggested minimum width of the view.
28350      */
getSuggestedMinimumWidth()28351     protected int getSuggestedMinimumWidth() {
28352         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
28353     }
28354 
28355     /**
28356      * Returns the minimum height of the view.
28357      *
28358      * @return the minimum height the view will try to be, in pixels
28359      *
28360      * @see #setMinimumHeight(int)
28361      *
28362      * @attr ref android.R.styleable#View_minHeight
28363      */
28364     @InspectableProperty(name = "minHeight")
getMinimumHeight()28365     public int getMinimumHeight() {
28366         return mMinHeight;
28367     }
28368 
28369     /**
28370      * Sets the minimum height of the view. It is not guaranteed the view will
28371      * be able to achieve this minimum height (for example, if its parent layout
28372      * constrains it with less available height).
28373      *
28374      * @param minHeight The minimum height the view will try to be, in pixels
28375      *
28376      * @see #getMinimumHeight()
28377      *
28378      * @attr ref android.R.styleable#View_minHeight
28379      */
28380     @RemotableViewMethod
setMinimumHeight(int minHeight)28381     public void setMinimumHeight(int minHeight) {
28382         mMinHeight = minHeight;
28383         requestLayout();
28384     }
28385 
28386     /**
28387      * Returns the minimum width of the view.
28388      *
28389      * @return the minimum width the view will try to be, in pixels
28390      *
28391      * @see #setMinimumWidth(int)
28392      *
28393      * @attr ref android.R.styleable#View_minWidth
28394      */
28395     @InspectableProperty(name = "minWidth")
getMinimumWidth()28396     public int getMinimumWidth() {
28397         return mMinWidth;
28398     }
28399 
28400     /**
28401      * Sets the minimum width of the view. It is not guaranteed the view will
28402      * be able to achieve this minimum width (for example, if its parent layout
28403      * constrains it with less available width).
28404      *
28405      * @param minWidth The minimum width the view will try to be, in pixels
28406      *
28407      * @see #getMinimumWidth()
28408      *
28409      * @attr ref android.R.styleable#View_minWidth
28410      */
28411     @RemotableViewMethod
setMinimumWidth(int minWidth)28412     public void setMinimumWidth(int minWidth) {
28413         mMinWidth = minWidth;
28414         requestLayout();
28415 
28416     }
28417 
28418     /**
28419      * Get the animation currently associated with this view.
28420      *
28421      * @return The animation that is currently playing or
28422      *         scheduled to play for this view.
28423      */
getAnimation()28424     public Animation getAnimation() {
28425         return mCurrentAnimation;
28426     }
28427 
28428     /**
28429      * Start the specified animation now.
28430      *
28431      * @param animation the animation to start now
28432      */
startAnimation(Animation animation)28433     public void startAnimation(Animation animation) {
28434         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
28435         setAnimation(animation);
28436         invalidateParentCaches();
28437         invalidate(true);
28438     }
28439 
28440     /**
28441      * Cancels any animations for this view.
28442      */
clearAnimation()28443     public void clearAnimation() {
28444         if (mCurrentAnimation != null) {
28445             mCurrentAnimation.detach();
28446         }
28447         mCurrentAnimation = null;
28448         invalidateParentIfNeeded();
28449     }
28450 
28451     /**
28452      * Sets the next animation to play for this view.
28453      * If you want the animation to play immediately, use
28454      * {@link #startAnimation(android.view.animation.Animation)} instead.
28455      * This method provides allows fine-grained
28456      * control over the start time and invalidation, but you
28457      * must make sure that 1) the animation has a start time set, and
28458      * 2) the view's parent (which controls animations on its children)
28459      * will be invalidated when the animation is supposed to
28460      * start.
28461      *
28462      * @param animation The next animation, or null.
28463      */
setAnimation(Animation animation)28464     public void setAnimation(Animation animation) {
28465         mCurrentAnimation = animation;
28466 
28467         if (animation != null) {
28468             // If the screen is off assume the animation start time is now instead of
28469             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
28470             // would cause the animation to start when the screen turns back on
28471             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
28472                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
28473                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
28474             }
28475             animation.reset();
28476         }
28477     }
28478 
28479     /**
28480      * Invoked by a parent ViewGroup to notify the start of the animation
28481      * currently associated with this view. If you override this method,
28482      * always call super.onAnimationStart();
28483      *
28484      * @see #setAnimation(android.view.animation.Animation)
28485      * @see #getAnimation()
28486      */
28487     @CallSuper
onAnimationStart()28488     protected void onAnimationStart() {
28489         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
28490     }
28491 
28492     /**
28493      * Invoked by a parent ViewGroup to notify the end of the animation
28494      * currently associated with this view. If you override this method,
28495      * always call super.onAnimationEnd();
28496      *
28497      * @see #setAnimation(android.view.animation.Animation)
28498      * @see #getAnimation()
28499      */
28500     @CallSuper
onAnimationEnd()28501     protected void onAnimationEnd() {
28502         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
28503     }
28504 
28505     /**
28506      * Invoked if there is a Transform that involves alpha. Subclass that can
28507      * draw themselves with the specified alpha should return true, and then
28508      * respect that alpha when their onDraw() is called. If this returns false
28509      * then the view may be redirected to draw into an offscreen buffer to
28510      * fulfill the request, which will look fine, but may be slower than if the
28511      * subclass handles it internally. The default implementation returns false.
28512      *
28513      * @param alpha The alpha (0..255) to apply to the view's drawing
28514      * @return true if the view can draw with the specified alpha.
28515      */
onSetAlpha(int alpha)28516     protected boolean onSetAlpha(int alpha) {
28517         return false;
28518     }
28519 
28520     /**
28521      * This is used by the ViewRoot to perform an optimization when
28522      * the view hierarchy contains one or several SurfaceView.
28523      * SurfaceView is always considered transparent, but its children are not,
28524      * therefore all View objects remove themselves from the global transparent
28525      * region (passed as a parameter to this function).
28526      *
28527      * @param region The transparent region for this ViewAncestor (window).
28528      *
28529      * @return Returns true if the effective visibility of the view at this
28530      * point is opaque, regardless of the transparent region; returns false
28531      * if it is possible for underlying windows to be seen behind the view.
28532      *
28533      */
gatherTransparentRegion(@ullable Region region)28534     public boolean gatherTransparentRegion(@Nullable Region region) {
28535         final AttachInfo attachInfo = mAttachInfo;
28536         if (region != null && attachInfo != null) {
28537             final int pflags = mPrivateFlags;
28538             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
28539                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
28540                 // remove it from the transparent region.
28541                 final int[] location = attachInfo.mTransparentLocation;
28542                 getLocationInWindow(location);
28543                 // When a view has Z value, then it will be better to leave some area below the view
28544                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
28545                 // the bottom part needs more offset than the left, top and right parts due to the
28546                 // spot light effects.
28547                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
28548                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
28549                         location[0] + mRight - mLeft + shadowOffset,
28550                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
28551             } else {
28552                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
28553                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
28554                     // the background drawable's non-transparent parts from this transparent region.
28555                     applyDrawableToTransparentRegion(mBackground, region);
28556                 }
28557                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
28558                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
28559                     // Similarly, we remove the foreground drawable's non-transparent parts.
28560                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
28561                 }
28562                 if (mDefaultFocusHighlight != null
28563                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
28564                     // Similarly, we remove the default focus highlight's non-transparent parts.
28565                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
28566                 }
28567             }
28568         }
28569         return true;
28570     }
28571 
28572     /**
28573      * Play a sound effect for this view.
28574      *
28575      * <p>The framework will play sound effects for some built in actions, such as
28576      * clicking, but you may wish to play these effects in your widget,
28577      * for instance, for internal navigation.
28578      *
28579      * <p>The sound effect will only be played if sound effects are enabled by the user, and
28580      * {@link #isSoundEffectsEnabled()} is true.
28581      *
28582      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}.
28583      */
playSoundEffect(@oundEffectConstants.SoundEffect int soundConstant)28584     public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
28585         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
28586             return;
28587         }
28588         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
28589     }
28590 
28591     /**
28592      * BZZZTT!!1!
28593      *
28594      * <p>Provide haptic feedback to the user for this view.
28595      *
28596      * <p>The framework will provide haptic feedback for some built in actions,
28597      * such as long presses, but you may wish to provide feedback for your
28598      * own widget.
28599      *
28600      * <p>The feedback will only be performed if
28601      * {@link #isHapticFeedbackEnabled()} is true.
28602      *
28603      * @param feedbackConstant One of the constants defined in
28604      * {@link HapticFeedbackConstants}
28605      */
performHapticFeedback(int feedbackConstant)28606     public boolean performHapticFeedback(int feedbackConstant) {
28607         return performHapticFeedback(feedbackConstant, 0);
28608     }
28609 
28610     /**
28611      * BZZZTT!!1!
28612      *
28613      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
28614      *
28615      * @param feedbackConstant One of the constants defined in
28616      * {@link HapticFeedbackConstants}
28617      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
28618      */
performHapticFeedback(int feedbackConstant, int flags)28619     public boolean performHapticFeedback(int feedbackConstant, int flags) {
28620         if (feedbackConstant == HapticFeedbackConstants.NO_HAPTICS
28621                 || mAttachInfo == null) {
28622             return false;
28623         }
28624         //noinspection SimplifiableIfStatement
28625         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
28626                 && !isHapticFeedbackEnabled()) {
28627             return false;
28628         }
28629 
28630         final boolean always = (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0;
28631         boolean fromIme = false;
28632         if (mAttachInfo.mViewRootImpl != null) {
28633             fromIme = mAttachInfo.mViewRootImpl.mWindowAttributes.type == TYPE_INPUT_METHOD;
28634         }
28635         if (Flags.useVibratorHapticFeedback()) {
28636             if (!mAttachInfo.canPerformHapticFeedback()) {
28637                 return false;
28638             }
28639             getSystemVibrator().performHapticFeedback(
28640                     feedbackConstant, always, "View#performHapticFeedback", fromIme);
28641             return true;
28642         }
28643         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, always, fromIme);
28644     }
28645 
getSystemVibrator()28646     private Vibrator getSystemVibrator() {
28647         if (mVibrator != null) {
28648             return mVibrator;
28649         }
28650         return mVibrator = mContext.getSystemService(Vibrator.class);
28651     }
28652 
28653     /**
28654      * Request that the visibility of the status bar or other screen/window
28655      * decorations be changed.
28656      *
28657      * <p>This method is used to put the over device UI into temporary modes
28658      * where the user's attention is focused more on the application content,
28659      * by dimming or hiding surrounding system affordances.  This is typically
28660      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
28661      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
28662      * to be placed behind the action bar (and with these flags other system
28663      * affordances) so that smooth transitions between hiding and showing them
28664      * can be done.
28665      *
28666      * <p>Two representative examples of the use of system UI visibility is
28667      * implementing a content browsing application (like a magazine reader)
28668      * and a video playing application.
28669      *
28670      * <p>The first code shows a typical implementation of a View in a content
28671      * browsing application.  In this implementation, the application goes
28672      * into a content-oriented mode by hiding the status bar and action bar,
28673      * and putting the navigation elements into lights out mode.  The user can
28674      * then interact with content while in this mode.  Such an application should
28675      * provide an easy way for the user to toggle out of the mode (such as to
28676      * check information in the status bar or access notifications).  In the
28677      * implementation here, this is done simply by tapping on the content.
28678      *
28679      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
28680      *      content}
28681      *
28682      * <p>This second code sample shows a typical implementation of a View
28683      * in a video playing application.  In this situation, while the video is
28684      * playing the application would like to go into a complete full-screen mode,
28685      * to use as much of the display as possible for the video.  When in this state
28686      * the user can not interact with the application; the system intercepts
28687      * touching on the screen to pop the UI out of full screen mode.  See
28688      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
28689      *
28690      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
28691      *      content}
28692      *
28693      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
28694      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
28695      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
28696      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
28697      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
28698      *
28699      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
28700      * instead.
28701      */
28702     @Deprecated
setSystemUiVisibility(int visibility)28703     public void setSystemUiVisibility(int visibility) {
28704         if (visibility != mSystemUiVisibility) {
28705             mSystemUiVisibility = visibility;
28706             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
28707                 mParent.recomputeViewAttributes(this);
28708             }
28709         }
28710     }
28711 
28712     /**
28713      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
28714      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
28715      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
28716      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
28717      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
28718      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
28719      *
28720      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
28721      * instead.
28722      */
28723     @Deprecated
getSystemUiVisibility()28724     public int getSystemUiVisibility() {
28725         return mSystemUiVisibility;
28726     }
28727 
28728     /**
28729      * Returns the current system UI visibility that is currently set for
28730      * the entire window.  This is the combination of the
28731      * {@link #setSystemUiVisibility(int)} values supplied by all of the
28732      * views in the window.
28733      *
28734      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
28735      * instead.
28736      */
28737     @Deprecated
getWindowSystemUiVisibility()28738     public int getWindowSystemUiVisibility() {
28739         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
28740     }
28741 
28742     /**
28743      * Override to find out when the window's requested system UI visibility
28744      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
28745      * This is different from the callbacks received through
28746      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
28747      * in that this is only telling you about the local request of the window,
28748      * not the actual values applied by the system.
28749      *
28750      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
28751      * instead.
28752      */
28753     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)28754     public void onWindowSystemUiVisibilityChanged(int visible) {
28755     }
28756 
28757     /**
28758      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
28759      * the view hierarchy.
28760      *
28761      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
28762      * instead.
28763      */
28764     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)28765     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
28766         onWindowSystemUiVisibilityChanged(visible);
28767     }
28768 
28769     /**
28770      * Set a listener to receive callbacks when the visibility of the system bar changes.
28771      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
28772      *
28773      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
28774      * by setting a {@link OnApplyWindowInsetsListener} on this view.
28775      */
28776     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)28777     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
28778         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
28779         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
28780             mParent.recomputeViewAttributes(this);
28781         }
28782     }
28783 
28784     /**
28785      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
28786      * the view hierarchy.
28787      *
28788      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
28789      * by setting a {@link OnApplyWindowInsetsListener} on this view.
28790      */
28791     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)28792     public void dispatchSystemUiVisibilityChanged(int visibility) {
28793         ListenerInfo li = mListenerInfo;
28794         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
28795             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
28796                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
28797         }
28798     }
28799 
updateLocalSystemUiVisibility(int localValue, int localChanges)28800     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
28801         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
28802         if (val != mSystemUiVisibility) {
28803             setSystemUiVisibility(val);
28804             return true;
28805         }
28806         return false;
28807     }
28808 
28809     /** @hide */
28810     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDisabledSystemUiVisibility(int flags)28811     public void setDisabledSystemUiVisibility(int flags) {
28812         if (mAttachInfo != null) {
28813             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
28814                 mAttachInfo.mDisabledSystemUiVisibility = flags;
28815                 if (mParent != null) {
28816                     mParent.recomputeViewAttributes(this);
28817                 }
28818             }
28819         }
28820     }
28821 
28822     /**
28823      * This needs to be a better API before it is exposed. For now, only the root view will get
28824      * notified.
28825      * @hide
28826      */
onSystemBarAppearanceChanged(@indowInsetsController.Appearance int appearance)28827     public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
28828     }
28829 
28830     /**
28831      * Creates an image that the system displays during the drag and drop
28832      * operation. This is called a &quot;drag shadow&quot;. The default implementation
28833      * for a DragShadowBuilder based on a View returns an image that has exactly the same
28834      * appearance as the given View. The default also positions the center of the drag shadow
28835      * directly under the touch point. If no View is provided (the constructor with no parameters
28836      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
28837      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
28838      * default is an invisible drag shadow.
28839      * <p>
28840      * You are not required to use the View you provide to the constructor as the basis of the
28841      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
28842      * anything you want as the drag shadow.
28843      * </p>
28844      * <p>
28845      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
28846      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
28847      *  size and position of the drag shadow. It uses this data to construct a
28848      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
28849      *  so that your application can draw the shadow image in the Canvas.
28850      * </p>
28851      *
28852      * <div class="special reference">
28853      * <h3>Developer Guides</h3>
28854      * <p>For a guide to implementing drag and drop features, read the
28855      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
28856      * </div>
28857      */
28858     public static class DragShadowBuilder {
28859         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
28860         private final WeakReference<View> mView;
28861 
28862         /**
28863          * Constructs a shadow image builder based on a View. By default, the resulting drag
28864          * shadow will have the same appearance and dimensions as the View, with the touch point
28865          * over the center of the View.
28866          * @param view A View. Any View in scope can be used.
28867          */
DragShadowBuilder(View view)28868         public DragShadowBuilder(View view) {
28869             mView = new WeakReference<View>(view);
28870         }
28871 
28872         /**
28873          * Construct a shadow builder object with no associated View.  This
28874          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
28875          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
28876          * to supply the drag shadow's dimensions and appearance without
28877          * reference to any View object.
28878          */
DragShadowBuilder()28879         public DragShadowBuilder() {
28880             mView = new WeakReference<View>(null);
28881         }
28882 
28883         /**
28884          * Returns the View object that had been passed to the
28885          * {@link #DragShadowBuilder(View)}
28886          * constructor.  If that View parameter was {@code null} or if the
28887          * {@link #DragShadowBuilder()}
28888          * constructor was used to instantiate the builder object, this method will return
28889          * null.
28890          *
28891          * @return The View object associate with this builder object.
28892          */
28893         @SuppressWarnings({"JavadocReference"})
getView()28894         final public View getView() {
28895             return mView.get();
28896         }
28897 
28898         /**
28899          * Provides the metrics for the shadow image. These include the dimensions of
28900          * the shadow image, and the point within that shadow that should
28901          * be centered under the touch location while dragging.
28902          * <p>
28903          * The default implementation sets the dimensions of the shadow to be the
28904          * same as the dimensions of the View itself and centers the shadow under
28905          * the touch point.
28906          * </p>
28907          *
28908          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
28909          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
28910          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
28911          * image. Since Android P, the width and height must be positive values.
28912          *
28913          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
28914          * shadow image that should be underneath the touch point during the drag and drop
28915          * operation. Your application must set {@link android.graphics.Point#x} to the
28916          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
28917          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)28918         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
28919             final View view = mView.get();
28920             if (view != null) {
28921                 outShadowSize.set(view.getWidth(), view.getHeight());
28922                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
28923             } else {
28924                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
28925             }
28926         }
28927 
28928         /**
28929          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
28930          * based on the dimensions it received from the
28931          * {@link #onProvideShadowMetrics(Point, Point)} callback.
28932          *
28933          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
28934          */
onDrawShadow(@onNull Canvas canvas)28935         public void onDrawShadow(@NonNull Canvas canvas) {
28936             final View view = mView.get();
28937             if (view != null) {
28938                 view.draw(canvas);
28939             } else {
28940                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
28941             }
28942         }
28943     }
28944 
28945     /**
28946      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
28947      * startDragAndDrop()} for newer platform versions.
28948      */
28949     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)28950     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
28951                                    Object myLocalState, int flags) {
28952         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
28953     }
28954 
28955     /**
28956      * Starts a drag and drop operation. When your application calls this method, it passes a
28957      * {@link android.view.View.DragShadowBuilder} object to the system. The
28958      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
28959      * to get metrics for the drag shadow, and then calls the object's
28960      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
28961      * <p>
28962      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
28963      *  drag events to all the View objects in your application that are currently visible. It does
28964      *  this either by calling the View object's drag listener (an implementation of
28965      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
28966      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
28967      *  Both are passed a {@link android.view.DragEvent} object that has a
28968      *  {@link android.view.DragEvent#getAction()} value of
28969      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
28970      * </p>
28971      * <p>
28972      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
28973      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
28974      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
28975      * to the View the user selected for dragging.
28976      * </p>
28977      * @param data A {@link android.content.ClipData} object pointing to the data to be
28978      * transferred by the drag and drop operation.
28979      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
28980      * drag shadow.
28981      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
28982      * drop operation. When dispatching drag events to views in the same activity this object
28983      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
28984      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
28985      * will return null).
28986      * <p>
28987      * myLocalState is a lightweight mechanism for the sending information from the dragged View
28988      * to the target Views. For example, it can contain flags that differentiate between a
28989      * a copy operation and a move operation.
28990      * </p>
28991      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
28992      * flags, or any combination of the following:
28993      *     <ul>
28994      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
28995      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
28996      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
28997      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
28998      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
28999      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
29000      *         <li>{@link #DRAG_FLAG_ACCESSIBILITY_ACTION}</li>
29001      *     </ul>
29002      * @return {@code true} if the method completes successfully, or
29003      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
29004      * do a drag because of another ongoing operation or some other reasons.
29005      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)29006     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
29007             Object myLocalState, int flags) {
29008         if (ViewDebug.DEBUG_DRAG) {
29009             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
29010         }
29011         if (mAttachInfo == null) {
29012             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
29013             return false;
29014         }
29015         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
29016             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
29017             return false;
29018         }
29019         if ((flags & DRAG_FLAG_GLOBAL) != 0 && ((flags & DRAG_FLAG_GLOBAL_SAME_APPLICATION) != 0)) {
29020             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with both DRAG_FLAG_GLOBAL "
29021                     + "and DRAG_FLAG_GLOBAL_SAME_APPLICATION, the drag will default to "
29022                     + "DRAG_FLAG_GLOBAL_SAME_APPLICATION");
29023             flags &= ~DRAG_FLAG_GLOBAL;
29024         }
29025 
29026         if (data != null) {
29027             if (com.android.window.flags.Flags.delegateUnhandledDrags()) {
29028                 data.prepareToLeaveProcess(
29029                         (flags & (DRAG_FLAG_GLOBAL_SAME_APPLICATION | DRAG_FLAG_GLOBAL)) != 0);
29030                 if ((flags & DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG) != 0) {
29031                     if (!hasActivityPendingIntents(data)) {
29032                         // Reset the flag if there is no launchable activity intent
29033                         flags &= ~DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG;
29034                         Log.w(VIEW_LOG_TAG, "startDragAndDrop called with "
29035                                 + "DRAG_FLAG_START_INTENT_ON_UNHANDLED_DRAG but the clip data "
29036                                 + "contains non-activity PendingIntents");
29037                     }
29038                 }
29039             } else {
29040                 data.prepareToLeaveProcess((flags & DRAG_FLAG_GLOBAL) != 0);
29041             }
29042         }
29043 
29044         Rect bounds = new Rect();
29045         getBoundsOnScreen(bounds, true);
29046 
29047         Point lastTouchPoint = new Point();
29048         mAttachInfo.mViewRootImpl.getLastTouchPoint(lastTouchPoint);
29049         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
29050 
29051         // Skip surface logic since shadows and animation are not required during the a11y drag
29052         final boolean a11yEnabled = AccessibilityManager.getInstance(mContext).isEnabled();
29053         if (a11yEnabled && (flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) != 0) {
29054             try {
29055                 IBinder token = mAttachInfo.mSession.performDrag(
29056                         mAttachInfo.mWindow, flags, null,
29057                         mAttachInfo.mViewRootImpl.getLastTouchSource(),
29058                         mAttachInfo.mViewRootImpl.getLastTouchDeviceId(),
29059                         mAttachInfo.mViewRootImpl.getLastTouchPointerId(),
29060                         0f, 0f, 0f, 0f, data);
29061                 if (ViewDebug.DEBUG_DRAG) {
29062                     Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
29063                 }
29064                 if (token != null) {
29065                     root.setLocalDragState(myLocalState);
29066                     mAttachInfo.mDragToken = token;
29067                     mAttachInfo.mDragData = data;
29068                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
29069                     setAccessibilityDragStarted(true);
29070                 }
29071                 return token != null;
29072             } catch (Exception e) {
29073                 Log.e(VIEW_LOG_TAG, "Unable to initiate a11y drag", e);
29074                 return false;
29075             }
29076         }
29077 
29078         Point shadowSize = new Point();
29079         Point shadowTouchPoint = new Point();
29080         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
29081 
29082         if ((shadowSize.x < 0) || (shadowSize.y < 0)
29083                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
29084             throw new IllegalStateException("Drag shadow dimensions must not be negative");
29085         }
29086         final float overrideInvScale = CompatibilityInfo.getOverrideInvertedScale();
29087         if (overrideInvScale != 1f) {
29088             shadowTouchPoint.x = (int) (shadowTouchPoint.x / overrideInvScale);
29089             shadowTouchPoint.y = (int) (shadowTouchPoint.y / overrideInvScale);
29090         }
29091 
29092         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
29093         // does not accept zero size surface.
29094         if (shadowSize.x == 0  || shadowSize.y == 0) {
29095             if (!sAcceptZeroSizeDragShadow) {
29096                 throw new IllegalStateException("Drag shadow dimensions must be positive");
29097             }
29098             shadowSize.x = 1;
29099             shadowSize.y = 1;
29100         }
29101 
29102         if (ViewDebug.DEBUG_DRAG) {
29103             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
29104                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
29105         }
29106 
29107         final SurfaceSession session = new SurfaceSession();
29108         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
29109                 .setName("drag surface")
29110                 .setParent(root.getSurfaceControl())
29111                 .setBufferSize(shadowSize.x, shadowSize.y)
29112                 .setFormat(PixelFormat.TRANSLUCENT)
29113                 .setCallsite("View.startDragAndDrop")
29114                 .build();
29115         if (overrideInvScale != 1f) {
29116             final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
29117             transaction.setMatrix(surfaceControl, 1 / overrideInvScale, 0, 0, 1 / overrideInvScale)
29118                     .apply();
29119         }
29120         final Surface surface = new Surface();
29121         surface.copyFrom(surfaceControl);
29122         IBinder token = null;
29123         try {
29124             Trace.traceBegin(TRACE_TAG_VIEW, "startDragAndDrop#drawDragShadow");
29125             final Canvas canvas = isHardwareAccelerated()
29126                     ? surface.lockHardwareCanvas()
29127                     : surface.lockCanvas(null);
29128             try {
29129                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
29130                 shadowBuilder.onDrawShadow(canvas);
29131             } finally {
29132                 surface.unlockCanvasAndPost(canvas);
29133                 Trace.traceEnd(TRACE_TAG_VIEW);
29134             }
29135 
29136             Trace.traceBegin(TRACE_TAG_VIEW, "startDragAndDrop#performDrag");
29137             try {
29138                 token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
29139                         root.getLastTouchSource(), root.getLastTouchDeviceId(),
29140                         root.getLastTouchPointerId(), lastTouchPoint.x, lastTouchPoint.y,
29141                         shadowTouchPoint.x, shadowTouchPoint.y, data);
29142                 if (ViewDebug.DEBUG_DRAG) {
29143                     Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
29144                 }
29145                 if (token != null) {
29146                     if (mAttachInfo.mDragSurface != null) {
29147                         mAttachInfo.mDragSurface.release();
29148                     }
29149                     if (mAttachInfo.mDragData != null) {
29150                         // Clean up previous drag data intents
29151                         View.cleanUpPendingIntents(mAttachInfo.mDragData);
29152                     }
29153                     mAttachInfo.mDragSurface = surface;
29154                     mAttachInfo.mDragToken = token;
29155                     mAttachInfo.mDragData = data;
29156                     // Cache the local state object for delivery with DragEvents
29157                     root.setLocalDragState(myLocalState);
29158                     if (a11yEnabled) {
29159                         // Set for AccessibilityEvents
29160                         mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
29161                     }
29162                 }
29163                 return token != null;
29164             } finally {
29165                 Trace.traceEnd(TRACE_TAG_VIEW);
29166             }
29167         } catch (Exception e) {
29168             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
29169             return false;
29170         } finally {
29171             if (token == null) {
29172                 surface.destroy();
29173             }
29174             session.kill();
29175             surfaceControl.release();
29176         }
29177     }
29178 
29179      /**
29180      * Checks if this clip data has a pending intent that is an activity type.
29181      * @hide
29182      */
hasActivityPendingIntents(ClipData data)29183     static boolean hasActivityPendingIntents(ClipData data) {
29184         final int size = data.getItemCount();
29185         for (int i = 0; i < size; i++) {
29186             final ClipData.Item item = data.getItemAt(i);
29187             if (item.getIntentSender() != null) {
29188                 final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());
29189                 if (pi.isActivity()) {
29190                     return true;
29191                 }
29192             }
29193         }
29194         return false;
29195     }
29196 
29197     /**
29198      * Cleans up all pending intents in the ClipData.
29199      * @hide
29200      */
cleanUpPendingIntents(ClipData data)29201     static void cleanUpPendingIntents(ClipData data) {
29202         final int size = data.getItemCount();
29203         for (int i = 0; i < size; i++) {
29204             final ClipData.Item item = data.getItemAt(i);
29205             if (item.getIntentSender() != null) {
29206                 final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());
29207                 pi.cancel();
29208             }
29209         }
29210     }
29211 
setAccessibilityDragStarted(boolean started)29212     void setAccessibilityDragStarted(boolean started) {
29213         int pflags4 = mPrivateFlags4;
29214         if (started) {
29215             pflags4 |= PFLAG4_DRAG_A11Y_STARTED;
29216         } else {
29217             pflags4 &= ~PFLAG4_DRAG_A11Y_STARTED;
29218         }
29219 
29220         if (pflags4 != mPrivateFlags4) {
29221             mPrivateFlags4 = pflags4;
29222             sendWindowContentChangedAccessibilityEvent(CONTENT_CHANGE_TYPE_UNDEFINED);
29223         }
29224     }
29225 
startedSystemDragForAccessibility()29226     private boolean startedSystemDragForAccessibility() {
29227         return (mPrivateFlags4 & PFLAG4_DRAG_A11Y_STARTED) != 0;
29228     }
29229 
29230     /**
29231      * Cancels an ongoing drag and drop operation.
29232      * <p>
29233      * A {@link android.view.DragEvent} object with
29234      * {@link android.view.DragEvent#getAction()} value of
29235      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
29236      * {@link android.view.DragEvent#getResult()} value of {@code false}
29237      * will be sent to every
29238      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
29239      * even if they are not currently visible.
29240      * </p>
29241      * <p>
29242      * This method can be called on any View in the same window as the View on which
29243      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
29244      * was called.
29245      * </p>
29246      */
cancelDragAndDrop()29247     public final void cancelDragAndDrop() {
29248         if (ViewDebug.DEBUG_DRAG) {
29249             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
29250         }
29251         if (mAttachInfo == null) {
29252             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
29253             return;
29254         }
29255         if (mAttachInfo.mDragToken != null) {
29256             try {
29257                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
29258             } catch (Exception e) {
29259                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
29260             }
29261             mAttachInfo.mDragToken = null;
29262         } else {
29263             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
29264         }
29265     }
29266 
29267     /**
29268      * Updates the drag shadow for the ongoing drag and drop operation.
29269      *
29270      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
29271      * new drag shadow.
29272      */
updateDragShadow(DragShadowBuilder shadowBuilder)29273     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
29274         if (ViewDebug.DEBUG_DRAG) {
29275             Log.d(VIEW_LOG_TAG, "updateDragShadow");
29276         }
29277         if (mAttachInfo == null) {
29278             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
29279             return;
29280         }
29281         if (mAttachInfo.mDragToken != null) {
29282             try {
29283                 Canvas canvas = isHardwareAccelerated()
29284                         ? mAttachInfo.mDragSurface.lockHardwareCanvas()
29285                         : mAttachInfo.mDragSurface.lockCanvas(null);
29286                 try {
29287                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
29288                     shadowBuilder.onDrawShadow(canvas);
29289                 } finally {
29290                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
29291                 }
29292             } catch (Exception e) {
29293                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
29294             }
29295         } else {
29296             Log.e(VIEW_LOG_TAG, "No active drag");
29297         }
29298     }
29299 
29300     /**
29301      * Starts a move from {startX, startY}, the amount of the movement will be the offset
29302      * between {startX, startY} and the new cursor positon.
29303      * @param startX horizontal coordinate where the move started.
29304      * @param startY vertical coordinate where the move started.
29305      * @return whether moving was started successfully.
29306      * @hide
29307      */
startMovingTask(float startX, float startY)29308     public final boolean startMovingTask(float startX, float startY) {
29309         if (ViewDebug.DEBUG_POSITIONING) {
29310             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
29311         }
29312         try {
29313             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
29314         } catch (RemoteException e) {
29315             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
29316         }
29317         return false;
29318     }
29319 
29320     /**
29321      * Finish a window move task.
29322      * @hide
29323      */
finishMovingTask()29324     public void finishMovingTask() {
29325         if (ViewDebug.DEBUG_POSITIONING) {
29326             Log.d(VIEW_LOG_TAG, "finishMovingTask");
29327         }
29328         try {
29329             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
29330         } catch (RemoteException e) {
29331             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
29332         }
29333     }
29334 
29335     /**
29336      * Handles drag events sent by the system following a call to
29337      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
29338      * startDragAndDrop()}.
29339      * <p>
29340      * The system calls this method and passes a {@link DragEvent} object in response to drag and
29341      * drop events. This method can then call {@link DragEvent#getAction()} to determine the state
29342      * of the drag and drop operation.
29343      * <p>
29344      * The default implementation returns {@code false} unless an {@link OnReceiveContentListener}
29345      * has been set for this view (see {@link #setOnReceiveContentListener}), in which case
29346      * the default implementation does the following:
29347      * <ul>
29348      *   <li>Returns {@code true} for an
29349      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
29350      *   <li>Calls {@link #performReceiveContent} for an
29351      *     {@link DragEvent#ACTION_DROP ACTION_DROP} event
29352      *   <li>Returns {@code true} for an {@link DragEvent#ACTION_DROP ACTION_DROP} event if the
29353      *     {@code OnReceiveContentListener} consumed some or all of the content
29354      * </ul>
29355      *
29356      * @param event The {@link DragEvent} object sent by the system. The
29357      *   {@link DragEvent#getAction()} method returns an action type constant that indicates the
29358      *   type of drag event represented by this object.
29359      * @return {@code true} if the method successfully handled the drag event, otherwise
29360      *   {@code false}.
29361      *   <p>
29362      *     The method must return {@code true} in response to an
29363      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} action type to continue to
29364      *     receive drag events for the current drag and drop operation.
29365      *   <p>
29366      *     The method should return {@code true} in response to an
29367      *     {@link DragEvent#ACTION_DROP ACTION_DROP} action type if the dropped data was consumed
29368      *     (at least partially); {@code false}, if none of the data was consumed.
29369      *   <p>
29370      *     For all other events, the return value is {@code false}.
29371      */
onDragEvent(DragEvent event)29372     public boolean onDragEvent(DragEvent event) {
29373         if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
29374             return false;
29375         }
29376         // Accept drag events by default if there's an OnReceiveContentListener set.
29377         if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
29378             return true;
29379         }
29380         if (event.getAction() == DragEvent.ACTION_DROP) {
29381             final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
29382             if (permissions != null) {
29383                 permissions.takeTransient();
29384             }
29385             final ContentInfo payload =
29386                     new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
29387                             .setDragAndDropPermissions(permissions)
29388                             .build();
29389             ContentInfo remainingPayload = performReceiveContent(payload);
29390             // Return true unless none of the payload was consumed.
29391             return remainingPayload != payload;
29392         }
29393         return false;
29394     }
29395 
29396     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)29397     boolean dispatchDragEnterExitInPreN(DragEvent event) {
29398         return callDragEventHandler(event);
29399     }
29400 
29401     /**
29402      * Detects if this View is enabled and has a drag event listener.
29403      * If both are true, then it calls the drag event listener with the
29404      * {@link android.view.DragEvent} it received. If the drag event listener returns
29405      * {@code true}, then dispatchDragEvent() returns {@code true}.
29406      * <p>
29407      * For all other cases, the method calls the
29408      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
29409      * method and returns its result.
29410      * </p>
29411      * <p>
29412      * This ensures that a drag event is always consumed, even if the View does not have a drag
29413      * event listener. However, if the View has a listener and the listener returns true, then
29414      * onDragEvent() is not called.
29415      * </p>
29416      */
dispatchDragEvent(DragEvent event)29417     public boolean dispatchDragEvent(DragEvent event) {
29418         event.mEventHandlerWasCalled = true;
29419         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
29420             event.mAction == DragEvent.ACTION_DROP) {
29421             // About to deliver an event with coordinates to this view. Notify that now this view
29422             // has drag focus. This will send exit/enter events as needed.
29423             getViewRootImpl().setDragFocus(this, event);
29424         }
29425         return callDragEventHandler(event);
29426     }
29427 
callDragEventHandler(DragEvent event)29428     final boolean callDragEventHandler(DragEvent event) {
29429         final boolean result;
29430 
29431         ListenerInfo li = mListenerInfo;
29432         //noinspection SimplifiableIfStatement
29433         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
29434                 && li.mOnDragListener.onDrag(this, event)) {
29435             result = true;
29436         } else {
29437             result = onDragEvent(event);
29438         }
29439 
29440         switch (event.mAction) {
29441             case DragEvent.ACTION_DRAG_STARTED: {
29442                 if (result && li != null && li.mOnDragListener != null) {
29443                     sendWindowContentChangedAccessibilityEvent(
29444                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
29445                 }
29446             } break;
29447             case DragEvent.ACTION_DRAG_ENTERED: {
29448                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
29449                 refreshDrawableState();
29450             } break;
29451             case DragEvent.ACTION_DRAG_EXITED: {
29452                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
29453                 refreshDrawableState();
29454             } break;
29455             case DragEvent.ACTION_DROP: {
29456                 if (result && li != null && (li.mOnDragListener != null
29457                         || li.mOnReceiveContentListener != null)) {
29458                     sendWindowContentChangedAccessibilityEvent(
29459                             AccessibilityEvent.CONTENT_CHANGE_TYPE_DRAG_DROPPED);
29460                 }
29461             } break;
29462             case DragEvent.ACTION_DRAG_ENDED: {
29463                 sendWindowContentChangedAccessibilityEvent(
29464                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
29465                 mPrivateFlags2 &= ~View.DRAG_MASK;
29466                 refreshDrawableState();
29467             } break;
29468         }
29469 
29470         return result;
29471     }
29472 
canAcceptDrag()29473     boolean canAcceptDrag() {
29474         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
29475     }
29476 
sendWindowContentChangedAccessibilityEvent(int changeType)29477     void sendWindowContentChangedAccessibilityEvent(int changeType) {
29478         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
29479             AccessibilityEvent event = AccessibilityEvent.obtain();
29480             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
29481             event.setContentChangeTypes(changeType);
29482             sendAccessibilityEventUnchecked(event);
29483         }
29484     }
29485 
29486     /**
29487      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
29488      * it is ever exposed at all.
29489      * @hide
29490      */
29491     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)29492     public void onCloseSystemDialogs(String reason) {
29493     }
29494 
29495     /**
29496      * Given a Drawable whose bounds have been set to draw into this view,
29497      * update a Region being computed for
29498      * {@link #gatherTransparentRegion(android.graphics.Region)} so
29499      * that any non-transparent parts of the Drawable are removed from the
29500      * given transparent region.
29501      *
29502      * @param dr The Drawable whose transparency is to be applied to the region.
29503      * @param region A Region holding the current transparency information,
29504      * where any parts of the region that are set are considered to be
29505      * transparent.  On return, this region will be modified to have the
29506      * transparency information reduced by the corresponding parts of the
29507      * Drawable that are not transparent.
29508      * {@hide}
29509      */
29510     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
applyDrawableToTransparentRegion(Drawable dr, Region region)29511     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
29512         if (DBG) {
29513             Log.i("View", "Getting transparent region for: " + this);
29514         }
29515         final Region r = dr.getTransparentRegion();
29516         final Rect db = dr.getBounds();
29517         final AttachInfo attachInfo = mAttachInfo;
29518         if (r != null && attachInfo != null) {
29519             final int w = getRight()-getLeft();
29520             final int h = getBottom()-getTop();
29521             if (db.left > 0) {
29522                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
29523                 r.op(0, 0, db.left, h, Region.Op.UNION);
29524             }
29525             if (db.right < w) {
29526                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
29527                 r.op(db.right, 0, w, h, Region.Op.UNION);
29528             }
29529             if (db.top > 0) {
29530                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
29531                 r.op(0, 0, w, db.top, Region.Op.UNION);
29532             }
29533             if (db.bottom < h) {
29534                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
29535                 r.op(0, db.bottom, w, h, Region.Op.UNION);
29536             }
29537             final int[] location = attachInfo.mTransparentLocation;
29538             getLocationInWindow(location);
29539             r.translate(location[0], location[1]);
29540             region.op(r, Region.Op.INTERSECT);
29541         } else {
29542             region.op(db, Region.Op.DIFFERENCE);
29543         }
29544     }
29545 
checkForLongClick(long delay, float x, float y, int classification)29546     private void checkForLongClick(long delay, float x, float y, int classification) {
29547         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
29548             mHasPerformedLongPress = false;
29549 
29550             if (mPendingCheckForLongPress == null) {
29551                 mPendingCheckForLongPress = new CheckForLongPress();
29552             }
29553             mPendingCheckForLongPress.setAnchor(x, y);
29554             mPendingCheckForLongPress.rememberWindowAttachCount();
29555             mPendingCheckForLongPress.rememberPressedState();
29556             mPendingCheckForLongPress.setClassification(classification);
29557             postDelayed(mPendingCheckForLongPress, delay);
29558         }
29559     }
29560 
29561     /**
29562      * Inflate a view from an XML resource.  This convenience method wraps the {@link
29563      * LayoutInflater} class, which provides a full range of options for view inflation.
29564      *
29565      * @param context The Context object for your activity or application.
29566      * @param resource The resource ID to inflate
29567      * @param root A view group that will be the parent.  Used to properly inflate the
29568      * layout_* parameters.
29569      * @see LayoutInflater
29570      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)29571     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
29572         LayoutInflater factory = LayoutInflater.from(context);
29573         return factory.inflate(resource, root);
29574     }
29575 
29576     /**
29577      * Scroll the view with standard behavior for scrolling beyond the normal
29578      * content boundaries. Views that call this method should override
29579      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
29580      * results of an over-scroll operation.
29581      *
29582      * Views can use this method to handle any touch or fling-based scrolling.
29583      *
29584      * @param deltaX Change in X in pixels
29585      * @param deltaY Change in Y in pixels
29586      * @param scrollX Current X scroll value in pixels before applying deltaX
29587      * @param scrollY Current Y scroll value in pixels before applying deltaY
29588      * @param scrollRangeX Maximum content scroll range along the X axis
29589      * @param scrollRangeY Maximum content scroll range along the Y axis
29590      * @param maxOverScrollX Number of pixels to overscroll by in either direction
29591      *          along the X axis.
29592      * @param maxOverScrollY Number of pixels to overscroll by in either direction
29593      *          along the Y axis.
29594      * @param isTouchEvent true if this scroll operation is the result of a touch event.
29595      * @return true if scrolling was clamped to an over-scroll boundary along either
29596      *          axis, false otherwise.
29597      */
29598     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)29599     protected boolean overScrollBy(int deltaX, int deltaY,
29600             int scrollX, int scrollY,
29601             int scrollRangeX, int scrollRangeY,
29602             int maxOverScrollX, int maxOverScrollY,
29603             boolean isTouchEvent) {
29604         final int overScrollMode = mOverScrollMode;
29605         final boolean canScrollHorizontal =
29606                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
29607         final boolean canScrollVertical =
29608                 computeVerticalScrollRange() > computeVerticalScrollExtent();
29609         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
29610                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
29611         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
29612                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
29613 
29614         int newScrollX = scrollX + deltaX;
29615         if (!overScrollHorizontal) {
29616             maxOverScrollX = 0;
29617         }
29618 
29619         int newScrollY = scrollY + deltaY;
29620         if (!overScrollVertical) {
29621             maxOverScrollY = 0;
29622         }
29623 
29624         // Clamp values if at the limits and record
29625         final int left = -maxOverScrollX;
29626         final int right = maxOverScrollX + scrollRangeX;
29627         final int top = -maxOverScrollY;
29628         final int bottom = maxOverScrollY + scrollRangeY;
29629 
29630         boolean clampedX = false;
29631         if (newScrollX > right) {
29632             newScrollX = right;
29633             clampedX = true;
29634         } else if (newScrollX < left) {
29635             newScrollX = left;
29636             clampedX = true;
29637         }
29638 
29639         boolean clampedY = false;
29640         if (newScrollY > bottom) {
29641             newScrollY = bottom;
29642             clampedY = true;
29643         } else if (newScrollY < top) {
29644             newScrollY = top;
29645             clampedY = true;
29646         }
29647 
29648         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
29649 
29650         return clampedX || clampedY;
29651     }
29652 
29653     /**
29654      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
29655      * respond to the results of an over-scroll operation.
29656      *
29657      * @param scrollX New X scroll value in pixels
29658      * @param scrollY New Y scroll value in pixels
29659      * @param clampedX True if scrollX was clamped to an over-scroll boundary
29660      * @param clampedY True if scrollY was clamped to an over-scroll boundary
29661      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)29662     protected void onOverScrolled(int scrollX, int scrollY,
29663             boolean clampedX, boolean clampedY) {
29664         // Intentionally empty.
29665     }
29666 
29667     /**
29668      * Returns the over-scroll mode for this view. The result will be
29669      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
29670      * (allow over-scrolling only if the view content is larger than the container),
29671      * or {@link #OVER_SCROLL_NEVER}.
29672      *
29673      * @return This view's over-scroll mode.
29674      */
29675     @InspectableProperty(enumMapping = {
29676             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
29677             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
29678             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
29679     })
getOverScrollMode()29680     public int getOverScrollMode() {
29681         return mOverScrollMode;
29682     }
29683 
29684     /**
29685      * Set the over-scroll mode for this view. Valid over-scroll modes are
29686      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
29687      * (allow over-scrolling only if the view content is larger than the container),
29688      * or {@link #OVER_SCROLL_NEVER}.
29689      *
29690      * Setting the over-scroll mode of a view will have an effect only if the
29691      * view is capable of scrolling.
29692      *
29693      * @param overScrollMode The new over-scroll mode for this view.
29694      */
setOverScrollMode(int overScrollMode)29695     public void setOverScrollMode(int overScrollMode) {
29696         if (overScrollMode != OVER_SCROLL_ALWAYS &&
29697                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
29698                 overScrollMode != OVER_SCROLL_NEVER) {
29699             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
29700         }
29701         mOverScrollMode = overScrollMode;
29702     }
29703 
29704     /**
29705      * Enable or disable nested scrolling for this view.
29706      *
29707      * <p>If this property is set to true the view will be permitted to initiate nested
29708      * scrolling operations with a compatible parent view in the current hierarchy. If this
29709      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
29710      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
29711      * the nested scroll.</p>
29712      *
29713      * @param enabled true to enable nested scrolling, false to disable
29714      *
29715      * @see #isNestedScrollingEnabled()
29716      */
setNestedScrollingEnabled(boolean enabled)29717     public void setNestedScrollingEnabled(boolean enabled) {
29718         if (enabled) {
29719             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
29720         } else {
29721             stopNestedScroll();
29722             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
29723         }
29724     }
29725 
29726     /**
29727      * Returns true if nested scrolling is enabled for this view.
29728      *
29729      * <p>If nested scrolling is enabled and this View class implementation supports it,
29730      * this view will act as a nested scrolling child view when applicable, forwarding data
29731      * about the scroll operation in progress to a compatible and cooperating nested scrolling
29732      * parent.</p>
29733      *
29734      * @return true if nested scrolling is enabled
29735      *
29736      * @see #setNestedScrollingEnabled(boolean)
29737      */
29738     @InspectableProperty
isNestedScrollingEnabled()29739     public boolean isNestedScrollingEnabled() {
29740         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
29741                 PFLAG3_NESTED_SCROLLING_ENABLED;
29742     }
29743 
29744     /**
29745      * Begin a nestable scroll operation along the given axes.
29746      *
29747      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
29748      *
29749      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
29750      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
29751      * In the case of touch scrolling the nested scroll will be terminated automatically in
29752      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
29753      * In the event of programmatic scrolling the caller must explicitly call
29754      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
29755      *
29756      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
29757      * If it returns false the caller may ignore the rest of this contract until the next scroll.
29758      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
29759      *
29760      * <p>At each incremental step of the scroll the caller should invoke
29761      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
29762      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
29763      * parent at least partially consumed the scroll and the caller should adjust the amount it
29764      * scrolls by.</p>
29765      *
29766      * <p>After applying the remainder of the scroll delta the caller should invoke
29767      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
29768      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
29769      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
29770      * </p>
29771      *
29772      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
29773      *             {@link #SCROLL_AXIS_VERTICAL}.
29774      * @return true if a cooperative parent was found and nested scrolling has been enabled for
29775      *         the current gesture.
29776      *
29777      * @see #stopNestedScroll()
29778      * @see #dispatchNestedPreScroll(int, int, int[], int[])
29779      * @see #dispatchNestedScroll(int, int, int, int, int[])
29780      */
startNestedScroll(int axes)29781     public boolean startNestedScroll(int axes) {
29782         if (hasNestedScrollingParent()) {
29783             // Already in progress
29784             return true;
29785         }
29786         if (isNestedScrollingEnabled()) {
29787             ViewParent p = getParent();
29788             View child = this;
29789             while (p != null) {
29790                 try {
29791                     if (p.onStartNestedScroll(child, this, axes)) {
29792                         mNestedScrollingParent = p;
29793                         p.onNestedScrollAccepted(child, this, axes);
29794                         return true;
29795                     }
29796                 } catch (AbstractMethodError e) {
29797                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
29798                             "method onStartNestedScroll", e);
29799                     // Allow the search upward to continue
29800                 }
29801                 if (p instanceof View) {
29802                     child = (View) p;
29803                 }
29804                 p = p.getParent();
29805             }
29806         }
29807         return false;
29808     }
29809 
29810     /**
29811      * Stop a nested scroll in progress.
29812      *
29813      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
29814      *
29815      * @see #startNestedScroll(int)
29816      */
stopNestedScroll()29817     public void stopNestedScroll() {
29818         if (mNestedScrollingParent != null) {
29819             mNestedScrollingParent.onStopNestedScroll(this);
29820             mNestedScrollingParent = null;
29821         }
29822     }
29823 
29824     /**
29825      * Returns true if this view has a nested scrolling parent.
29826      *
29827      * <p>The presence of a nested scrolling parent indicates that this view has initiated
29828      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
29829      *
29830      * @return whether this view has a nested scrolling parent
29831      */
hasNestedScrollingParent()29832     public boolean hasNestedScrollingParent() {
29833         return mNestedScrollingParent != null;
29834     }
29835 
29836     /**
29837      * Dispatch one step of a nested scroll in progress.
29838      *
29839      * <p>Implementations of views that support nested scrolling should call this to report
29840      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
29841      * is not currently in progress or nested scrolling is not
29842      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
29843      *
29844      * <p>Compatible View implementations should also call
29845      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
29846      * consuming a component of the scroll event themselves.</p>
29847      *
29848      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
29849      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
29850      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
29851      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
29852      * @param offsetInWindow Optional. If not null, on return this will contain the offset
29853      *                       in local view coordinates of this view from before this operation
29854      *                       to after it completes. View implementations may use this to adjust
29855      *                       expected input coordinate tracking.
29856      * @return true if the event was dispatched, false if it could not be dispatched.
29857      * @see #dispatchNestedPreScroll(int, int, int[], int[])
29858      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)29859     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
29860             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
29861         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
29862             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
29863                 int startX = 0;
29864                 int startY = 0;
29865                 if (offsetInWindow != null) {
29866                     getLocationInWindow(offsetInWindow);
29867                     startX = offsetInWindow[0];
29868                     startY = offsetInWindow[1];
29869                 }
29870 
29871                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
29872                         dxUnconsumed, dyUnconsumed);
29873 
29874                 if (offsetInWindow != null) {
29875                     getLocationInWindow(offsetInWindow);
29876                     offsetInWindow[0] -= startX;
29877                     offsetInWindow[1] -= startY;
29878                 }
29879                 return true;
29880             } else if (offsetInWindow != null) {
29881                 // No motion, no dispatch. Keep offsetInWindow up to date.
29882                 offsetInWindow[0] = 0;
29883                 offsetInWindow[1] = 0;
29884             }
29885         }
29886         return false;
29887     }
29888 
29889     /**
29890      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
29891      *
29892      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
29893      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
29894      * scrolling operation to consume some or all of the scroll operation before the child view
29895      * consumes it.</p>
29896      *
29897      * @param dx Horizontal scroll distance in pixels
29898      * @param dy Vertical scroll distance in pixels
29899      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
29900      *                 and consumed[1] the consumed dy.
29901      * @param offsetInWindow Optional. If not null, on return this will contain the offset
29902      *                       in local view coordinates of this view from before this operation
29903      *                       to after it completes. View implementations may use this to adjust
29904      *                       expected input coordinate tracking.
29905      * @return true if the parent consumed some or all of the scroll delta
29906      * @see #dispatchNestedScroll(int, int, int, int, int[])
29907      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)29908     public boolean dispatchNestedPreScroll(int dx, int dy,
29909             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
29910         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
29911             if (dx != 0 || dy != 0) {
29912                 int startX = 0;
29913                 int startY = 0;
29914                 if (offsetInWindow != null) {
29915                     getLocationInWindow(offsetInWindow);
29916                     startX = offsetInWindow[0];
29917                     startY = offsetInWindow[1];
29918                 }
29919 
29920                 if (consumed == null) {
29921                     if (mTempNestedScrollConsumed == null) {
29922                         mTempNestedScrollConsumed = new int[2];
29923                     }
29924                     consumed = mTempNestedScrollConsumed;
29925                 }
29926                 consumed[0] = 0;
29927                 consumed[1] = 0;
29928                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
29929 
29930                 if (offsetInWindow != null) {
29931                     getLocationInWindow(offsetInWindow);
29932                     offsetInWindow[0] -= startX;
29933                     offsetInWindow[1] -= startY;
29934                 }
29935                 return consumed[0] != 0 || consumed[1] != 0;
29936             } else if (offsetInWindow != null) {
29937                 offsetInWindow[0] = 0;
29938                 offsetInWindow[1] = 0;
29939             }
29940         }
29941         return false;
29942     }
29943 
29944     /**
29945      * Dispatch a fling to a nested scrolling parent.
29946      *
29947      * <p>This method should be used to indicate that a nested scrolling child has detected
29948      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
29949      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
29950      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
29951      * along a scrollable axis.</p>
29952      *
29953      * <p>If a nested scrolling child view would normally fling but it is at the edge of
29954      * its own content, it can use this method to delegate the fling to its nested scrolling
29955      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
29956      *
29957      * @param velocityX Horizontal fling velocity in pixels per second
29958      * @param velocityY Vertical fling velocity in pixels per second
29959      * @param consumed true if the child consumed the fling, false otherwise
29960      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
29961      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)29962     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
29963         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
29964             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
29965         }
29966         return false;
29967     }
29968 
29969     /**
29970      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
29971      *
29972      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
29973      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
29974      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
29975      * before the child view consumes it. If this method returns <code>true</code>, a nested
29976      * parent view consumed the fling and this view should not scroll as a result.</p>
29977      *
29978      * <p>For a better user experience, only one view in a nested scrolling chain should consume
29979      * the fling at a time. If a parent view consumed the fling this method will return false.
29980      * Custom view implementations should account for this in two ways:</p>
29981      *
29982      * <ul>
29983      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
29984      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
29985      *     position regardless.</li>
29986      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
29987      *     even to settle back to a valid idle position.</li>
29988      * </ul>
29989      *
29990      * <p>Views should also not offer fling velocities to nested parent views along an axis
29991      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
29992      * should not offer a horizontal fling velocity to its parents since scrolling along that
29993      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
29994      *
29995      * @param velocityX Horizontal fling velocity in pixels per second
29996      * @param velocityY Vertical fling velocity in pixels per second
29997      * @return true if a nested scrolling parent consumed the fling
29998      */
dispatchNestedPreFling(float velocityX, float velocityY)29999     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
30000         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
30001             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
30002         }
30003         return false;
30004     }
30005 
30006     /**
30007      * Gets a scale factor that determines the distance the view should scroll
30008      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
30009      * @return The vertical scroll scale factor.
30010      * @hide
30011      */
30012     @UnsupportedAppUsage
getVerticalScrollFactor()30013     protected float getVerticalScrollFactor() {
30014         if (mVerticalScrollFactor == 0) {
30015             TypedValue outValue = new TypedValue();
30016             if (!mContext.getTheme().resolveAttribute(
30017                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
30018                 throw new IllegalStateException(
30019                         "Expected theme to define listPreferredItemHeight.");
30020             }
30021             mVerticalScrollFactor = outValue.getDimension(
30022                     mContext.getResources().getDisplayMetrics());
30023         }
30024         return mVerticalScrollFactor;
30025     }
30026 
30027     /**
30028      * Gets a scale factor that determines the distance the view should scroll
30029      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
30030      * @return The horizontal scroll scale factor.
30031      * @hide
30032      */
30033     @UnsupportedAppUsage
getHorizontalScrollFactor()30034     protected float getHorizontalScrollFactor() {
30035         // TODO: Should use something else.
30036         return getVerticalScrollFactor();
30037     }
30038 
30039     /**
30040      * Return the value specifying the text direction or policy that was set with
30041      * {@link #setTextDirection(int)}.
30042      *
30043      * @return the defined text direction. It can be one of:
30044      *
30045      * {@link #TEXT_DIRECTION_INHERIT},
30046      * {@link #TEXT_DIRECTION_FIRST_STRONG},
30047      * {@link #TEXT_DIRECTION_ANY_RTL},
30048      * {@link #TEXT_DIRECTION_LTR},
30049      * {@link #TEXT_DIRECTION_RTL},
30050      * {@link #TEXT_DIRECTION_LOCALE},
30051      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
30052      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
30053      *
30054      * @attr ref android.R.styleable#View_textDirection
30055      *
30056      * @hide
30057      */
30058     @ViewDebug.ExportedProperty(category = "text", mapping = {
30059             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
30060             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
30061             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
30062             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
30063             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
30064             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
30065             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
30066             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
30067     })
30068     @InspectableProperty(hasAttributeId = false, enumMapping = {
30069             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
30070             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
30071             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
30072             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
30073             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
30074             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
30075             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
30076             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
30077     })
30078     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextDirection()30079     public int getRawTextDirection() {
30080         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
30081     }
30082 
30083     /**
30084      * Set the text direction.
30085      *
30086      * @param textDirection the direction to set. Should be one of:
30087      *
30088      * {@link #TEXT_DIRECTION_INHERIT},
30089      * {@link #TEXT_DIRECTION_FIRST_STRONG},
30090      * {@link #TEXT_DIRECTION_ANY_RTL},
30091      * {@link #TEXT_DIRECTION_LTR},
30092      * {@link #TEXT_DIRECTION_RTL},
30093      * {@link #TEXT_DIRECTION_LOCALE}
30094      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
30095      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
30096      *
30097      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
30098      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
30099      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
30100      *
30101      * @attr ref android.R.styleable#View_textDirection
30102      */
setTextDirection(int textDirection)30103     public void setTextDirection(int textDirection) {
30104         if (getRawTextDirection() != textDirection) {
30105             // Reset the current text direction and the resolved one
30106             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
30107             resetResolvedTextDirection();
30108             // Set the new text direction
30109             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
30110             // Do resolution
30111             resolveTextDirection();
30112             // Notify change
30113             onRtlPropertiesChanged(getLayoutDirection());
30114             // Refresh
30115             requestLayout();
30116             invalidate(true);
30117         }
30118     }
30119 
30120     /**
30121      * Return the resolved text direction.
30122      *
30123      * @return the resolved text direction. Returns one of:
30124      *
30125      * {@link #TEXT_DIRECTION_FIRST_STRONG},
30126      * {@link #TEXT_DIRECTION_ANY_RTL},
30127      * {@link #TEXT_DIRECTION_LTR},
30128      * {@link #TEXT_DIRECTION_RTL},
30129      * {@link #TEXT_DIRECTION_LOCALE},
30130      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
30131      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
30132      *
30133      * @attr ref android.R.styleable#View_textDirection
30134      */
30135     @ViewDebug.ExportedProperty(category = "text", mapping = {
30136             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
30137             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
30138             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
30139             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
30140             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
30141             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
30142             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
30143             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
30144     })
30145     @InspectableProperty(hasAttributeId = false, enumMapping = {
30146             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
30147             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
30148             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
30149             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
30150             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
30151             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
30152             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
30153     })
getTextDirection()30154     public int getTextDirection() {
30155         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
30156     }
30157 
30158     /**
30159      * Resolve the text direction.
30160      *
30161      * @return true if resolution has been done, false otherwise.
30162      *
30163      * @hide
30164      */
resolveTextDirection()30165     public boolean resolveTextDirection() {
30166         // Reset any previous text direction resolution
30167         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
30168 
30169         if (hasRtlSupport()) {
30170             // Set resolved text direction flag depending on text direction flag
30171             final int textDirection = getRawTextDirection();
30172             switch(textDirection) {
30173                 case TEXT_DIRECTION_INHERIT:
30174                     if (!canResolveTextDirection()) {
30175                         // We cannot do the resolution if there is no parent, so use the default one
30176                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30177                         // Resolution will need to happen again later
30178                         return false;
30179                     }
30180 
30181                     // Parent has not yet resolved, so we still return the default
30182                     try {
30183                         if (!mParent.isTextDirectionResolved()) {
30184                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30185                             // Resolution will need to happen again later
30186                             return false;
30187                         }
30188                     } catch (AbstractMethodError e) {
30189                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30190                                 " does not fully implement ViewParent", e);
30191                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
30192                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30193                         return true;
30194                     }
30195 
30196                     // Set current resolved direction to the same value as the parent's one
30197                     int parentResolvedDirection;
30198                     try {
30199                         parentResolvedDirection = mParent.getTextDirection();
30200                     } catch (AbstractMethodError e) {
30201                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30202                                 " does not fully implement ViewParent", e);
30203                         parentResolvedDirection = TEXT_DIRECTION_LTR;
30204                     }
30205                     switch (parentResolvedDirection) {
30206                         case TEXT_DIRECTION_FIRST_STRONG:
30207                         case TEXT_DIRECTION_ANY_RTL:
30208                         case TEXT_DIRECTION_LTR:
30209                         case TEXT_DIRECTION_RTL:
30210                         case TEXT_DIRECTION_LOCALE:
30211                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
30212                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
30213                             mPrivateFlags2 |=
30214                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
30215                             break;
30216                         default:
30217                             // Default resolved direction is "first strong" heuristic
30218                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30219                     }
30220                     break;
30221                 case TEXT_DIRECTION_FIRST_STRONG:
30222                 case TEXT_DIRECTION_ANY_RTL:
30223                 case TEXT_DIRECTION_LTR:
30224                 case TEXT_DIRECTION_RTL:
30225                 case TEXT_DIRECTION_LOCALE:
30226                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
30227                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
30228                     // Resolved direction is the same as text direction
30229                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
30230                     break;
30231                 default:
30232                     // Default resolved direction is "first strong" heuristic
30233                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30234             }
30235         } else {
30236             // Default resolved direction is "first strong" heuristic
30237             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30238         }
30239 
30240         // Set to resolved
30241         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
30242         return true;
30243     }
30244 
30245     /**
30246      * Check if text direction resolution can be done.
30247      *
30248      * @return true if text direction resolution can be done otherwise return false.
30249      */
canResolveTextDirection()30250     public boolean canResolveTextDirection() {
30251         switch (getRawTextDirection()) {
30252             case TEXT_DIRECTION_INHERIT:
30253                 if (mParent != null) {
30254                     try {
30255                         return mParent.canResolveTextDirection();
30256                     } catch (AbstractMethodError e) {
30257                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30258                                 " does not fully implement ViewParent", e);
30259                     }
30260                 }
30261                 return false;
30262 
30263             default:
30264                 return true;
30265         }
30266     }
30267 
30268     /**
30269      * Reset resolved text direction. Text direction will be resolved during a call to
30270      * {@link #onMeasure(int, int)}.
30271      *
30272      * @hide
30273      */
30274     @TestApi
resetResolvedTextDirection()30275     public void resetResolvedTextDirection() {
30276         // Reset any previous text direction resolution
30277         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
30278         // Set to default value
30279         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30280     }
30281 
30282     /**
30283      * @return true if text direction is inherited.
30284      *
30285      * @hide
30286      */
isTextDirectionInherited()30287     public boolean isTextDirectionInherited() {
30288         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
30289     }
30290 
30291     /**
30292      * @return true if text direction is resolved.
30293      */
isTextDirectionResolved()30294     public boolean isTextDirectionResolved() {
30295         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
30296     }
30297 
30298     /**
30299      * Return the value specifying the text alignment or policy that was set with
30300      * {@link #setTextAlignment(int)}.
30301      *
30302      * @return the defined text alignment. It can be one of:
30303      *
30304      * {@link #TEXT_ALIGNMENT_INHERIT},
30305      * {@link #TEXT_ALIGNMENT_GRAVITY},
30306      * {@link #TEXT_ALIGNMENT_CENTER},
30307      * {@link #TEXT_ALIGNMENT_TEXT_START},
30308      * {@link #TEXT_ALIGNMENT_TEXT_END},
30309      * {@link #TEXT_ALIGNMENT_VIEW_START},
30310      * {@link #TEXT_ALIGNMENT_VIEW_END}
30311      *
30312      * @attr ref android.R.styleable#View_textAlignment
30313      *
30314      * @hide
30315      */
30316     @ViewDebug.ExportedProperty(category = "text", mapping = {
30317             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
30318             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
30319             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
30320             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
30321             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
30322             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
30323             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
30324     })
30325     @InspectableProperty(hasAttributeId = false, enumMapping = {
30326             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
30327             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
30328             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
30329             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
30330             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
30331             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
30332             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
30333     })
30334     @TextAlignment
30335     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextAlignment()30336     public int getRawTextAlignment() {
30337         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
30338     }
30339 
30340     /**
30341      * Set the text alignment.
30342      *
30343      * @param textAlignment The text alignment to set. Should be one of
30344      *
30345      * {@link #TEXT_ALIGNMENT_INHERIT},
30346      * {@link #TEXT_ALIGNMENT_GRAVITY},
30347      * {@link #TEXT_ALIGNMENT_CENTER},
30348      * {@link #TEXT_ALIGNMENT_TEXT_START},
30349      * {@link #TEXT_ALIGNMENT_TEXT_END},
30350      * {@link #TEXT_ALIGNMENT_VIEW_START},
30351      * {@link #TEXT_ALIGNMENT_VIEW_END}
30352      *
30353      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
30354      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
30355      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
30356      *
30357      * @attr ref android.R.styleable#View_textAlignment
30358      */
setTextAlignment(@extAlignment int textAlignment)30359     public void setTextAlignment(@TextAlignment int textAlignment) {
30360         if (textAlignment != getRawTextAlignment()) {
30361             // Reset the current and resolved text alignment
30362             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
30363             resetResolvedTextAlignment();
30364             // Set the new text alignment
30365             mPrivateFlags2 |=
30366                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
30367             // Do resolution
30368             resolveTextAlignment();
30369             // Notify change
30370             onRtlPropertiesChanged(getLayoutDirection());
30371             // Refresh
30372             requestLayout();
30373             invalidate(true);
30374         }
30375     }
30376 
30377     /**
30378      * Return the resolved text alignment.
30379      *
30380      * @return the resolved text alignment. Returns one of:
30381      *
30382      * {@link #TEXT_ALIGNMENT_GRAVITY},
30383      * {@link #TEXT_ALIGNMENT_CENTER},
30384      * {@link #TEXT_ALIGNMENT_TEXT_START},
30385      * {@link #TEXT_ALIGNMENT_TEXT_END},
30386      * {@link #TEXT_ALIGNMENT_VIEW_START},
30387      * {@link #TEXT_ALIGNMENT_VIEW_END}
30388      *
30389      * @attr ref android.R.styleable#View_textAlignment
30390      */
30391     @ViewDebug.ExportedProperty(category = "text", mapping = {
30392             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
30393             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
30394             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
30395             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
30396             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
30397             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
30398             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
30399     })
30400     @InspectableProperty(enumMapping = {
30401             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
30402             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
30403             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
30404             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
30405             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
30406             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
30407     })
30408     @TextAlignment
getTextAlignment()30409     public int getTextAlignment() {
30410         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
30411                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
30412     }
30413 
30414     /**
30415      * Resolve the text alignment.
30416      *
30417      * @return true if resolution has been done, false otherwise.
30418      *
30419      * @hide
30420      */
resolveTextAlignment()30421     public boolean resolveTextAlignment() {
30422         // Reset any previous text alignment resolution
30423         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
30424 
30425         if (hasRtlSupport()) {
30426             // Set resolved text alignment flag depending on text alignment flag
30427             final int textAlignment = getRawTextAlignment();
30428             switch (textAlignment) {
30429                 case TEXT_ALIGNMENT_INHERIT:
30430                     // Check if we can resolve the text alignment
30431                     if (!canResolveTextAlignment()) {
30432                         // We cannot do the resolution if there is no parent so use the default
30433                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30434                         // Resolution will need to happen again later
30435                         return false;
30436                     }
30437 
30438                     // Parent has not yet resolved, so we still return the default
30439                     try {
30440                         if (!mParent.isTextAlignmentResolved()) {
30441                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30442                             // Resolution will need to happen again later
30443                             return false;
30444                         }
30445                     } catch (AbstractMethodError e) {
30446                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30447                                 " does not fully implement ViewParent", e);
30448                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
30449                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30450                         return true;
30451                     }
30452 
30453                     int parentResolvedTextAlignment;
30454                     try {
30455                         parentResolvedTextAlignment = mParent.getTextAlignment();
30456                     } catch (AbstractMethodError e) {
30457                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30458                                 " does not fully implement ViewParent", e);
30459                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
30460                     }
30461                     switch (parentResolvedTextAlignment) {
30462                         case TEXT_ALIGNMENT_GRAVITY:
30463                         case TEXT_ALIGNMENT_TEXT_START:
30464                         case TEXT_ALIGNMENT_TEXT_END:
30465                         case TEXT_ALIGNMENT_CENTER:
30466                         case TEXT_ALIGNMENT_VIEW_START:
30467                         case TEXT_ALIGNMENT_VIEW_END:
30468                             // Resolved text alignment is the same as the parent resolved
30469                             // text alignment
30470                             mPrivateFlags2 |=
30471                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
30472                             break;
30473                         default:
30474                             // Use default resolved text alignment
30475                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30476                     }
30477                     break;
30478                 case TEXT_ALIGNMENT_GRAVITY:
30479                 case TEXT_ALIGNMENT_TEXT_START:
30480                 case TEXT_ALIGNMENT_TEXT_END:
30481                 case TEXT_ALIGNMENT_CENTER:
30482                 case TEXT_ALIGNMENT_VIEW_START:
30483                 case TEXT_ALIGNMENT_VIEW_END:
30484                     // Resolved text alignment is the same as text alignment
30485                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
30486                     break;
30487                 default:
30488                     // Use default resolved text alignment
30489                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30490             }
30491         } else {
30492             // Use default resolved text alignment
30493             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30494         }
30495 
30496         // Set the resolved
30497         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
30498         return true;
30499     }
30500 
30501     /**
30502      * Check if text alignment resolution can be done.
30503      *
30504      * @return true if text alignment resolution can be done otherwise return false.
30505      */
canResolveTextAlignment()30506     public boolean canResolveTextAlignment() {
30507         switch (getRawTextAlignment()) {
30508             case TEXT_DIRECTION_INHERIT:
30509                 if (mParent != null) {
30510                     try {
30511                         return mParent.canResolveTextAlignment();
30512                     } catch (AbstractMethodError e) {
30513                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30514                                 " does not fully implement ViewParent", e);
30515                     }
30516                 }
30517                 return false;
30518 
30519             default:
30520                 return true;
30521         }
30522     }
30523 
30524     /**
30525      * Reset resolved text alignment. Text alignment will be resolved during a call to
30526      * {@link #onMeasure(int, int)}.
30527      *
30528      * @hide
30529      */
30530     @TestApi
resetResolvedTextAlignment()30531     public void resetResolvedTextAlignment() {
30532         // Reset any previous text alignment resolution
30533         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
30534         // Set to default
30535         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30536     }
30537 
30538     /**
30539      * @return true if text alignment is inherited.
30540      *
30541      * @hide
30542      */
isTextAlignmentInherited()30543     public boolean isTextAlignmentInherited() {
30544         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
30545     }
30546 
30547     /**
30548      * @return true if text alignment is resolved.
30549      */
isTextAlignmentResolved()30550     public boolean isTextAlignmentResolved() {
30551         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
30552     }
30553 
30554     /**
30555      * Generate a value suitable for use in {@link #setId(int)}.
30556      * This value will not collide with ID values generated at build time by aapt for R.id.
30557      *
30558      * @return a generated ID value
30559      */
generateViewId()30560     public static int generateViewId() {
30561         for (;;) {
30562             final int result = sNextGeneratedId.get();
30563             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
30564             int newValue = result + 1;
30565             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
30566             if (sNextGeneratedId.compareAndSet(result, newValue)) {
30567                 return result;
30568             }
30569         }
30570     }
30571 
isViewIdGenerated(int id)30572     private static boolean isViewIdGenerated(int id) {
30573         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
30574     }
30575 
30576     /**
30577      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
30578      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
30579      *                           a normal View or a ViewGroup with
30580      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
30581      * @hide
30582      */
captureTransitioningViews(List<View> transitioningViews)30583     public void captureTransitioningViews(List<View> transitioningViews) {
30584         if (getVisibility() == View.VISIBLE) {
30585             transitioningViews.add(this);
30586         }
30587     }
30588 
30589     /**
30590      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
30591      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
30592      * @hide
30593      */
findNamedViews(Map<String, View> namedElements)30594     public void findNamedViews(Map<String, View> namedElements) {
30595         if (getVisibility() == VISIBLE || mGhostView != null) {
30596             String transitionName = getTransitionName();
30597             if (transitionName != null) {
30598                 namedElements.put(transitionName, this);
30599             }
30600         }
30601     }
30602 
30603     /**
30604      * Resolve the pointer icon that should be used for specified pointer in the motion event.
30605      *
30606      * The default implementation will resolve the pointer icon to one set using
30607      * {@link #setPointerIcon(PointerIcon)} for mouse devices. Subclasses may override this to
30608      * customize the icon for the given pointer.
30609      *
30610      * For example, the pointer icon for a stylus pointer can be resolved in the following way:
30611      * <code><pre>
30612      * &#64;Override
30613      * public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
30614      *     final int toolType = event.getToolType(pointerIndex);
30615      *     if (!event.isFromSource(InputDevice.SOURCE_MOUSE)
30616      *             && event.isFromSource(InputDevice.SOURCE_STYLUS)
30617      *             && (toolType == MotionEvent.TOOL_TYPE_STYLUS
30618      *                     || toolType == MotionEvent.TOOL_TYPE_ERASER)) {
30619      *         // Show this pointer icon only if this pointer is a stylus.
30620      *         return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_WAIT);
30621      *     }
30622      *     // Use the default logic for determining the pointer icon for other non-stylus pointers,
30623      *     // like for the mouse cursor.
30624      *     return super.onResolvePointerIcon(event, pointerIndex);
30625      * }
30626      * </pre></code>
30627      *
30628      * @param event The {@link MotionEvent} that requires a pointer icon to be resolved for one of
30629      *              pointers.
30630      * @param pointerIndex The index of the pointer in {@code event} for which to retrieve the
30631      *     {@link PointerIcon}. This will be between 0 and {@link MotionEvent#getPointerCount()}.
30632      * @return the pointer icon to use for specified pointer, or {@code null} if a pointer icon
30633      *     is not specified and the default icon should be used.
30634      * @see PointerIcon
30635      * @see InputManager#isStylusPointerIconEnabled()
30636      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)30637     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
30638         final float x = event.getX(pointerIndex);
30639         final float y = event.getY(pointerIndex);
30640         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
30641             // Use the default pointer icon.
30642             return null;
30643         }
30644 
30645         // Note: A drawing tablet will have both SOURCE_MOUSE and SOURCE_STYLUS, but it would use
30646         // TOOL_TYPE_STYLUS. For now, treat drawing tablets the same way as a mouse or touchpad.
30647         if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
30648             return mMousePointerIcon;
30649         }
30650 
30651         return null;
30652     }
30653 
30654     /**
30655      * Set the pointer icon to be used for a mouse pointer in the current view.
30656      *
30657      * Passing {@code null} will restore the pointer icon to its default value.
30658      * Note that setting the pointer icon using this method will only set it for events coming from
30659      * a mouse device (i.e. with source {@link InputDevice#SOURCE_MOUSE}). To resolve
30660      * the pointer icon for other device types like styluses, override
30661      * {@link #onResolvePointerIcon(MotionEvent, int)}.
30662      *
30663      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
30664      * @see #onResolvePointerIcon(MotionEvent, int)
30665      * @see PointerIcon
30666      */
setPointerIcon(PointerIcon pointerIcon)30667     public void setPointerIcon(PointerIcon pointerIcon) {
30668         mMousePointerIcon = pointerIcon;
30669         final ViewRootImpl viewRootImpl = getViewRootImpl();
30670         if (viewRootImpl == null) {
30671             return;
30672         }
30673         viewRootImpl.refreshPointerIcon();
30674     }
30675 
30676     /**
30677      * Gets the mouse pointer icon for the current view.
30678      *
30679      * @see #setPointerIcon(PointerIcon)
30680      */
30681     @InspectableProperty
getPointerIcon()30682     public PointerIcon getPointerIcon() {
30683         return mMousePointerIcon;
30684     }
30685 
30686     /**
30687      * Checks pointer capture status.
30688      *
30689      * @return true if the view has pointer capture.
30690      * @see #requestPointerCapture()
30691      * @see #hasPointerCapture()
30692      */
hasPointerCapture()30693     public boolean hasPointerCapture() {
30694         final ViewRootImpl viewRootImpl = getViewRootImpl();
30695         if (viewRootImpl == null) {
30696             return false;
30697         }
30698         return viewRootImpl.hasPointerCapture();
30699     }
30700 
30701     /**
30702      * Requests pointer capture mode.
30703      * <p>
30704      * When the window has pointer capture, the mouse pointer icon will disappear and will not
30705      * change its position. Enabling pointer capture will change the behavior of input devices in
30706      * the following ways:
30707      * <ul>
30708      *     <li>Events from a mouse will be delivered with the source
30709      *     {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
30710      *     available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
30711      *
30712      *     <li>Events from a touchpad or trackpad will be delivered with the source
30713      *     {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
30714      *     on the touchpad will be available through {@link MotionEvent#getX(int)} and
30715      *     {@link MotionEvent#getY(int)}, and their relative movements are stored in
30716      *     {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li>
30717      *
30718      *     <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
30719      * </ul>
30720      * <p>
30721      * When pointer capture changes, connected mouse and trackpad devices may be reconfigured,
30722      * and their properties (such as their sources or motion ranges) may change. Use an
30723      * {@link android.hardware.input.InputManager.InputDeviceListener} to be notified when a device
30724      * changes (which may happen after enabling or disabling pointer capture), and use
30725      * {@link InputDevice#getDevice(int)} to get the updated {@link InputDevice}.
30726      * <p>
30727      * Events captured through pointer capture will be dispatched to
30728      * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
30729      * {@link OnCapturedPointerListener} is set, and otherwise to
30730      * {@link #onCapturedPointerEvent(MotionEvent)}.
30731      * <p>
30732      * If the window already has pointer capture, this call does nothing.
30733      * <p>
30734      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
30735      * automatically when the window loses focus.
30736      *
30737      * @see #releasePointerCapture()
30738      * @see #hasPointerCapture()
30739      * @see #onPointerCaptureChange(boolean)
30740      */
requestPointerCapture()30741     public void requestPointerCapture() {
30742         final ViewRootImpl viewRootImpl = getViewRootImpl();
30743         if (viewRootImpl != null) {
30744             viewRootImpl.requestPointerCapture(true);
30745         }
30746     }
30747 
30748 
30749     /**
30750      * Releases the pointer capture.
30751      * <p>
30752      * If the window does not have pointer capture, this call will do nothing.
30753      * @see #requestPointerCapture()
30754      * @see #hasPointerCapture()
30755      * @see #onPointerCaptureChange(boolean)
30756      */
releasePointerCapture()30757     public void releasePointerCapture() {
30758         final ViewRootImpl viewRootImpl = getViewRootImpl();
30759         if (viewRootImpl != null) {
30760             viewRootImpl.requestPointerCapture(false);
30761         }
30762     }
30763 
30764     /**
30765      * Called when the window has just acquired or lost pointer capture.
30766      *
30767      * @param hasCapture True if the view now has pointerCapture, false otherwise.
30768      */
30769     @CallSuper
onPointerCaptureChange(boolean hasCapture)30770     public void onPointerCaptureChange(boolean hasCapture) {
30771     }
30772 
30773     /**
30774      * @see #onPointerCaptureChange
30775      */
dispatchPointerCaptureChanged(boolean hasCapture)30776     public void dispatchPointerCaptureChanged(boolean hasCapture) {
30777         onPointerCaptureChange(hasCapture);
30778     }
30779 
30780     /**
30781      * Implement this method to handle captured pointer events
30782      *
30783      * @param event The captured pointer event.
30784      * @return True if the event was handled, false otherwise.
30785      * @see #requestPointerCapture()
30786      */
onCapturedPointerEvent(MotionEvent event)30787     public boolean onCapturedPointerEvent(MotionEvent event) {
30788         return false;
30789     }
30790 
30791     /**
30792      * Interface definition for a callback to be invoked when a captured pointer event
30793      * is being dispatched this view. The callback will be invoked before the event is
30794      * given to the view.
30795      */
30796     public interface OnCapturedPointerListener {
30797         /**
30798          * Called when a captured pointer event is dispatched to a view.
30799          * @param view The view this event has been dispatched to.
30800          * @param event The captured event.
30801          * @return True if the listener has consumed the event, false otherwise.
30802          */
30803         boolean onCapturedPointer(View view, MotionEvent event);
30804     }
30805 
30806     /**
30807      * Set a listener to receive callbacks when the pointer capture state of a view changes.
30808      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
30809      */
setOnCapturedPointerListener(OnCapturedPointerListener l)30810     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
30811         getListenerInfo().mOnCapturedPointerListener = l;
30812     }
30813 
30814     // Properties
30815     //
30816     /**
30817      * A Property wrapper around the <code>alpha</code> functionality handled by the
30818      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
30819      */
30820     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
30821         @Override
30822         public void setValue(View object, float value) {
30823             object.setAlpha(value);
30824         }
30825 
30826         @Override
30827         public Float get(View object) {
30828             return object.getAlpha();
30829         }
30830     };
30831 
30832     /**
30833      * A Property wrapper around the <code>translationX</code> functionality handled by the
30834      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
30835      */
30836     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
30837         @Override
30838         public void setValue(View object, float value) {
30839             object.setTranslationX(value);
30840         }
30841 
30842                 @Override
30843         public Float get(View object) {
30844             return object.getTranslationX();
30845         }
30846     };
30847 
30848     /**
30849      * A Property wrapper around the <code>translationY</code> functionality handled by the
30850      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
30851      */
30852     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
30853         @Override
30854         public void setValue(View object, float value) {
30855             object.setTranslationY(value);
30856         }
30857 
30858         @Override
30859         public Float get(View object) {
30860             return object.getTranslationY();
30861         }
30862     };
30863 
30864     /**
30865      * A Property wrapper around the <code>translationZ</code> functionality handled by the
30866      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
30867      */
30868     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
30869         @Override
30870         public void setValue(View object, float value) {
30871             object.setTranslationZ(value);
30872         }
30873 
30874         @Override
30875         public Float get(View object) {
30876             return object.getTranslationZ();
30877         }
30878     };
30879 
30880     /**
30881      * A Property wrapper around the <code>x</code> functionality handled by the
30882      * {@link View#setX(float)} and {@link View#getX()} methods.
30883      */
30884     public static final Property<View, Float> X = new FloatProperty<View>("x") {
30885         @Override
30886         public void setValue(View object, float value) {
30887             object.setX(value);
30888         }
30889 
30890         @Override
30891         public Float get(View object) {
30892             return object.getX();
30893         }
30894     };
30895 
30896     /**
30897      * A Property wrapper around the <code>y</code> functionality handled by the
30898      * {@link View#setY(float)} and {@link View#getY()} methods.
30899      */
30900     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
30901         @Override
30902         public void setValue(View object, float value) {
30903             object.setY(value);
30904         }
30905 
30906         @Override
30907         public Float get(View object) {
30908             return object.getY();
30909         }
30910     };
30911 
30912     /**
30913      * A Property wrapper around the <code>z</code> functionality handled by the
30914      * {@link View#setZ(float)} and {@link View#getZ()} methods.
30915      */
30916     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
30917         @Override
30918         public void setValue(View object, float value) {
30919             object.setZ(value);
30920         }
30921 
30922         @Override
30923         public Float get(View object) {
30924             return object.getZ();
30925         }
30926     };
30927 
30928     /**
30929      * A Property wrapper around the <code>rotation</code> functionality handled by the
30930      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
30931      */
30932     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
30933         @Override
30934         public void setValue(View object, float value) {
30935             object.setRotation(value);
30936         }
30937 
30938         @Override
30939         public Float get(View object) {
30940             return object.getRotation();
30941         }
30942     };
30943 
30944     /**
30945      * A Property wrapper around the <code>rotationX</code> functionality handled by the
30946      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
30947      */
30948     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
30949         @Override
30950         public void setValue(View object, float value) {
30951             object.setRotationX(value);
30952         }
30953 
30954         @Override
30955         public Float get(View object) {
30956             return object.getRotationX();
30957         }
30958     };
30959 
30960     /**
30961      * A Property wrapper around the <code>rotationY</code> functionality handled by the
30962      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
30963      */
30964     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
30965         @Override
30966         public void setValue(View object, float value) {
30967             object.setRotationY(value);
30968         }
30969 
30970         @Override
30971         public Float get(View object) {
30972             return object.getRotationY();
30973         }
30974     };
30975 
30976     /**
30977      * A Property wrapper around the <code>scaleX</code> functionality handled by the
30978      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
30979      */
30980     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
30981         @Override
30982         public void setValue(View object, float value) {
30983             object.setScaleX(value);
30984         }
30985 
30986         @Override
30987         public Float get(View object) {
30988             return object.getScaleX();
30989         }
30990     };
30991 
30992     /**
30993      * A Property wrapper around the <code>scaleY</code> functionality handled by the
30994      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
30995      */
30996     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
30997         @Override
30998         public void setValue(View object, float value) {
30999             object.setScaleY(value);
31000         }
31001 
31002         @Override
31003         public Float get(View object) {
31004             return object.getScaleY();
31005         }
31006     };
31007 
31008     /**
31009      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
31010      * Each MeasureSpec represents a requirement for either the width or the height.
31011      * A MeasureSpec is comprised of a size and a mode. There are three possible
31012      * modes:
31013      * <dl>
31014      * <dt>UNSPECIFIED</dt>
31015      * <dd>
31016      * The parent has not imposed any constraint on the child. It can be whatever size
31017      * it wants.
31018      * </dd>
31019      *
31020      * <dt>EXACTLY</dt>
31021      * <dd>
31022      * The parent has determined an exact size for the child. The child is going to be
31023      * given those bounds regardless of how big it wants to be.
31024      * </dd>
31025      *
31026      * <dt>AT_MOST</dt>
31027      * <dd>
31028      * The child can be as large as it wants up to the specified size.
31029      * </dd>
31030      * </dl>
31031      *
31032      * MeasureSpecs are implemented as ints to reduce object allocation. This class
31033      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
31034      */
31035     public static class MeasureSpec {
31036         private static final int MODE_SHIFT = 30;
31037         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
31038 
31039         /** @hide */
31040         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
31041         @Retention(RetentionPolicy.SOURCE)
31042         public @interface MeasureSpecMode {}
31043 
31044         /**
31045          * Measure specification mode: The parent has not imposed any constraint
31046          * on the child. It can be whatever size it wants.
31047          */
31048         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
31049 
31050         /**
31051          * Measure specification mode: The parent has determined an exact size
31052          * for the child. The child is going to be given those bounds regardless
31053          * of how big it wants to be.
31054          */
31055         public static final int EXACTLY     = 1 << MODE_SHIFT;
31056 
31057         /**
31058          * Measure specification mode: The child can be as large as it wants up
31059          * to the specified size.
31060          */
31061         public static final int AT_MOST     = 2 << MODE_SHIFT;
31062 
31063         /**
31064          * Creates a measure specification based on the supplied size and mode.
31065          *
31066          * The mode must always be one of the following:
31067          * <ul>
31068          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
31069          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
31070          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
31071          * </ul>
31072          *
31073          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
31074          * implementation was such that the order of arguments did not matter
31075          * and overflow in either value could impact the resulting MeasureSpec.
31076          * {@link android.widget.RelativeLayout} was affected by this bug.
31077          * Apps targeting API levels greater than 17 will get the fixed, more strict
31078          * behavior.</p>
31079          *
31080          * @param size the size of the measure specification
31081          * @param mode the mode of the measure specification
31082          * @return the measure specification based on size and mode
31083          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)31084         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
31085                                           @MeasureSpecMode int mode) {
31086             return (size & ~MODE_MASK) | (mode & MODE_MASK);
31087         }
31088 
31089         /**
31090          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
31091          * will automatically get a size of 0. Older apps expect this.
31092          *
31093          * @hide internal use only for compatibility with system widgets and older apps
31094          */
31095         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)31096         public static int makeSafeMeasureSpec(int size, int mode) {
31097             return makeMeasureSpec(size, mode);
31098         }
31099 
31100         /**
31101          * Extracts the mode from the supplied measure specification.
31102          *
31103          * @param measureSpec the measure specification to extract the mode from
31104          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
31105          *         {@link android.view.View.MeasureSpec#AT_MOST} or
31106          *         {@link android.view.View.MeasureSpec#EXACTLY}
31107          */
31108         @MeasureSpecMode
getMode(int measureSpec)31109         public static int getMode(int measureSpec) {
31110             //noinspection ResourceType
31111             return (measureSpec & MODE_MASK);
31112         }
31113 
31114         /**
31115          * Extracts the size from the supplied measure specification.
31116          *
31117          * @param measureSpec the measure specification to extract the size from
31118          * @return the size in pixels defined in the supplied measure specification
31119          */
getSize(int measureSpec)31120         public static int getSize(int measureSpec) {
31121             return (measureSpec & ~MODE_MASK);
31122         }
31123 
adjust(int measureSpec, int delta)31124         static int adjust(int measureSpec, int delta) {
31125             final int mode = getMode(measureSpec);
31126             int size = getSize(measureSpec);
31127             if (mode == UNSPECIFIED) {
31128                 // No need to adjust size for UNSPECIFIED mode.
31129                 return makeMeasureSpec(size, UNSPECIFIED);
31130             }
31131             size += delta;
31132             if (size < 0) {
31133                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
31134                         ") spec: " + toString(measureSpec) + " delta: " + delta);
31135                 size = 0;
31136             }
31137             return makeMeasureSpec(size, mode);
31138         }
31139 
31140         /**
31141          * Returns a String representation of the specified measure
31142          * specification.
31143          *
31144          * @param measureSpec the measure specification to convert to a String
31145          * @return a String with the following format: "MeasureSpec: MODE SIZE"
31146          */
toString(int measureSpec)31147         public static String toString(int measureSpec) {
31148             int mode = getMode(measureSpec);
31149             int size = getSize(measureSpec);
31150 
31151             StringBuilder sb = new StringBuilder("MeasureSpec: ");
31152 
31153             if (mode == UNSPECIFIED)
31154                 sb.append("UNSPECIFIED ");
31155             else if (mode == EXACTLY)
31156                 sb.append("EXACTLY ");
31157             else if (mode == AT_MOST)
31158                 sb.append("AT_MOST ");
31159             else
31160                 sb.append(mode).append(" ");
31161 
31162             sb.append(size);
31163             return sb.toString();
31164         }
31165     }
31166 
31167     private final class CheckForLongPress implements Runnable {
31168         private int mOriginalWindowAttachCount;
31169         private float mX;
31170         private float mY;
31171         private boolean mOriginalPressedState;
31172         /**
31173          * The classification of the long click being checked: one of the
31174          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
31175          */
31176         private int mClassification;
31177 
31178         @UnsupportedAppUsage
CheckForLongPress()31179         private CheckForLongPress() {
31180         }
31181 
31182         @Override
run()31183         public void run() {
31184             if ((mOriginalPressedState == isPressed()) && (mParent != null)
31185                     && mOriginalWindowAttachCount == mWindowAttachCount) {
31186                 recordGestureClassification(mClassification);
31187                 if (performLongClick(mX, mY)) {
31188                     mHasPerformedLongPress = true;
31189                 }
31190             }
31191         }
31192 
setAnchor(float x, float y)31193         public void setAnchor(float x, float y) {
31194             mX = x;
31195             mY = y;
31196         }
31197 
rememberWindowAttachCount()31198         public void rememberWindowAttachCount() {
31199             mOriginalWindowAttachCount = mWindowAttachCount;
31200         }
31201 
rememberPressedState()31202         public void rememberPressedState() {
31203             mOriginalPressedState = isPressed();
31204         }
31205 
setClassification(int classification)31206         public void setClassification(int classification) {
31207             mClassification = classification;
31208         }
31209     }
31210 
31211     private final class CheckForTap implements Runnable {
31212         public float x;
31213         public float y;
31214 
31215         @Override
run()31216         public void run() {
31217             mPrivateFlags &= ~PFLAG_PREPRESSED;
31218             setPressed(true, x, y);
31219             final long delay =
31220                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
31221             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
31222         }
31223     }
31224 
31225     private final class PerformClick implements Runnable {
31226         @Override
run()31227         public void run() {
31228             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
31229             performClickInternal();
31230         }
31231     }
31232 
31233     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)31234     private void recordGestureClassification(int classification) {
31235         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
31236             return;
31237         }
31238         // To avoid negatively impacting View performance, the latency and displacement metrics
31239         // are omitted.
31240         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
31241                 classification);
31242     }
31243 
31244     /**
31245      * This method returns a ViewPropertyAnimator object, which can be used to animate
31246      * specific properties on this View.
31247      *
31248      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
31249      */
animate()31250     public ViewPropertyAnimator animate() {
31251         if (mAnimator == null) {
31252             mAnimator = new ViewPropertyAnimator(this);
31253         }
31254         return mAnimator;
31255     }
31256 
31257     /**
31258      * Sets the name of the View to be used to identify Views in Transitions.
31259      * Names should be unique in the View hierarchy.
31260      *
31261      * @param transitionName The name of the View to uniquely identify it for Transitions.
31262      */
setTransitionName(String transitionName)31263     public final void setTransitionName(String transitionName) {
31264         mTransitionName = transitionName;
31265     }
31266 
31267     /**
31268      * Returns the name of the View to be used to identify Views in Transitions.
31269      * Names should be unique in the View hierarchy.
31270      *
31271      * <p>This returns null if the View has not been given a name.</p>
31272      *
31273      * @return The name used of the View to be used to identify Views in Transitions or null
31274      * if no name has been given.
31275      */
31276     @ViewDebug.ExportedProperty
31277     @InspectableProperty
getTransitionName()31278     public String getTransitionName() {
31279         return mTransitionName;
31280     }
31281 
31282     /**
31283      * @hide
31284      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)31285     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
31286         // Do nothing.
31287     }
31288 
31289     /**
31290      * Interface definition for a callback to be invoked when a hardware key event is
31291      * dispatched to this view. The callback will be invoked before the key event is
31292      * given to the view. This is only useful for hardware keyboards; a software input
31293      * method has no obligation to trigger this listener.
31294      */
31295     public interface OnKeyListener {
31296         /**
31297          * Called when a hardware key is dispatched to a view. This allows listeners to
31298          * get a chance to respond before the target view.
31299          * <p>Key presses in software keyboards will generally NOT trigger this method,
31300          * although some may elect to do so in some situations. Do not assume a
31301          * software input method has to be key-based; even if it is, it may use key presses
31302          * in a different way than you expect, so there is no way to reliably catch soft
31303          * input key presses.
31304          *
31305          * @param v The view the key has been dispatched to.
31306          * @param keyCode The code for the physical key that was pressed
31307          * @param event The KeyEvent object containing full information about
31308          *        the event.
31309          * @return True if the listener has consumed the event, false otherwise.
31310          */
31311         boolean onKey(View v, int keyCode, KeyEvent event);
31312     }
31313 
31314     /**
31315      * Interface definition for a callback to be invoked when a hardware key event hasn't
31316      * been handled by the view hierarchy.
31317      */
31318     public interface OnUnhandledKeyEventListener {
31319         /**
31320          * Called when a hardware key is dispatched to a view after being unhandled during normal
31321          * {@link KeyEvent} dispatch.
31322          *
31323          * @param v The view the key has been dispatched to.
31324          * @param event The KeyEvent object containing information about the event.
31325          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
31326          */
31327         boolean onUnhandledKeyEvent(View v, KeyEvent event);
31328     }
31329 
31330     /**
31331      * Interface definition for a callback to be invoked when a touch event is
31332      * dispatched to this view. The callback will be invoked before the touch
31333      * event is given to the view.
31334      */
31335     public interface OnTouchListener {
31336         /**
31337          * Called when a touch event is dispatched to a view. This allows listeners to
31338          * get a chance to respond before the target view.
31339          *
31340          * @param v The view the touch event has been dispatched to.
31341          * @param event The MotionEvent object containing full information about
31342          *        the event.
31343          * @return True if the listener has consumed the event, false otherwise.
31344          */
31345         boolean onTouch(View v, MotionEvent event);
31346     }
31347 
31348     /**
31349      * Interface definition for a callback to be invoked when a hover event is
31350      * dispatched to this view. The callback will be invoked before the hover
31351      * event is given to the view.
31352      */
31353     public interface OnHoverListener {
31354         /**
31355          * Called when a hover event is dispatched to a view. This allows listeners to
31356          * get a chance to respond before the target view.
31357          *
31358          * @param v The view the hover event has been dispatched to.
31359          * @param event The MotionEvent object containing full information about
31360          *        the event.
31361          * @return True if the listener has consumed the event, false otherwise.
31362          */
31363         boolean onHover(View v, MotionEvent event);
31364     }
31365 
31366     /**
31367      * Interface definition for a callback to be invoked when a generic motion event is
31368      * dispatched to this view. The callback will be invoked before the generic motion
31369      * event is given to the view.
31370      */
31371     public interface OnGenericMotionListener {
31372         /**
31373          * Called when a generic motion event is dispatched to a view. This allows listeners to
31374          * get a chance to respond before the target view.
31375          *
31376          * @param v The view the generic motion event has been dispatched to.
31377          * @param event The MotionEvent object containing full information about
31378          *        the event.
31379          * @return True if the listener has consumed the event, false otherwise.
31380          */
31381         boolean onGenericMotion(View v, MotionEvent event);
31382     }
31383 
31384     /**
31385      * Interface definition for a callback to be invoked when a view has been clicked and held.
31386      */
31387     public interface OnLongClickListener {
31388         /**
31389          * Called when a view has been clicked and held.
31390          *
31391          * @param v The view that was clicked and held.
31392          *
31393          * @return true if the callback consumed the long click, false otherwise.
31394          */
31395         boolean onLongClick(View v);
31396 
31397         /**
31398          * Returns whether the default {@link HapticFeedbackConstants#LONG_PRESS} haptic feedback
31399          * is performed when this listener has consumed the long click. This method is called
31400          * immediately after {@link #onLongClick} has returned true.
31401          *
31402          * @param v The view that was clicked and held.
31403          * @return true to perform the default {@link HapticFeedbackConstants#LONG_PRESS} haptic
31404          * feedback, or false if the handler manages all haptics itself.
31405          */
onLongClickUseDefaultHapticFeedback(@onNull View v)31406         default boolean onLongClickUseDefaultHapticFeedback(@NonNull View v) {
31407             return true;
31408         }
31409     }
31410 
31411     /**
31412      * Interface definition for a listener that's invoked when a drag event is dispatched to this
31413      * view. The listener is invoked before the view's own
31414      * {@link #onDragEvent(DragEvent)} method. To fall back to the view's
31415      * {@code onDragEvent(DragEvent)} behavior, return {@code false} from the listener method.
31416      *
31417      * <div class="special reference">
31418      *   <h3>Developer Guides</h3>
31419      *   <p>For a guide to implementing drag and drop features, see the
31420      *   <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and drop</a> developer guide.</p>
31421      * </div>
31422      */
31423     public interface OnDragListener {
31424         /**
31425          * Called when a drag event is dispatched to a view. Enables listeners to override the
31426          * base behavior provided by {@link #onDragEvent(DragEvent)}.
31427          *
31428          * @param v The {@code View} that received the drag event.
31429          * @param event The event object for the drag event.
31430          * @return {@code true} if the drag event was handled successfully; {@code false}, if the
31431          *   drag event was not handled. <b>Note:</b> A {@code false} return value triggers the
31432          *   view's {@link #onDragEvent(DragEvent)} handler.
31433          */
31434         boolean onDrag(View v, DragEvent event);
31435     }
31436 
31437     /**
31438      * Interface definition for a callback to be invoked when the focus state of
31439      * a view changed.
31440      */
31441     public interface OnFocusChangeListener {
31442         /**
31443          * Called when the focus state of a view has changed.
31444          *
31445          * @param v The view whose state has changed.
31446          * @param hasFocus The new focus state of v.
31447          */
31448         void onFocusChange(View v, boolean hasFocus);
31449     }
31450 
31451     /**
31452      * Interface definition for a callback to be invoked when a view is clicked.
31453      */
31454     public interface OnClickListener {
31455         /**
31456          * Called when a view has been clicked.
31457          *
31458          * @param v The view that was clicked.
31459          */
31460         void onClick(View v);
31461     }
31462 
31463     /**
31464      * Interface definition for a callback to be invoked when a view is context clicked.
31465      */
31466     public interface OnContextClickListener {
31467         /**
31468          * Called when a view is context clicked.
31469          *
31470          * @param v The view that has been context clicked.
31471          * @return true if the callback consumed the context click, false otherwise.
31472          */
31473         boolean onContextClick(View v);
31474     }
31475 
31476     /**
31477      * Interface definition for a callback to be invoked when the context menu
31478      * for this view is being built.
31479      */
31480     public interface OnCreateContextMenuListener {
31481         /**
31482          * Called when the context menu for this view is being built. It is not
31483          * safe to hold onto the menu after this method returns.
31484          *
31485          * @param menu The context menu that is being built
31486          * @param v The view for which the context menu is being built
31487          * @param menuInfo Extra information about the item for which the
31488          *            context menu should be shown. This information will vary
31489          *            depending on the class of v.
31490          */
31491         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
31492     }
31493 
31494     /**
31495      * Interface definition for a callback to be invoked when the status bar changes
31496      * visibility.  This reports <strong>global</strong> changes to the system UI
31497      * state, not what the application is requesting.
31498      *
31499      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
31500      *
31501      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
31502      * by setting a {@link OnApplyWindowInsetsListener} on this view.
31503      */
31504     @Deprecated
31505     public interface OnSystemUiVisibilityChangeListener {
31506         /**
31507          * Called when the status bar changes visibility because of a call to
31508          * {@link View#setSystemUiVisibility(int)}.
31509          *
31510          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
31511          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
31512          * This tells you the <strong>global</strong> state of these UI visibility
31513          * flags, not what your app is currently applying.
31514          */
31515         public void onSystemUiVisibilityChange(int visibility);
31516     }
31517 
31518     /**
31519      * Interface definition for a callback to be invoked when this view is attached
31520      * or detached from its window.
31521      */
31522     public interface OnAttachStateChangeListener {
31523         /**
31524          * Called when the view is attached to a window.
31525          * @param v The view that was attached
31526          */
31527         public void onViewAttachedToWindow(@NonNull View v);
31528         /**
31529          * Called when the view is detached from a window.
31530          * @param v The view that was detached
31531          */
31532         public void onViewDetachedFromWindow(@NonNull View v);
31533     }
31534 
31535     /**
31536      * Listener for applying window insets on a view in a custom way.
31537      *
31538      * <p>Apps may choose to implement this interface if they want to apply custom policy
31539      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
31540      * is set, its
31541      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
31542      * method will be called instead of the View's own
31543      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
31544      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
31545      * the View's normal behavior as part of its own.</p>
31546      */
31547     public interface OnApplyWindowInsetsListener {
31548         /**
31549          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
31550          * on a View, this listener method will be called instead of the view's own
31551          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
31552          *
31553          * @param v The view applying window insets
31554          * @param insets The insets to apply
31555          * @return The insets supplied, minus any insets that were consumed
31556          */
31557         public @NonNull WindowInsets onApplyWindowInsets(@NonNull View v,
31558                 @NonNull WindowInsets insets);
31559     }
31560 
31561     private final class UnsetPressedState implements Runnable {
31562         @Override
run()31563         public void run() {
31564             setPressed(false);
31565         }
31566     }
31567 
31568     /**
31569      * When a view becomes invisible checks if autofill considers the view invisible too. This
31570      * happens after the regular removal operation to make sure the operation is finished by the
31571      * time this is called.
31572      */
31573     private static class VisibilityChangeForAutofillHandler extends Handler {
31574         private final AutofillManager mAfm;
31575         private final View mView;
31576 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)31577         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
31578                 @NonNull View view) {
31579             mAfm = afm;
31580             mView = view;
31581         }
31582 
31583         @Override
handleMessage(Message msg)31584         public void handleMessage(Message msg) {
31585             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
31586         }
31587     }
31588 
31589     /**
31590      * Base class for derived classes that want to save and restore their own
31591      * state in {@link android.view.View#onSaveInstanceState()}.
31592      */
31593     public static class BaseSavedState extends AbsSavedState {
31594         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
31595         static final int IS_AUTOFILLED = 0b10;
31596         static final int AUTOFILL_ID = 0b100;
31597 
31598         // Flags that describe what data in this state is valid
31599         int mSavedData;
31600         String mStartActivityRequestWhoSaved;
31601         boolean mIsAutofilled;
31602         boolean mHideHighlight;
31603         int mAutofillViewId;
31604 
31605         /**
31606          * Constructor used when reading from a parcel. Reads the state of the superclass.
31607          *
31608          * @param source parcel to read from
31609          */
BaseSavedState(Parcel source)31610         public BaseSavedState(Parcel source) {
31611             this(source, null);
31612         }
31613 
31614         /**
31615          * Constructor used when reading from a parcel using a given class loader.
31616          * Reads the state of the superclass.
31617          *
31618          * @param source parcel to read from
31619          * @param loader ClassLoader to use for reading
31620          */
BaseSavedState(Parcel source, ClassLoader loader)31621         public BaseSavedState(Parcel source, ClassLoader loader) {
31622             super(source, loader);
31623             mSavedData = source.readInt();
31624             mStartActivityRequestWhoSaved = source.readString();
31625             mIsAutofilled = source.readBoolean();
31626             mHideHighlight = source.readBoolean();
31627             mAutofillViewId = source.readInt();
31628         }
31629 
31630         /**
31631          * Constructor called by derived classes when creating their SavedState objects
31632          *
31633          * @param superState The state of the superclass of this view
31634          */
BaseSavedState(Parcelable superState)31635         public BaseSavedState(Parcelable superState) {
31636             super(superState);
31637         }
31638 
31639         @Override
writeToParcel(Parcel out, int flags)31640         public void writeToParcel(Parcel out, int flags) {
31641             super.writeToParcel(out, flags);
31642 
31643             out.writeInt(mSavedData);
31644             out.writeString(mStartActivityRequestWhoSaved);
31645             out.writeBoolean(mIsAutofilled);
31646             out.writeBoolean(mHideHighlight);
31647             out.writeInt(mAutofillViewId);
31648         }
31649 
31650         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
31651                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
31652             @Override
31653             public BaseSavedState createFromParcel(Parcel in) {
31654                 return new BaseSavedState(in);
31655             }
31656 
31657             @Override
31658             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
31659                 return new BaseSavedState(in, loader);
31660             }
31661 
31662             @Override
31663             public BaseSavedState[] newArray(int size) {
31664                 return new BaseSavedState[size];
31665             }
31666         };
31667     }
31668 
31669     /**
31670      * A set of information given to a view when it is attached to its parent
31671      * window.
31672      */
31673     final static class AttachInfo {
31674 
31675         interface Callbacks {
31676             void playSoundEffect(int effectId);
31677             boolean performHapticFeedback(int effectId, boolean always, boolean fromIme);
31678         }
31679 
31680         /**
31681          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
31682          * to a Handler. This class contains the target (View) to invalidate and
31683          * the coordinates of the dirty rectangle.
31684          *
31685          * For performance purposes, this class also implements a pool of up to
31686          * POOL_LIMIT objects that get reused. This reduces memory allocations
31687          * whenever possible.
31688          */
31689         static class InvalidateInfo {
31690 
31691             @UnsupportedAppUsage
InvalidateInfo()31692             InvalidateInfo() {
31693             }
31694 
31695             private static final int POOL_LIMIT = 10;
31696 
31697             private static final SynchronizedPool<InvalidateInfo> sPool =
31698                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
31699 
31700             @UnsupportedAppUsage
31701             View target;
31702 
31703             @UnsupportedAppUsage
31704             int left;
31705             @UnsupportedAppUsage
31706             int top;
31707             @UnsupportedAppUsage
31708             int right;
31709             @UnsupportedAppUsage
31710             int bottom;
31711 
obtain()31712             public static InvalidateInfo obtain() {
31713                 InvalidateInfo instance = sPool.acquire();
31714                 return (instance != null) ? instance : new InvalidateInfo();
31715             }
31716 
recycle()31717             public void recycle() {
31718                 target = null;
31719                 sPool.release(this);
31720             }
31721         }
31722 
31723         @UnsupportedAppUsage
31724         final IWindowSession mSession;
31725 
31726         @UnsupportedAppUsage
31727         final IWindow mWindow;
31728 
31729         final IBinder mWindowToken;
31730 
31731         Display mDisplay;
31732 
31733         final Callbacks mRootCallbacks;
31734 
31735         IWindowId mIWindowId;
31736         WindowId mWindowId;
31737 
31738         /**
31739          * The top view of the hierarchy.
31740          */
31741         View mRootView;
31742 
31743         IBinder mPanelParentWindowToken;
31744 
31745         boolean mHardwareAccelerated;
31746         boolean mHardwareAccelerationRequested;
31747         ThreadedRenderer mThreadedRenderer;
31748         List<RenderNode> mPendingAnimatingRenderNodes;
31749 
31750         /**
31751          * The state of the display to which the window is attached, as reported
31752          * by {@link Display#getState()}.  Note that the display state constants
31753          * declared by {@link Display} do not exactly line up with the screen state
31754          * constants declared by {@link View} (there are more display states than
31755          * screen states).
31756          */
31757         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
31758         int mDisplayState = Display.STATE_UNKNOWN;
31759 
31760         /**
31761          * Scale factor used by the compatibility mode
31762          */
31763         @UnsupportedAppUsage
31764         float mApplicationScale;
31765 
31766         /**
31767          * Indicates whether the application is in compatibility mode
31768          */
31769         @UnsupportedAppUsage
31770         boolean mScalingRequired;
31771 
31772         /**
31773          * Left position of this view's window
31774          */
31775         int mWindowLeft;
31776 
31777         /**
31778          * Top position of this view's window
31779          */
31780         int mWindowTop;
31781 
31782         /**
31783          * Indicates whether views need to use 32-bit drawing caches
31784          */
31785         boolean mUse32BitDrawingCache;
31786 
31787         /**
31788          * For windows that are full-screen but using insets to layout inside
31789          * of the screen decorations, these are the current insets for the
31790          * content of the window.
31791          */
31792         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
31793                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
31794         final Rect mContentInsets = new Rect();
31795 
31796         /**
31797          * For windows that are full-screen but using insets to layout inside
31798          * of the screen decorations, these are the current insets for the
31799          * actual visible parts of the window.
31800          */
31801         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
31802                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
31803         final Rect mVisibleInsets = new Rect();
31804 
31805         /**
31806          * For windows that are full-screen but using insets to layout inside
31807          * of the screen decorations, these are the current insets for the
31808          * stable system windows.
31809          */
31810         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
31811                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
31812         final Rect mStableInsets = new Rect();
31813 
31814         /**
31815          * Current caption insets to the display coordinate.
31816          */
31817         final Rect mCaptionInsets = new Rect();
31818 
31819         /**
31820          * In multi-window we force show the system bars. Because we don't want that the surface
31821          * size changes in this mode, we instead have a flag whether the system bars sizes should
31822          * always be consumed, so the app is treated like there are no virtual system bars at all.
31823          */
31824         boolean mAlwaysConsumeSystemBars;
31825 
31826         /**
31827          * The internal insets given by this window.  This value is
31828          * supplied by the client (through
31829          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
31830          * be given to the window manager when changed to be used in laying
31831          * out windows behind it.
31832          */
31833         @UnsupportedAppUsage
31834         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
31835                 = new ViewTreeObserver.InternalInsetsInfo();
31836 
31837         /**
31838          * Set to true when mGivenInternalInsets is non-empty.
31839          */
31840         boolean mHasNonEmptyGivenInternalInsets;
31841 
31842         /**
31843          * All views in the window's hierarchy that serve as scroll containers,
31844          * used to determine if the window can be resized or must be panned
31845          * to adjust for a soft input area.
31846          */
31847         @UnsupportedAppUsage
31848         final ArrayList<View> mScrollContainers = new ArrayList<View>();
31849 
31850         @UnsupportedAppUsage
31851         final KeyEvent.DispatcherState mKeyDispatchState
31852                 = new KeyEvent.DispatcherState();
31853 
31854         /**
31855          * Indicates whether the view's window currently has the focus.
31856          */
31857         @UnsupportedAppUsage
31858         boolean mHasWindowFocus;
31859 
31860         /**
31861          * The current visibility of the window.
31862          */
31863         int mWindowVisibility;
31864 
31865         /**
31866          * Indicates the time at which drawing started to occur.
31867          */
31868         @UnsupportedAppUsage
31869         long mDrawingTime;
31870 
31871         /**
31872          * Indicates whether the view's window is currently in touch mode.
31873          */
31874         @UnsupportedAppUsage
31875         boolean mInTouchMode;
31876 
31877         /**
31878          * Indicates whether the view has requested unbuffered input dispatching for the current
31879          * event stream.
31880          */
31881         boolean mUnbufferedDispatchRequested;
31882 
31883         /**
31884          * Indicates that ViewAncestor should trigger a global layout change
31885          * the next time it performs a traversal
31886          */
31887         @UnsupportedAppUsage
31888         boolean mRecomputeGlobalAttributes;
31889 
31890         /**
31891          * Always report new attributes at next traversal.
31892          */
31893         boolean mForceReportNewAttributes;
31894 
31895         /**
31896          * Set during a traveral if any views want to keep the screen on.
31897          */
31898         @UnsupportedAppUsage
31899         boolean mKeepScreenOn;
31900 
31901         /**
31902          * Set during a traveral if the light center needs to be updated.
31903          */
31904         boolean mNeedsUpdateLightCenter;
31905 
31906         /**
31907          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
31908          */
31909         int mSystemUiVisibility;
31910 
31911         /**
31912          * Hack to force certain system UI visibility flags to be cleared.
31913          */
31914         int mDisabledSystemUiVisibility;
31915 
31916         /**
31917          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
31918          * attached.
31919          */
31920         boolean mHasSystemUiListeners;
31921 
31922         /**
31923          * Set if the visibility of any views has changed.
31924          */
31925         @UnsupportedAppUsage
31926         boolean mViewVisibilityChanged;
31927 
31928         /**
31929          * Set to true if a view has been scrolled.
31930          */
31931         @UnsupportedAppUsage
31932         boolean mViewScrollChanged;
31933 
31934         /**
31935          * Set to true if a pointer event is currently being handled.
31936          */
31937         boolean mHandlingPointerEvent;
31938 
31939         /**
31940          * The window matrix of this view when it's on a {@link SurfaceControlViewHost} that is
31941          * embedded within a SurfaceView.
31942          */
31943         Matrix mWindowMatrixInEmbeddedHierarchy;
31944 
31945         /**
31946          * Global to the view hierarchy used as a temporary for dealing with
31947          * x/y points in the transparent region computations.
31948          */
31949         final int[] mTransparentLocation = new int[2];
31950 
31951         /**
31952          * Global to the view hierarchy used as a temporary for dealing with
31953          * x/y points in the ViewGroup.invalidateChild implementation.
31954          */
31955         final int[] mInvalidateChildLocation = new int[2];
31956 
31957         /**
31958          * Global to the view hierarchy used as a temporary for dealing with
31959          * computing absolute on-screen location.
31960          */
31961         final int[] mTmpLocation = new int[2];
31962 
31963         /**
31964          * Global to the view hierarchy used as a temporary for dealing with
31965          * x/y location when view is transformed.
31966          */
31967         final float[] mTmpTransformLocation = new float[2];
31968 
31969         /**
31970          * The view tree observer used to dispatch global events like
31971          * layout, pre-draw, touch mode change, etc.
31972          */
31973         @UnsupportedAppUsage
31974         final ViewTreeObserver mTreeObserver;
31975 
31976         /**
31977          * A Canvas used by the view hierarchy to perform bitmap caching.
31978          */
31979         Canvas mCanvas;
31980 
31981         /**
31982          * The view root impl.
31983          */
31984         final ViewRootImpl mViewRootImpl;
31985 
31986         /**
31987          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
31988          * handler can be used to pump events in the UI events queue.
31989          */
31990         @UnsupportedAppUsage
31991         final Handler mHandler;
31992 
31993         /**
31994          * Temporary for use in computing invalidate rectangles while
31995          * calling up the hierarchy.
31996          */
31997         final Rect mTmpInvalRect = new Rect();
31998 
31999         /**
32000          * Temporary for use in computing hit areas with transformed views
32001          */
32002         final RectF mTmpTransformRect = new RectF();
32003 
32004         /**
32005          * Temporary for use in computing hit areas with transformed views
32006          */
32007         final RectF mTmpTransformRect1 = new RectF();
32008 
32009         /**
32010          * Temporary list of rectanges.
32011          */
32012         final List<RectF> mTmpRectList = new ArrayList<>();
32013 
32014         /**
32015          * Temporary for use in transforming invalidation rect
32016          */
32017         final Matrix mTmpMatrix = new Matrix();
32018 
32019         /**
32020          * Temporary for use in transforming invalidation rect
32021          */
32022         final Transformation mTmpTransformation = new Transformation();
32023 
32024         /**
32025          * Temporary for use in querying outlines from OutlineProviders
32026          */
32027         final Outline mTmpOutline = new Outline();
32028 
32029         /**
32030          * Temporary list for use in collecting focusable descendents of a view.
32031          */
32032         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
32033 
32034         /**
32035          * Indicates if the next focus will be looped back to the first focusable view of the entire
32036          * hierarchy when finding in the direction of {@link #FOCUS_FORWARD} or to the last
32037          * focusable view when finding in the direction of {@link #FOCUS_BACKWARD}.
32038          */
32039         boolean mNextFocusLooped = false;
32040 
32041         /**
32042          * The id of the window for accessibility purposes.
32043          */
32044         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
32045 
32046         /**
32047          * Flags related to accessibility processing.
32048          *
32049          * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
32050          * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
32051          */
32052         int mAccessibilityFetchFlags;
32053 
32054         /**
32055          * The drawable for highlighting accessibility focus.
32056          */
32057         Drawable mAccessibilityFocusDrawable;
32058 
32059         /**
32060          * The drawable for highlighting autofilled views.
32061          *
32062          * @see #isAutofilled()
32063          */
32064         Drawable mAutofilledDrawable;
32065 
32066         /**
32067          * Show where the margins, bounds and layout bounds are for each view.
32068          */
32069         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
32070 
32071         /**
32072          * Point used to compute visible regions.
32073          */
32074         final Point mPoint = new Point();
32075 
32076         /**
32077          * Used to track which View originated a requestLayout() call, used when
32078          * requestLayout() is called during layout.
32079          */
32080         View mViewRequestingLayout;
32081 
32082         /**
32083          * Used to track the identity of the current drag operation.
32084          */
32085         IBinder mDragToken;
32086 
32087         /**
32088          * Used to track the data of the current drag operation for cleanup later.
32089          */
32090         ClipData mDragData;
32091 
32092         /**
32093          * The drag shadow surface for the current drag operation.
32094          */
32095         public Surface mDragSurface;
32096 
32097         /**
32098          * The view that currently has a tooltip displayed.
32099          */
32100         View mTooltipHost;
32101 
32102         /**
32103          * The initial structure has been reported so the view is ready to report updates.
32104          */
32105         boolean mReadyForContentCaptureUpdates;
32106 
32107         /**
32108          * Map(keyed by session) of content capture events that need to be notified after the view
32109          * hierarchy is traversed: value is either the view itself for appearead events, or its
32110          * autofill id for disappeared.
32111          */
32112         SparseArray<ArrayList<Object>> mContentCaptureEvents;
32113 
32114         /**
32115          * Cached reference to the {@link ContentCaptureManager}.
32116          */
32117         ContentCaptureManager mContentCaptureManager;
32118 
32119         /**
32120          * Listener used to fit content on window level.
32121          */
32122         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
32123 
32124         /**
32125          * The leash token of this view's parent when it's in an embedded hierarchy that is
32126          * re-parented to another window.
32127          */
32128         IBinder mLeashedParentToken;
32129 
32130         /**
32131          * The accessibility view id of this view's parent when it's in an embedded
32132          * hierarchy that is re-parented to another window.
32133          */
32134         int mLeashedParentAccessibilityViewId;
32135 
32136         /**
32137          *
32138          */
32139         ScrollCaptureInternal mScrollCaptureInternal;
32140 
32141         /**
32142          * sensitive views attached to the window
32143          */
32144         int mSensitiveViewsCount;
32145 
32146         /**
32147          * The value of viewVelocityApi(), read only once per ViewRootImpl
32148          */
32149         final boolean mViewVelocityApi = viewVelocityApi();
32150 
32151         /**
32152          * Density so that it doesn't need to be retrieved on every invalidation.
32153          */
32154         final float mDensity;
32155 
32156         /**
32157          * The number of pixels in the display (width * height).
32158          */
32159         final float mDisplayPixelCount;
32160 
32161         /**
32162          * Creates a new set of attachment information with the specified
32163          * events handler and thread.
32164          *
32165          * @param handler the events handler the view must use
32166          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)32167         AttachInfo(IWindowSession session, IWindow window, Display display,
32168                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
32169                 Context context) {
32170             mSession = session;
32171             mWindow = window;
32172             mWindowToken = window.asBinder();
32173             mDisplay = display;
32174             mViewRootImpl = viewRootImpl;
32175             mHandler = handler;
32176             mRootCallbacks = effectPlayer;
32177             mTreeObserver = new ViewTreeObserver(context);
32178             DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
32179             mDensity = displayMetrics.density;
32180             float pixelCount = (float) displayMetrics.widthPixels * displayMetrics.heightPixels;
32181             mDisplayPixelCount = pixelCount == 0f ? Float.POSITIVE_INFINITY : pixelCount;
32182         }
32183 
increaseSensitiveViewsCount()32184         void increaseSensitiveViewsCount() {
32185             if (mSensitiveViewsCount == 0) {
32186                 mViewRootImpl.addSensitiveContentAppProtection();
32187             }
32188             mSensitiveViewsCount++;
32189         }
32190 
decreaseSensitiveViewsCount()32191         void decreaseSensitiveViewsCount() {
32192             mSensitiveViewsCount--;
32193             if (mSensitiveViewsCount == 0) {
32194                 mViewRootImpl.removeSensitiveContentAppProtection();
32195             }
32196             if (mSensitiveViewsCount < 0) {
32197                 Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount);
32198                 mSensitiveViewsCount = 0;
32199             }
32200         }
32201 
32202         @Nullable
getContentCaptureManager(@onNull Context context)32203         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
32204             if (mContentCaptureManager != null) {
32205                 return mContentCaptureManager;
32206             }
32207             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
32208             return mContentCaptureManager;
32209         }
32210 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)32211         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
32212             if (mContentCaptureManager == null) {
32213                 return;
32214             }
32215 
32216             ArrayList<Object> events = ensureEvents(
32217                         mContentCaptureManager.getMainContentCaptureSession());
32218             events.add(insets);
32219         }
32220 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)32221         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
32222                 @NonNull View view, boolean appeared) {
32223             ArrayList<Object> events = ensureEvents(session);
32224             events.add(appeared ? view : view.getAutofillId());
32225         }
32226 
32227         @NonNull
ensureEvents(@onNull ContentCaptureSession session)32228         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
32229             if (mContentCaptureEvents == null) {
32230                 // Most of the time there will be just one session, so intial capacity is 1
32231                 mContentCaptureEvents = new SparseArray<>(1);
32232             }
32233             int sessionId = session.getId();
32234             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
32235             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
32236             if (events == null) {
32237                 events = new ArrayList<>();
32238                 mContentCaptureEvents.put(sessionId, events);
32239             }
32240 
32241             return events;
32242         }
32243 
canPerformHapticFeedback()32244         private boolean canPerformHapticFeedback() {
32245             return mSession != null
32246                     && (mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) == 0;
32247         }
32248 
32249         @Nullable
getScrollCaptureInternal()32250         ScrollCaptureInternal getScrollCaptureInternal() {
32251             if (mScrollCaptureInternal != null) {
32252                 mScrollCaptureInternal = new ScrollCaptureInternal();
32253             }
32254             return mScrollCaptureInternal;
32255         }
32256 
getRootSurfaceControl()32257         AttachedSurfaceControl getRootSurfaceControl() {
32258             return mViewRootImpl;
32259         }
32260 
dump(String prefix, PrintWriter writer)32261         public void dump(String prefix, PrintWriter writer) {
32262             String innerPrefix = prefix + "  ";
32263             writer.println(prefix + "AttachInfo:");
32264             writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
32265             writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
32266             writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
32267             writer.println(innerPrefix + "mUnbufferedDispatchRequested="
32268                     + mUnbufferedDispatchRequested);
32269         }
32270     }
32271 
32272     /**
32273      * <p>ScrollabilityCache holds various fields used by a View when scrolling
32274      * is supported. This avoids keeping too many unused fields in most
32275      * instances of View.</p>
32276      */
32277     private static class ScrollabilityCache implements Runnable {
32278 
32279         /**
32280          * Scrollbars are not visible
32281          */
32282         public static final int OFF = 0;
32283 
32284         /**
32285          * Scrollbars are visible
32286          */
32287         public static final int ON = 1;
32288 
32289         /**
32290          * Scrollbars are fading away
32291          */
32292         public static final int FADING = 2;
32293 
32294         public boolean fadeScrollBars;
32295 
32296         public int fadingEdgeLength;
32297         public int scrollBarDefaultDelayBeforeFade;
32298         public int scrollBarFadeDuration;
32299 
32300         public int scrollBarSize;
32301         public int scrollBarMinTouchTarget;
32302         @UnsupportedAppUsage
32303         public ScrollBarDrawable scrollBar;
32304         public float[] interpolatorValues;
32305         @UnsupportedAppUsage
32306         public View host;
32307 
32308         public final Paint paint;
32309         public final Matrix matrix;
32310         public Shader shader;
32311 
32312         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
32313 
32314         private static final float[] OPAQUE = { 255 };
32315         private static final float[] TRANSPARENT = { 0.0f };
32316 
32317         /**
32318          * When fading should start. This time moves into the future every time
32319          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
32320          */
32321         public long fadeStartTime;
32322 
32323 
32324         /**
32325          * The current state of the scrollbars: ON, OFF, or FADING
32326          */
32327         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
32328         public int state = OFF;
32329 
32330         private int mLastColor;
32331 
32332         public final Rect mScrollBarBounds = new Rect();
32333         public final Rect mScrollBarTouchBounds = new Rect();
32334 
32335         public static final int NOT_DRAGGING = 0;
32336         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
32337         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
32338         public int mScrollBarDraggingState = NOT_DRAGGING;
32339 
32340         public float mScrollBarDraggingPos = 0;
32341 
ScrollabilityCache(ViewConfiguration configuration, View host)32342         public ScrollabilityCache(ViewConfiguration configuration, View host) {
32343             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
32344             scrollBarSize = configuration.getScaledScrollBarSize();
32345             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
32346             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
32347             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
32348 
32349             paint = new Paint();
32350             matrix = new Matrix();
32351             // use use a height of 1, and then wack the matrix each time we
32352             // actually use it.
32353             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
32354             paint.setShader(shader);
32355             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
32356 
32357             this.host = host;
32358         }
32359 
setFadeColor(int color)32360         public void setFadeColor(int color) {
32361             if (color != mLastColor) {
32362                 mLastColor = color;
32363 
32364                 if (color != 0) {
32365                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
32366                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
32367                     paint.setShader(shader);
32368                     // Restore the default transfer mode (src_over)
32369                     paint.setXfermode(null);
32370                 } else {
32371                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
32372                     paint.setShader(shader);
32373                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
32374                 }
32375             }
32376         }
32377 
run()32378         public void run() {
32379             long now = AnimationUtils.currentAnimationTimeMillis();
32380             if (now >= fadeStartTime) {
32381 
32382                 // the animation fades the scrollbars out by changing
32383                 // the opacity (alpha) from fully opaque to fully
32384                 // transparent
32385                 int nextFrame = (int) now;
32386                 int framesCount = 0;
32387 
32388                 Interpolator interpolator = scrollBarInterpolator;
32389 
32390                 // Start opaque
32391                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
32392 
32393                 // End transparent
32394                 nextFrame += scrollBarFadeDuration;
32395                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
32396 
32397                 state = FADING;
32398 
32399                 // Kick off the fade animation
32400                 host.invalidate(true);
32401             }
32402         }
32403     }
32404 
32405     private class SendAccessibilityEventThrottle implements Runnable {
32406         public volatile boolean mIsPending;
32407         private AccessibilityEvent mAccessibilityEvent;
32408 
post(AccessibilityEvent accessibilityEvent)32409         public void post(AccessibilityEvent accessibilityEvent) {
32410             updateWithAccessibilityEvent(accessibilityEvent);
32411             if (!mIsPending) {
32412                 mIsPending = true;
32413                 postDelayed(this,
32414                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
32415             }
32416         }
32417 
32418         @Override
run()32419         public void run() {
32420             if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
32421                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
32422             }
32423             reset();
32424         }
32425 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)32426         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
32427             mAccessibilityEvent = accessibilityEvent;
32428         }
32429 
reset()32430         public void reset() {
32431             mIsPending = false;
32432             mAccessibilityEvent = null;
32433         }
32434 
32435     }
32436 
32437     /**
32438      * Resuable callback for sending
32439      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
32440      */
32441     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
32442         public int mDeltaX;
32443         public int mDeltaY;
32444 
32445         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)32446         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
32447             super.updateWithAccessibilityEvent(accessibilityEvent);
32448             mDeltaX += accessibilityEvent.getScrollDeltaX();
32449             mDeltaY += accessibilityEvent.getScrollDeltaY();
32450             accessibilityEvent.setScrollDeltaX(mDeltaX);
32451             accessibilityEvent.setScrollDeltaY(mDeltaY);
32452         }
32453 
32454         @Override
reset()32455         public void reset() {
32456             super.reset();
32457             mDeltaX = 0;
32458             mDeltaY = 0;
32459         }
32460     }
32461     /**
32462      * Remove the pending callback for sending a throttled accessibility event.
32463      */
32464     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)32465     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
32466         if (callback == null || !callback.mIsPending) return;
32467         removeCallbacks(callback);
32468         callback.reset();
32469     }
32470 
32471     /**
32472      * <p>
32473      * This class represents a delegate that can be registered in a {@link View}
32474      * to enhance accessibility support via composition rather via inheritance.
32475      * It is specifically targeted to widget developers that extend basic View
32476      * classes i.e. classes in package android.view, that would like their
32477      * applications to be backwards compatible.
32478      * </p>
32479      * <div class="special reference">
32480      * <h3>Developer Guides</h3>
32481      * <p>For more information about making applications accessible, read the
32482      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
32483      * developer guide.</p>
32484      * </div>
32485      * <p>
32486      * A scenario in which a developer would like to use an accessibility delegate
32487      * is overriding a method introduced in a later API version than the minimal API
32488      * version supported by the application. For example, the method
32489      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
32490      * in API version 4 when the accessibility APIs were first introduced. If a
32491      * developer would like their application to run on API version 4 devices (assuming
32492      * all other APIs used by the application are version 4 or lower) and take advantage
32493      * of this method, instead of overriding the method which would break the application's
32494      * backwards compatibility, they can override the corresponding method in this
32495      * delegate and register the delegate in the target View if the API version of
32496      * the system is high enough, i.e. the API version is the same as or higher than the API
32497      * version that introduced
32498      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
32499      * </p>
32500      * <p>
32501      * Here is an example implementation:
32502      * </p>
32503      * <code><pre><p>
32504      * if (Build.VERSION.SDK_INT >= 14) {
32505      *     // If the API version is equal of higher than the version in
32506      *     // which onInitializeAccessibilityNodeInfo was introduced we
32507      *     // register a delegate with a customized implementation.
32508      *     View view = findViewById(R.id.view_id);
32509      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
32510      *         public void onInitializeAccessibilityNodeInfo(View host,
32511      *                 AccessibilityNodeInfo info) {
32512      *             // Let the default implementation populate the info.
32513      *             super.onInitializeAccessibilityNodeInfo(host, info);
32514      *             // Set some other information.
32515      *             info.setEnabled(host.isEnabled());
32516      *         }
32517      *     });
32518      * }
32519      * </code></pre></p>
32520      * <p>
32521      * This delegate contains methods that correspond to the accessibility methods
32522      * in View. If a delegate has been specified the implementation in View hands
32523      * off handling to the corresponding method in this delegate. The default
32524      * implementation the delegate methods behaves exactly as the corresponding
32525      * method in View for the case of no accessibility delegate been set. Hence,
32526      * to customize the behavior of a View method, clients can override only the
32527      * corresponding delegate method without altering the behavior of the rest
32528      * accessibility related methods of the host view.
32529      * </p>
32530      * <p>
32531      * <strong>Note:</strong> On platform versions prior to
32532      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
32533      * views in the {@code android.widget.*} package are called <i>before</i>
32534      * host methods. This prevents certain properties such as class name from
32535      * being modified by overriding
32536      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
32537      * as any changes will be overwritten by the host class.
32538      * <p>
32539      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
32540      * methods are called <i>after</i> host methods, which all properties to be
32541      * modified without being overwritten by the host class.
32542      * <aside class="note">
32543      * <b>Note:</b> Use a {@link androidx.core.view.AccessibilityDelegateCompat}
32544      * wrapper instead of this class for backwards-compatibility.
32545      * </aside>
32546      *
32547      */
32548     public static class AccessibilityDelegate {
32549 
32550         /**
32551          * Sends an accessibility event of the given type. If accessibility is not
32552          * enabled this method has no effect.
32553          * <p>
32554          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
32555          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
32556          * been set.
32557          * </p>
32558          *
32559          * @param host The View hosting the delegate.
32560          * @param eventType The type of the event to send.
32561          *
32562          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
32563          */
sendAccessibilityEvent(@onNull View host, int eventType)32564         public void sendAccessibilityEvent(@NonNull View host, int eventType) {
32565             host.sendAccessibilityEventInternal(eventType);
32566         }
32567 
32568         /**
32569          * Performs the specified accessibility action on the view. For
32570          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
32571          * <p>
32572          * The default implementation behaves as
32573          * {@link View#performAccessibilityAction(int, Bundle)
32574          *  View#performAccessibilityAction(int, Bundle)} for the case of
32575          *  no accessibility delegate been set.
32576          * </p>
32577          *
32578          * @param action The action to perform.
32579          * @return Whether the action was performed.
32580          *
32581          * @see View#performAccessibilityAction(int, Bundle)
32582          *      View#performAccessibilityAction(int, Bundle)
32583          */
performAccessibilityAction(@onNull View host, int action, @Nullable Bundle args)32584         public boolean performAccessibilityAction(@NonNull View host, int action,
32585                 @Nullable Bundle args) {
32586             return host.performAccessibilityActionInternal(action, args);
32587         }
32588 
32589         /**
32590          * Sends an accessibility event. This method behaves exactly as
32591          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
32592          * empty {@link AccessibilityEvent} and does not perform a check whether
32593          * accessibility is enabled.
32594          * <p>
32595          * The default implementation behaves as
32596          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
32597          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
32598          * the case of no accessibility delegate been set.
32599          * </p>
32600          *
32601          * @param host The View hosting the delegate.
32602          * @param event The event to send.
32603          *
32604          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
32605          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
32606          */
sendAccessibilityEventUnchecked(@onNull View host, @NonNull AccessibilityEvent event)32607         public void sendAccessibilityEventUnchecked(@NonNull View host,
32608                 @NonNull AccessibilityEvent event) {
32609             host.sendAccessibilityEventUncheckedInternal(event);
32610         }
32611 
32612         /**
32613          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
32614          * to its children for adding their text content to the event.
32615          * <p>
32616          * The default implementation behaves as
32617          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
32618          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
32619          * the case of no accessibility delegate been set.
32620          * </p>
32621          *
32622          * @param host The View hosting the delegate.
32623          * @param event The event.
32624          * @return True if the event population was completed.
32625          *
32626          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
32627          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
32628          */
dispatchPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)32629         public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
32630                 @NonNull AccessibilityEvent event) {
32631             return host.dispatchPopulateAccessibilityEventInternal(event);
32632         }
32633 
32634         /**
32635          * Gives a chance to the host View to populate the accessibility event with its
32636          * text content.
32637          * <p>
32638          * The default implementation behaves as
32639          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
32640          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
32641          * the case of no accessibility delegate been set.
32642          * </p>
32643          *
32644          * @param host The View hosting the delegate.
32645          * @param event The accessibility event which to populate.
32646          *
32647          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
32648          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
32649          */
onPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)32650         public void onPopulateAccessibilityEvent(@NonNull View host,
32651                 @NonNull AccessibilityEvent event) {
32652             host.onPopulateAccessibilityEventInternal(event);
32653         }
32654 
32655         /**
32656          * Initializes an {@link AccessibilityEvent} with information about the
32657          * the host View which is the event source.
32658          * <p>
32659          * The default implementation behaves as
32660          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
32661          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
32662          * the case of no accessibility delegate been set.
32663          * </p>
32664          *
32665          * @param host The View hosting the delegate.
32666          * @param event The event to initialize.
32667          *
32668          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
32669          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
32670          */
onInitializeAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)32671         public void onInitializeAccessibilityEvent(@NonNull View host,
32672                 @NonNull AccessibilityEvent event) {
32673             host.onInitializeAccessibilityEventInternal(event);
32674         }
32675 
32676         /**
32677          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
32678          * <p>
32679          * The default implementation behaves as
32680          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
32681          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
32682          * the case of no accessibility delegate been set.
32683          * </p>
32684          *
32685          * @param host The View hosting the delegate.
32686          * @param info The instance to initialize.
32687          *
32688          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
32689          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
32690          */
onInitializeAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info)32691         public void onInitializeAccessibilityNodeInfo(@NonNull View host,
32692                 @NonNull AccessibilityNodeInfo info) {
32693             host.onInitializeAccessibilityNodeInfoInternal(info);
32694         }
32695 
32696         /**
32697          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
32698          * additional data.
32699          * <p>
32700          * This method only needs to be implemented if the View offers to provide additional data.
32701          * </p>
32702          * <p>
32703          * The default implementation behaves as
32704          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
32705          * for the case where no accessibility delegate is set.
32706          * </p>
32707          *
32708          * @param host The View hosting the delegate. Never {@code null}.
32709          * @param info The info to which to add the extra data. Never {@code null}.
32710          * @param extraDataKey A key specifying the type of extra data to add to the info. The
32711          *                     extra data should be added to the {@link Bundle} returned by
32712          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
32713          *                     {@code null}.
32714          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
32715          *                  May be {@code null} if the if the service provided no arguments.
32716          *
32717          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
32718          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)32719         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
32720                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
32721                 @Nullable Bundle arguments) {
32722             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
32723         }
32724 
32725         /**
32726          * Called when a child of the host View has requested sending an
32727          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
32728          * to augment the event.
32729          * <p>
32730          * The default implementation behaves as
32731          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
32732          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
32733          * the case of no accessibility delegate been set.
32734          * </p>
32735          *
32736          * @param host The View hosting the delegate.
32737          * @param child The child which requests sending the event.
32738          * @param event The event to be sent.
32739          * @return True if the event should be sent
32740          *
32741          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
32742          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
32743          */
onRequestSendAccessibilityEvent(@onNull ViewGroup host, @NonNull View child, @NonNull AccessibilityEvent event)32744         public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
32745                 @NonNull AccessibilityEvent event) {
32746             return host.onRequestSendAccessibilityEventInternal(child, event);
32747         }
32748 
32749         /**
32750          * Gets the provider for managing a virtual view hierarchy rooted at this View
32751          * and reported to {@link android.accessibilityservice.AccessibilityService}s
32752          * that explore the window content.
32753          * <p>
32754          * The default implementation behaves as
32755          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
32756          * the case of no accessibility delegate been set.
32757          * </p>
32758          *
32759          * @return The provider.
32760          *
32761          * @see AccessibilityNodeProvider
32762          */
getAccessibilityNodeProvider( @onNull View host)32763         public @Nullable AccessibilityNodeProvider getAccessibilityNodeProvider(
32764                 @NonNull View host) {
32765             return null;
32766         }
32767 
32768         /**
32769          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
32770          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
32771          * This method is responsible for obtaining an accessibility node info from a
32772          * pool of reusable instances and calling
32773          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
32774          * view to initialize the former.
32775          * <p>
32776          * <strong>Note:</strong> The client is responsible for recycling the obtained
32777          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
32778          * creation.
32779          * </p>
32780          * <p>
32781          * The default implementation behaves as
32782          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
32783          * the case of no accessibility delegate been set.
32784          * </p>
32785          * @return A populated {@link AccessibilityNodeInfo}.
32786          *
32787          * @see AccessibilityNodeInfo
32788          *
32789          * @hide
32790          */
32791         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
createAccessibilityNodeInfo(@onNull View host)32792         public AccessibilityNodeInfo createAccessibilityNodeInfo(@NonNull View host) {
32793             return host.createAccessibilityNodeInfoInternal();
32794         }
32795     }
32796 
32797     private static class MatchIdPredicate implements Predicate<View> {
32798         public int mId;
32799 
32800         @Override
test(View view)32801         public boolean test(View view) {
32802             return (view.mID == mId);
32803         }
32804     }
32805 
32806     private static class MatchLabelForPredicate implements Predicate<View> {
32807         private int mLabeledId;
32808 
32809         @Override
test(View view)32810         public boolean test(View view) {
32811             return (view.mLabelForId == mLabeledId);
32812         }
32813     }
32814 
32815     private static class SensitiveAutofillHintsHelper {
32816         /**
32817          * List of autofill hints deemed sensitive for screen protection during screen share.
32818          */
32819         private static final ArraySet<String> SENSITIVE_CONTENT_AUTOFILL_HINTS = new ArraySet<>();
32820         static {
32821             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME);
32822             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO);
32823             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD);
32824             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
32825             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
32826             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
32827             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY);
32828             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
32829             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
32830             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDENTIAL_MANAGER);
32831         }
32832 
32833         /**
32834          * Whether View's autofill hints contains a sensitive autofill hint.
32835          *
32836          * @see #SENSITIVE_CONTENT_AUTOFILL_HINTS
32837          */
containsSensitiveAutofillHint(@ullable String[] autofillHints)32838         static boolean containsSensitiveAutofillHint(@Nullable String[] autofillHints) {
32839             if (autofillHints == null) {
32840                 return false;
32841             }
32842 
32843             int size = autofillHints.length;
32844             for (int i = 0; i < size; i++) {
32845                 if (SENSITIVE_CONTENT_AUTOFILL_HINTS.contains(autofillHints[i])) {
32846                     return true;
32847                 }
32848             }
32849             return false;
32850         }
32851     }
32852 
32853     /**
32854      * Returns the current scroll capture hint for this view.
32855      *
32856      * @return the current scroll capture hint
32857      */
32858     @ScrollCaptureHint
getScrollCaptureHint()32859     public int getScrollCaptureHint() {
32860         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
32861                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
32862     }
32863 
32864     /**
32865      * Sets the scroll capture hint for this View. These flags affect the search for a potential
32866      * scroll capture targets.
32867      *
32868      * @param hint the scrollCaptureHint flags value to set
32869      */
setScrollCaptureHint(@crollCaptureHint int hint)32870     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
32871         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
32872         // Since include/exclude are mutually exclusive, exclude takes precedence.
32873         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
32874             hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
32875         }
32876         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
32877                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
32878     }
32879 
32880     /**
32881      * Sets the callback to receive scroll capture requests. This component is the adapter between
32882      * the scroll capture API and application UI code. If no callback is set, the system may provide
32883      * an implementation. Any value provided here will take precedence over a system version.
32884      * <p>
32885      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
32886      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
32887      * <p>
32888      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
32889      * setting a custom callback to help ensure it is selected as the target.
32890      *
32891      * @param callback the new callback to assign
32892      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)32893     public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
32894         getListenerInfo().mScrollCaptureCallback = callback;
32895     }
32896 
32897     /** {@hide} */
32898     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)32899     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
32900             @NonNull Point windowOffset) {
32901         if (mAttachInfo == null) {
32902             return null;
32903         }
32904         if (mAttachInfo.mScrollCaptureInternal == null) {
32905             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
32906         }
32907         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
32908                 windowOffset);
32909     }
32910 
32911     /**
32912      * Dispatch a scroll capture search request down the view hierarchy.
32913      *
32914      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
32915      *                         the parent
32916      * @param windowOffset     the offset of this view within the window
32917      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
32918      *                         results.accept} may be called zero or more times on the calling
32919      *                         thread before onScrollCaptureSearch returns
32920      */
dispatchScrollCaptureSearch( @onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)32921     public void dispatchScrollCaptureSearch(
32922             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
32923             @NonNull Consumer<ScrollCaptureTarget> targets) {
32924         onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
32925     }
32926 
32927     /**
32928      * Called when scroll capture is requested, to search for appropriate content to scroll. If
32929      * applicable, this view adds itself to the provided list for consideration, subject to the
32930      * flags set by {@link #setScrollCaptureHint}.
32931      *
32932      * @param localVisibleRect the local visible rect of this view
32933      * @param windowOffset     the offset of localVisibleRect within the window
32934      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
32935      *                         results.accept} may be called zero or more times on the calling
32936      *                         thread before onScrollCaptureSearch returns
32937      * @throws IllegalStateException if this view is not attached to a window
32938      */
onScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)32939     public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
32940             @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
32941         int hint = getScrollCaptureHint();
32942         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
32943             return;
32944         }
32945         boolean rectIsVisible = true;
32946 
32947         // Apply clipBounds if present.
32948         if (mClipBounds != null) {
32949             rectIsVisible = localVisibleRect.intersect(mClipBounds);
32950         }
32951         if (!rectIsVisible) {
32952             return;
32953         }
32954 
32955         // Get a callback provided by the framework, library or application.
32956         ScrollCaptureCallback callback =
32957                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
32958 
32959         // Try framework support for standard scrolling containers.
32960         if (callback == null) {
32961             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
32962         }
32963 
32964         // If found, then add it to the list.
32965         if (callback != null) {
32966             // Add to the list for consideration
32967             Point offset = new Point(windowOffset.x, windowOffset.y);
32968             Rect rect = new Rect(localVisibleRect);
32969             targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
32970         }
32971     }
32972 
32973     /**
32974      * Dump all private flags in readable format, useful for documentation and
32975      * consistency checking.
32976      */
dumpFlags()32977     private static void dumpFlags() {
32978         final HashMap<String, String> found = Maps.newHashMap();
32979         try {
32980             for (Field field : View.class.getDeclaredFields()) {
32981                 final int modifiers = field.getModifiers();
32982                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
32983                     if (field.getType().equals(int.class)) {
32984                         final int value = field.getInt(null);
32985                         dumpFlag(found, field.getName(), value);
32986                     } else if (field.getType().equals(int[].class)) {
32987                         final int[] values = (int[]) field.get(null);
32988                         for (int i = 0; i < values.length; i++) {
32989                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
32990                         }
32991                     }
32992                 }
32993             }
32994         } catch (IllegalAccessException e) {
32995             throw new RuntimeException(e);
32996         }
32997 
32998         final ArrayList<String> keys = Lists.newArrayList();
32999         keys.addAll(found.keySet());
33000         Collections.sort(keys);
33001         for (String key : keys) {
33002             Log.d(VIEW_LOG_TAG, found.get(key));
33003         }
33004     }
33005 
dumpFlag(HashMap<String, String> found, String name, int value)33006     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
33007         // Sort flags by prefix, then by bits, always keeping unique keys
33008         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
33009         final int prefix = name.indexOf('_');
33010         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
33011         final String output = bits + " " + name;
33012         found.put(key, output);
33013     }
33014 
33015     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)33016     public void encode(@NonNull ViewHierarchyEncoder stream) {
33017         stream.beginObject(this);
33018         encodeProperties(stream);
33019         stream.endObject();
33020     }
33021 
33022     /** {@hide} */
33023     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)33024     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
33025         Object resolveId = ViewDebug.resolveId(getContext(), mID);
33026         if (resolveId instanceof String) {
33027             stream.addProperty("id", (String) resolveId);
33028         } else {
33029             stream.addProperty("id", mID);
33030         }
33031 
33032         stream.addProperty("misc:transformation.alpha",
33033                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
33034         stream.addProperty("misc:transitionName", getTransitionName());
33035 
33036         // layout
33037         stream.addProperty("layout:left", mLeft);
33038         stream.addProperty("layout:right", mRight);
33039         stream.addProperty("layout:top", mTop);
33040         stream.addProperty("layout:bottom", mBottom);
33041         stream.addProperty("layout:width", getWidth());
33042         stream.addProperty("layout:height", getHeight());
33043         stream.addProperty("layout:layoutDirection", getLayoutDirection());
33044         stream.addProperty("layout:layoutRtl", isLayoutRtl());
33045         stream.addProperty("layout:hasTransientState", hasTransientState());
33046         stream.addProperty("layout:baseline", getBaseline());
33047 
33048         // layout params
33049         ViewGroup.LayoutParams layoutParams = getLayoutParams();
33050         if (layoutParams != null) {
33051             stream.addPropertyKey("layoutParams");
33052             layoutParams.encode(stream);
33053         }
33054 
33055         // scrolling
33056         stream.addProperty("scrolling:scrollX", mScrollX);
33057         stream.addProperty("scrolling:scrollY", mScrollY);
33058 
33059         // padding
33060         stream.addProperty("padding:paddingLeft", mPaddingLeft);
33061         stream.addProperty("padding:paddingRight", mPaddingRight);
33062         stream.addProperty("padding:paddingTop", mPaddingTop);
33063         stream.addProperty("padding:paddingBottom", mPaddingBottom);
33064         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
33065         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
33066         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
33067         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
33068         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
33069 
33070         // measurement
33071         stream.addProperty("measurement:minHeight", mMinHeight);
33072         stream.addProperty("measurement:minWidth", mMinWidth);
33073         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
33074         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
33075 
33076         // drawing
33077         stream.addProperty("drawing:elevation", getElevation());
33078         stream.addProperty("drawing:translationX", getTranslationX());
33079         stream.addProperty("drawing:translationY", getTranslationY());
33080         stream.addProperty("drawing:translationZ", getTranslationZ());
33081         stream.addProperty("drawing:rotation", getRotation());
33082         stream.addProperty("drawing:rotationX", getRotationX());
33083         stream.addProperty("drawing:rotationY", getRotationY());
33084         stream.addProperty("drawing:scaleX", getScaleX());
33085         stream.addProperty("drawing:scaleY", getScaleY());
33086         stream.addProperty("drawing:pivotX", getPivotX());
33087         stream.addProperty("drawing:pivotY", getPivotY());
33088         stream.addProperty("drawing:clipBounds",
33089                 mClipBounds == null ? null : mClipBounds.toString());
33090         stream.addProperty("drawing:opaque", isOpaque());
33091         stream.addProperty("drawing:alpha", getAlpha());
33092         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
33093         stream.addProperty("drawing:shadow", hasShadow());
33094         stream.addProperty("drawing:solidColor", getSolidColor());
33095         stream.addProperty("drawing:layerType", mLayerType);
33096         stream.addProperty("drawing:willNotDraw", willNotDraw());
33097         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
33098         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
33099         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
33100         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
33101         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
33102         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
33103 
33104         // focus
33105         stream.addProperty("focus:hasFocus", hasFocus());
33106         stream.addProperty("focus:isFocused", isFocused());
33107         stream.addProperty("focus:focusable", getFocusable());
33108         stream.addProperty("focus:isFocusable", isFocusable());
33109         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
33110 
33111         stream.addProperty("misc:clickable", isClickable());
33112         stream.addProperty("misc:pressed", isPressed());
33113         stream.addProperty("misc:selected", isSelected());
33114         stream.addProperty("misc:touchMode", isInTouchMode());
33115         stream.addProperty("misc:hovered", isHovered());
33116         stream.addProperty("misc:activated", isActivated());
33117 
33118         stream.addProperty("misc:visibility", getVisibility());
33119         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
33120         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
33121 
33122         stream.addProperty("misc:enabled", isEnabled());
33123         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
33124         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
33125 
33126         // theme attributes
33127         Resources.Theme theme = getContext().getTheme();
33128         if (theme != null) {
33129             stream.addPropertyKey("theme");
33130             theme.encode(stream);
33131         }
33132 
33133         // view attribute information
33134         int n = mAttributes != null ? mAttributes.length : 0;
33135         stream.addProperty("meta:__attrCount__", n/2);
33136         for (int i = 0; i < n; i += 2) {
33137             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
33138         }
33139 
33140         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
33141 
33142         // text
33143         stream.addProperty("text:textDirection", getTextDirection());
33144         stream.addProperty("text:textAlignment", getTextAlignment());
33145 
33146         // accessibility
33147         CharSequence contentDescription = getContentDescription();
33148         stream.addUserProperty("accessibility:contentDescription",
33149                 contentDescription == null ? "" : contentDescription.toString());
33150         stream.addProperty("accessibility:labelFor", getLabelFor());
33151         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
33152     }
33153 
33154     /**
33155      * Determine if this view is rendered on a round wearable device and is the main view
33156      * on the screen.
33157      */
shouldDrawRoundScrollbar()33158     boolean shouldDrawRoundScrollbar() {
33159         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
33160             return false;
33161         }
33162 
33163         final View rootView = getRootView();
33164         final WindowInsets insets = getRootWindowInsets();
33165 
33166         int height = getHeight();
33167         int width = getWidth();
33168         int displayHeight = rootView.getHeight();
33169         int displayWidth = rootView.getWidth();
33170 
33171         if (height != displayHeight || width != displayWidth) {
33172             return false;
33173         }
33174 
33175         return true;
33176     }
33177 
33178     /**
33179      * Sets the tooltip text which will be displayed in a small popup next to the view.
33180      * <p>
33181      * The tooltip will be displayed:
33182      * <ul>
33183      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
33184      * menu). </li>
33185      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
33186      * </ul>
33187      * <p>
33188      * <strong>Note:</strong> Do not override this method, as it will have no
33189      * effect on the text displayed in the tooltip.
33190      *
33191      * @param tooltipText the tooltip text, or null if no tooltip is required
33192      * @see #getTooltipText()
33193      * @attr ref android.R.styleable#View_tooltipText
33194      */
setTooltipText(@ullable CharSequence tooltipText)33195     public void setTooltipText(@Nullable CharSequence tooltipText) {
33196         if (TextUtils.isEmpty(tooltipText)) {
33197             setFlags(0, TOOLTIP);
33198             hideTooltip();
33199             mTooltipInfo = null;
33200         } else {
33201             setFlags(TOOLTIP, TOOLTIP);
33202             if (mTooltipInfo == null) {
33203                 mTooltipInfo = new TooltipInfo();
33204                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
33205                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
33206                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
33207                 mTooltipInfo.clearAnchorPos();
33208             }
33209             mTooltipInfo.mTooltipText = tooltipText;
33210         }
33211     }
33212 
33213     /**
33214      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
33215      */
33216     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)33217     public void setTooltip(@Nullable CharSequence tooltipText) {
33218         setTooltipText(tooltipText);
33219     }
33220 
33221     /**
33222      * Returns the view's tooltip text.
33223      *
33224      * <strong>Note:</strong> Do not override this method, as it will have no
33225      * effect on the text displayed in the tooltip. You must call
33226      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
33227      *
33228      * @return the tooltip text
33229      * @see #setTooltipText(CharSequence)
33230      * @attr ref android.R.styleable#View_tooltipText
33231      */
33232     @InspectableProperty
33233     @Nullable
getTooltipText()33234     public CharSequence getTooltipText() {
33235         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
33236     }
33237 
33238     /**
33239      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
33240      */
33241     @Nullable
getTooltip()33242     public CharSequence getTooltip() {
33243         return getTooltipText();
33244     }
33245 
showTooltip(int x, int y, boolean fromLongClick)33246     private boolean showTooltip(int x, int y, boolean fromLongClick) {
33247         if (mAttachInfo == null || mTooltipInfo == null) {
33248             return false;
33249         }
33250         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
33251             return false;
33252         }
33253         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
33254             return false;
33255         }
33256         hideTooltip();
33257         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
33258         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
33259         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
33260         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
33261         mAttachInfo.mTooltipHost = this;
33262         // The available accessibility actions have changed
33263         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
33264         return true;
33265     }
33266 
33267     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hideTooltip()33268     void hideTooltip() {
33269         if (mTooltipInfo == null) {
33270             return;
33271         }
33272         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
33273         if (mTooltipInfo.mTooltipPopup == null) {
33274             return;
33275         }
33276         mTooltipInfo.mTooltipPopup.hide();
33277         mTooltipInfo.mTooltipPopup = null;
33278         mTooltipInfo.mTooltipFromLongClick = false;
33279         mTooltipInfo.clearAnchorPos();
33280         if (mAttachInfo != null) {
33281             mAttachInfo.mTooltipHost = null;
33282         }
33283         // The available accessibility actions have changed
33284         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
33285     }
33286 
showLongClickTooltip(int x, int y)33287     private boolean showLongClickTooltip(int x, int y) {
33288         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
33289         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
33290         return showTooltip(x, y, true);
33291     }
33292 
showHoverTooltip()33293     private boolean showHoverTooltip() {
33294         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
33295     }
33296 
dispatchTooltipHoverEvent(MotionEvent event)33297     boolean dispatchTooltipHoverEvent(MotionEvent event) {
33298         if (mTooltipInfo == null) {
33299             return false;
33300         }
33301         switch(event.getAction()) {
33302             case MotionEvent.ACTION_HOVER_MOVE:
33303                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
33304                     break;
33305                 }
33306                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
33307                     if (mTooltipInfo.mTooltipPopup == null) {
33308                         // Schedule showing the tooltip after a timeout.
33309                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
33310                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
33311                                 ViewConfiguration.getHoverTooltipShowTimeout());
33312                     }
33313 
33314                     // Hide hover-triggered tooltip after a period of inactivity.
33315                     // Match the timeout used by NativeInputManager to hide the mouse pointer
33316                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
33317                     final int timeout;
33318                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
33319                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
33320                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
33321                     } else {
33322                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
33323                     }
33324                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
33325                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
33326                 }
33327                 return true;
33328 
33329             case MotionEvent.ACTION_HOVER_EXIT:
33330                 mTooltipInfo.clearAnchorPos();
33331                 if (!mTooltipInfo.mTooltipFromLongClick) {
33332                     hideTooltip();
33333                 }
33334                 break;
33335         }
33336         return false;
33337     }
33338 
handleTooltipKey(KeyEvent event)33339     void handleTooltipKey(KeyEvent event) {
33340         switch (event.getAction()) {
33341             case KeyEvent.ACTION_DOWN:
33342                 if (event.getRepeatCount() == 0) {
33343                     hideTooltip();
33344                 }
33345                 break;
33346 
33347             case KeyEvent.ACTION_UP:
33348                 handleTooltipUp();
33349                 break;
33350         }
33351     }
33352 
handleTooltipUp()33353     private void handleTooltipUp() {
33354         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
33355             return;
33356         }
33357         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
33358         postDelayed(mTooltipInfo.mHideTooltipRunnable,
33359                 ViewConfiguration.getLongPressTooltipHideTimeout());
33360     }
33361 
getFocusableAttribute(TypedArray attributes)33362     private int getFocusableAttribute(TypedArray attributes) {
33363         TypedValue val = new TypedValue();
33364         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
33365             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
33366                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
33367             } else {
33368                 return val.data;
33369             }
33370         } else {
33371             return FOCUSABLE_AUTO;
33372         }
33373     }
33374 
33375     /**
33376      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
33377      * is not showing.
33378      * @hide
33379      */
33380     @TestApi
getTooltipView()33381     public View getTooltipView() {
33382         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
33383             return null;
33384         }
33385         return mTooltipInfo.mTooltipPopup.getContentView();
33386     }
33387 
33388     /**
33389      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
33390      * @hide
33391      */
33392     @TestApi
isDefaultFocusHighlightEnabled()33393     public static boolean isDefaultFocusHighlightEnabled() {
33394         return sUseDefaultFocusHighlight;
33395     }
33396 
33397     /**
33398      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
33399      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
33400      * (visually on-top views first).
33401      *
33402      * @param evt the previously unhandled {@link KeyEvent}.
33403      * @return the {@link View} which consumed the event or {@code null} if not consumed.
33404      */
dispatchUnhandledKeyEvent(KeyEvent evt)33405     View dispatchUnhandledKeyEvent(KeyEvent evt) {
33406         if (onUnhandledKeyEvent(evt)) {
33407             return this;
33408         }
33409         return null;
33410     }
33411 
33412     /**
33413      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
33414      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
33415      * this will dispatch into all the listeners registered via
33416      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
33417      * order (most recently added will receive events first).
33418      *
33419      * @param event An unhandled event.
33420      * @return {@code true} if the event was handled, {@code false} otherwise.
33421      * @see #addOnUnhandledKeyEventListener
33422      */
onUnhandledKeyEvent(@onNull KeyEvent event)33423     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
33424         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
33425             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
33426                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
33427                     return true;
33428                 }
33429             }
33430         }
33431         return false;
33432     }
33433 
hasUnhandledKeyListener()33434     boolean hasUnhandledKeyListener() {
33435         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
33436                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
33437     }
33438 
33439     /**
33440      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
33441      * UI thread.
33442      *
33443      * @param listener a receiver of unhandled {@link KeyEvent}s.
33444      * @see #removeOnUnhandledKeyEventListener
33445      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)33446     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
33447         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
33448         if (listeners == null) {
33449             listeners = new ArrayList<>();
33450             getListenerInfo().mUnhandledKeyListeners = listeners;
33451         }
33452         listeners.add(listener);
33453         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
33454             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
33455         }
33456     }
33457 
33458     /**
33459      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
33460      * UI thread.
33461      *
33462      * @param listener a receiver of unhandled {@link KeyEvent}s.
33463      * @see #addOnUnhandledKeyEventListener
33464      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)33465     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
33466         if (mListenerInfo != null) {
33467             if (mListenerInfo.mUnhandledKeyListeners != null
33468                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
33469                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
33470                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
33471                     mListenerInfo.mUnhandledKeyListeners = null;
33472                     if (mParent instanceof ViewGroup) {
33473                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
33474                     }
33475                 }
33476             }
33477         }
33478     }
33479 
33480     /**
33481      * Set the view to be detached or not detached.
33482      *
33483      * @param detached Whether the view is detached.
33484      *
33485      * @hide
33486      */
setDetached(boolean detached)33487     protected void setDetached(boolean detached) {
33488         if (detached) {
33489             mPrivateFlags4 |= PFLAG4_DETACHED;
33490         } else {
33491             mPrivateFlags4 &= ~PFLAG4_DETACHED;
33492         }
33493     }
33494 
33495     /**
33496      * Sets whether this view is a credential for Credential Manager purposes.
33497      *
33498      * <p>See {@link #isCredential()}.
33499      *
33500      * @param isCredential Whether the view is a credential.
33501      *
33502      * @attr ref android.R.styleable#View_isCredential
33503      */
setIsCredential(boolean isCredential)33504     public void setIsCredential(boolean isCredential) {
33505         if (isCredential) {
33506             mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
33507         } else {
33508             mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
33509         }
33510     }
33511 
33512     /**
33513      * Gets the mode for determining whether this view is a credential.
33514      *
33515      * <p>See {@link #setIsCredential(boolean)}.
33516      *
33517      * @return false by default, or value passed to {@link #setIsCredential(boolean)}.
33518      *
33519      * @attr ref android.R.styleable#View_isCredential
33520      */
isCredential()33521     public boolean isCredential() {
33522         return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER)
33523                 == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER);
33524     }
33525 
33526     // TODO(316208691): Revive following removed API docs.
33527     // @see EditorInfo#setStylusHandwritingEnabled(boolean)
33528     /**
33529      * Set whether this view enables automatic handwriting initiation.
33530      *
33531      * For a view with an active {@link InputConnection}, if auto handwriting is enabled then
33532      * stylus movement within its view boundary will automatically trigger the handwriting mode.
33533      * Check {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} for
33534      * more details about handwriting mode.
33535      *
33536      * If the View wants to initiate handwriting mode by itself, it can set this field to
33537      * {@code false} and call
33538      * {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} when there
33539      * is stylus movement detected.
33540      *
33541      * Note that this attribute has no effect on the View's children. For example, if a
33542      * {@link ViewGroup} disables auto handwriting but its children set auto handwriting to true,
33543      * auto handwriting will still work for the children, and vice versa.
33544      *
33545      * @see #onCreateInputConnection(EditorInfo)
33546      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
33547      * @param enabled whether auto handwriting initiation is enabled for this view.
33548      * @attr ref android.R.styleable#View_autoHandwritingEnabled
33549      */
setAutoHandwritingEnabled(boolean enabled)33550     public void setAutoHandwritingEnabled(boolean enabled) {
33551         if (enabled) {
33552             mPrivateFlags4 |= PFLAG4_AUTO_HANDWRITING_ENABLED;
33553         } else {
33554             mPrivateFlags4 &= ~PFLAG4_AUTO_HANDWRITING_ENABLED;
33555         }
33556         updatePositionUpdateListener();
33557         postUpdate(this::updateHandwritingArea);
33558     }
33559 
33560     /**
33561      * Return whether the View allows automatic handwriting initiation. Returns true if automatic
33562      * handwriting initiation is enabled, and vice versa.
33563      * @see #setAutoHandwritingEnabled(boolean)
33564      */
isAutoHandwritingEnabled()33565     public boolean isAutoHandwritingEnabled() {
33566         return (mPrivateFlags4 & PFLAG4_AUTO_HANDWRITING_ENABLED)
33567                 == PFLAG4_AUTO_HANDWRITING_ENABLED;
33568     }
33569 
33570     /**
33571      * Return whether the stylus handwriting is available for this View.
33572      * @hide
33573      */
isStylusHandwritingAvailable()33574     public boolean isStylusHandwritingAvailable() {
33575         return getContext().getSystemService(InputMethodManager.class)
33576                 .isStylusHandwritingAvailable();
33577     }
33578 
setTraversalTracingEnabled(boolean enabled)33579     private void setTraversalTracingEnabled(boolean enabled) {
33580         if (enabled) {
33581             if (mTracingStrings == null) {
33582                 mTracingStrings = new ViewTraversalTracingStrings(this);
33583             }
33584             mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
33585         } else {
33586             mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
33587         }
33588     }
33589 
isTraversalTracingEnabled()33590     private boolean isTraversalTracingEnabled() {
33591         return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
33592                 == PFLAG4_TRAVERSAL_TRACING_ENABLED;
33593     }
33594 
setRelayoutTracingEnabled(boolean enabled)33595     private void setRelayoutTracingEnabled(boolean enabled) {
33596         if (enabled) {
33597             if (mTracingStrings == null) {
33598                 mTracingStrings = new ViewTraversalTracingStrings(this);
33599             }
33600             mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
33601         } else {
33602             mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
33603         }
33604     }
33605 
isRelayoutTracingEnabled()33606     private boolean isRelayoutTracingEnabled() {
33607         return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
33608                 == PFLAG4_RELAYOUT_TRACING_ENABLED;
33609     }
33610 
33611     /**
33612      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
33613      * the view.
33614      *
33615      * <p>The default implementation does nothing.</p>
33616      *
33617      * @param supportedFormats the supported translation formats. For now, the only possible value
33618      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
33619      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to
33620      * collect the information to be translated in the view. The {@code requestsCollector} only
33621      * accepts one request; an IllegalStateException is thrown if more than one
33622      * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the
33623      * {@link ViewTranslationRequest}.
33624      */
onCreateViewTranslationRequest(@onNull @ataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)33625     public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
33626             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
33627     }
33628 
33629     /**
33630      * Collects {@link ViewTranslationRequest}s which represents the content to be translated
33631      * for the virtual views in the host view. This is called if this view returned a virtual
33632      * view structure from {@link #onProvideContentCaptureStructure} and the system determined that
33633      * those virtual views were relevant for translation.
33634      *
33635      * <p>The default implementation does nothing.</p>
33636      *
33637      * @param virtualIds the virtual view ids which represents the virtual views in the host
33638      * view.
33639      * @param supportedFormats the supported translation formats. For now, the only possible value
33640      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
33641      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
33642      * multiple times to collect the information to be translated in the host view. One
33643      * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
33644      * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
33645      * Consumer after the method returns.
33646      */
33647     @SuppressLint("NullableCollection")
onCreateVirtualViewTranslationRequests(@onNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)33648     public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
33649             @NonNull @DataFormat int[] supportedFormats,
33650             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
33651         // no-op
33652     }
33653 
33654     /**
33655      * Returns a {@link ViewTranslationCallback} that is used to display the translated information
33656      * or {@code null} if this View doesn't support translation.
33657      *
33658      * @hide
33659      */
33660     @Nullable
getViewTranslationCallback()33661     public ViewTranslationCallback getViewTranslationCallback() {
33662         return mViewTranslationCallback;
33663     }
33664 
33665     /**
33666      * Sets a {@link ViewTranslationCallback} that is used to display/hide the translated
33667      * information. Developers can provide the customized implementation for show/hide translated
33668      * information.
33669      *
33670      * @param callback a {@link ViewTranslationCallback} that is used to control how to display the
33671      * translated information
33672      */
setViewTranslationCallback(@onNull ViewTranslationCallback callback)33673     public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
33674         mViewTranslationCallback = callback;
33675     }
33676 
33677     /**
33678      * Clear the {@link ViewTranslationCallback} from this view.
33679      */
clearViewTranslationCallback()33680     public void clearViewTranslationCallback() {
33681         mViewTranslationCallback = null;
33682     }
33683 
33684     /**
33685      * Returns the {@link ViewTranslationResponse} associated with this view. The response will be
33686      * set when the translation is done then {@link #onViewTranslationResponse} is called. The
33687      * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the
33688      * translated information.
33689      *
33690      * @return a {@link ViewTranslationResponse} that contains the translated information associated
33691      * with this view or {@code null} if this View doesn't have the translation.
33692      */
33693     @Nullable
getViewTranslationResponse()33694     public ViewTranslationResponse getViewTranslationResponse() {
33695         return mViewTranslationResponse;
33696     }
33697 
33698     /**
33699      * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated
33700      * by the TranslationService. The {@link ViewTranslationResponse} should be saved here so that
33701      * the {@link ViewTranslationResponse} can be used to display the translation when the system
33702      * calls {@link ViewTranslationCallback#onShowTranslation}.
33703      *
33704      * <p> The default implementation will set the ViewTranslationResponse that can be get from
33705      * {@link View#getViewTranslationResponse}. </p>
33706      *
33707      * @param response a {@link ViewTranslationResponse} that contains the translated information
33708      * which can be shown in the view.
33709      */
onViewTranslationResponse(@onNull ViewTranslationResponse response)33710     public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
33711         mViewTranslationResponse = response;
33712     }
33713 
33714     /**
33715      * Clears the ViewTranslationResponse stored by the default implementation of {@link
33716      * #onViewTranslationResponse}.
33717      *
33718      * @hide
33719      */
clearViewTranslationResponse()33720     public void clearViewTranslationResponse() {
33721         mViewTranslationResponse = null;
33722     }
33723 
33724     /**
33725      * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
33726      * translated by the TranslationService.
33727      *
33728      * <p> The default implementation does nothing.</p>
33729      *
33730      * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
33731      * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information
33732      * which can be shown in the view. The key of SparseArray is the virtual child ids.
33733      */
onVirtualViewTranslationResponses( @onNull LongSparseArray<ViewTranslationResponse> response)33734     public void onVirtualViewTranslationResponses(
33735             @NonNull LongSparseArray<ViewTranslationResponse> response) {
33736         // no-op
33737     }
33738 
33739     /**
33740      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
33741      * the hierarchy when the app requests ui translation. Typically, this method should only be
33742      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
33743      * classes should override {@link View#onCreateViewTranslationRequest} for normal view or
33744      * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children.
33745      * When requested to start the ui translation, the system will call this method to traverse the
33746      * view hierarchy to collect {@link ViewTranslationRequest}s and create a
33747      * {@link android.view.translation.Translator} to translate the requests. All the
33748      * {@link ViewTranslationRequest}s must be added when the traversal is done.
33749      *
33750      * <p> The default implementation calls {@link View#onCreateViewTranslationRequest} for normal
33751      * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
33752      * children to build {@link ViewTranslationRequest} if the view should be translated.
33753      * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
33754      * recycling of views doesn't prevent the system from attaching the response to it. Therefore,
33755      * if overriding this method, you should set or reset the transient state. </p>
33756      *
33757      * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
33758      * {@code null} if the view doesn't have virtual child that should be translated. The virtual
33759      * child ids are the same virtual ids provided by ContentCapture.
33760      * @param supportedFormats the supported translation formats. For now, the only possible value
33761      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
33762      * @param capability a {@link TranslationCapability} that holds translation capability.
33763      * information, e.g. source spec, target spec.
33764      * @param requests fill in with {@link ViewTranslationRequest}s for translation purpose.
33765      */
dispatchCreateViewTranslationRequest(@onNull Map<AutofillId, long[]> viewIds, @NonNull @DataFormat int[] supportedFormats, @NonNull TranslationCapability capability, @NonNull List<ViewTranslationRequest> requests)33766     public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
33767             @NonNull @DataFormat int[] supportedFormats,
33768             @NonNull TranslationCapability capability,
33769             @NonNull List<ViewTranslationRequest> requests) {
33770         AutofillId autofillId = getAutofillId();
33771         if (viewIds.containsKey(autofillId)) {
33772             if (viewIds.get(autofillId) == null) {
33773                 // TODO: avoiding the allocation per view
33774                 onCreateViewTranslationRequest(supportedFormats,
33775                         new ViewTranslationRequestConsumer(requests));
33776             } else {
33777                 onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
33778                         request -> {
33779                             requests.add(request);
33780                         });
33781             }
33782         }
33783     }
33784 
33785     private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
33786         private final List<ViewTranslationRequest> mRequests;
33787         private boolean mCalled;
33788 
ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests)33789         ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
33790             mRequests = requests;
33791         }
33792 
33793         @Override
accept(ViewTranslationRequest request)33794         public void accept(ViewTranslationRequest request) {
33795             if (mCalled) {
33796                 throw new IllegalStateException("The translation Consumer is not reusable.");
33797             }
33798             mCalled = true;
33799             if (request != null && request.getKeys().size() > 0) {
33800                 mRequests.add(request);
33801                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
33802                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
33803                             + getAutofillId());
33804                 }
33805                 setHasTransientState(true);
33806                 setHasTranslationTransientState(true);
33807             }
33808         }
33809     }
33810 
33811     /**
33812      * Called to generate a {@link DisplayHash} for this view.
33813      *
33814      * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
33815      *                      the values returned from
33816      *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
33817      * @param bounds The bounds for the content within the View to generate the hash for. If
33818      *               bounds are null, the entire View's bounds will be used. If empty, it will
33819      *               invoke the callback
33820      *               {@link DisplayHashResultCallback#onDisplayHashError} with error
33821      *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
33822      * @param executor The executor that the callback should be invoked on.
33823      * @param callback The callback to handle the results of generating the display hash
33824      */
generateDisplayHash(@onNull String hashAlgorithm, @Nullable Rect bounds, @NonNull Executor executor, @NonNull DisplayHashResultCallback callback)33825     public void generateDisplayHash(@NonNull String hashAlgorithm,
33826             @Nullable Rect bounds, @NonNull Executor executor,
33827             @NonNull DisplayHashResultCallback callback) {
33828         IWindowSession session = getWindowSession();
33829         if (session == null) {
33830             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
33831             return;
33832         }
33833         IWindow window = getWindow();
33834         if (window == null) {
33835             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
33836             return;
33837         }
33838 
33839         Rect visibleBounds = new Rect();
33840         getGlobalVisibleRect(visibleBounds);
33841 
33842         if (bounds != null && bounds.isEmpty()) {
33843             callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
33844             return;
33845         }
33846 
33847         if (bounds != null) {
33848             bounds.offset(visibleBounds.left, visibleBounds.top);
33849             visibleBounds.intersectUnchecked(bounds);
33850         }
33851 
33852         if (visibleBounds.isEmpty()) {
33853             callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
33854             return;
33855         }
33856 
33857         RemoteCallback remoteCallback = new RemoteCallback(result ->
33858                 executor.execute(() -> {
33859                     DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH, android.view.displayhash.DisplayHash.class);
33860                     int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
33861                             DISPLAY_HASH_ERROR_UNKNOWN);
33862                     if (displayHash != null) {
33863                         callback.onDisplayHashResult(displayHash);
33864                     } else {
33865                         callback.onDisplayHashError(errorCode);
33866                     }
33867                 }));
33868 
33869         try {
33870             session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
33871         } catch (RemoteException e) {
33872             Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
33873             callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
33874         }
33875     }
33876 
33877     /**
33878      * The AttachedSurfaceControl itself is not a View, it is just the interface to the
33879      * windowing-system object that contains the entire view hierarchy.
33880      * For the root View of a given hierarchy see {@link #getRootView}.
33881 
33882      * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
33883      * This will only return a non-null value when called between {@link #onAttachedToWindow}
33884      * and {@link #onDetachedFromWindow}.
33885      */
getRootSurfaceControl()33886     public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
33887         if (mAttachInfo != null) {
33888           return mAttachInfo.getRootSurfaceControl();
33889         }
33890         return null;
33891     }
33892 
33893     /**
33894      * Used to calculate the frame rate category of a View.
33895      *
33896      * @hide
33897      */
calculateFrameRateCategory()33898     protected int calculateFrameRateCategory() {
33899         int category;
33900         switch (getViewRootImpl().intermittentUpdateState()) {
33901             case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT -> category =
33902                     FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
33903             case ViewRootImpl.INTERMITTENT_STATE_NOT_INTERMITTENT ->
33904                     category = mSizeBasedFrameRateCategoryAndReason;
33905             default -> category = mLastFrameRateCategory;
33906         }
33907         return category;
33908     }
33909 
33910     /**
33911      * Used to vote the preferred frame rate and frame rate category to ViewRootImpl
33912      *
33913      * @hide
33914      */
votePreferredFrameRate()33915     protected void votePreferredFrameRate() {
33916         // use toolkitSetFrameRate flag to gate the change
33917         ViewRootImpl viewRootImpl = getViewRootImpl();
33918         if (viewRootImpl == null) {
33919             return; // can't vote if not connected
33920         }
33921         float velocity = mFrameContentVelocity;
33922         final float frameRate = mPreferredFrameRate;
33923         ViewParent parent = mParent;
33924         if (velocity <= 0 && Float.isNaN(frameRate)) {
33925             // The most common case is when nothing is set, so this special case is called
33926             // often.
33927             if (mAttachInfo.mViewVelocityApi
33928                     && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
33929                     PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
33930                     || mLastFrameTop != mTop)
33931                     && viewRootImpl.shouldCheckFrameRate(false)
33932                     && parent instanceof View
33933                     && ((View) parent).mFrameContentVelocity <= 0) {
33934                 viewRootImpl.votePreferredFrameRate(MAX_FRAME_RATE, FRAME_RATE_COMPATIBILITY_GTE);
33935             }
33936             if (viewRootImpl.shouldCheckFrameRateCategory()) {
33937                 int frameRateCategory = calculateFrameRateCategory();
33938                 int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
33939                 int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
33940                 viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
33941                 mLastFrameRateCategory = frameRateCategory;
33942             }
33943             mLastFrameLeft = mLeft;
33944             mLastFrameTop = mTop;
33945             return;
33946         }
33947         if (viewRootImpl.shouldCheckFrameRate(frameRate > 0f)) {
33948             float velocityFrameRate = 0f;
33949             if (mAttachInfo.mViewVelocityApi) {
33950                 if (velocity < 0f
33951                         && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
33952                         PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
33953                         || mLastFrameTop != mTop)
33954                         && mParent instanceof View
33955                         && ((View) mParent).mFrameContentVelocity <= 0
33956                 ) {
33957                     // This current calculation is very simple. If something on the screen
33958                     // moved, then it votes for the highest velocity.
33959                     velocityFrameRate = MAX_FRAME_RATE;
33960                 } else if (velocity > 0f) {
33961                     velocityFrameRate = convertVelocityToFrameRate(velocity);
33962                 }
33963             }
33964             if (velocityFrameRate > 0f || frameRate > 0f) {
33965                 int compatibility;
33966                 float frameRateToSet;
33967                 if (frameRate >= velocityFrameRate) {
33968                     compatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
33969                     frameRateToSet = frameRate;
33970                 } else {
33971                     compatibility = FRAME_RATE_COMPATIBILITY_GTE;
33972                     frameRateToSet = velocityFrameRate;
33973                 }
33974                 viewRootImpl.votePreferredFrameRate(frameRateToSet, compatibility);
33975             }
33976         }
33977 
33978         if (viewRootImpl.shouldCheckFrameRateCategory()) {
33979             if (sToolkitMetricsForFrameRateDecisionFlagValue) {
33980                 int width = mRight - mLeft;
33981                 int height = mBottom - mTop;
33982                 float sizePercentage = width * height / mAttachInfo.mDisplayPixelCount;
33983                 viewRootImpl.recordViewPercentage(sizePercentage);
33984             }
33985 
33986             int frameRateCategory;
33987             if (Float.isNaN(frameRate)) {
33988                 frameRateCategory = calculateFrameRateCategory();
33989             } else if (frameRate < 0) {
33990                 switch ((int) frameRate) {
33991                     case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->
33992                             frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
33993                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
33994                     case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->
33995                             frameRateCategory = FRAME_RATE_CATEGORY_LOW
33996                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
33997                     case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->
33998                             frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
33999                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34000                     case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->
34001                             frameRateCategory = FRAME_RATE_CATEGORY_HIGH
34002                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34003                     default -> {
34004                         // invalid frame rate, use default
34005                         int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
34006                                 ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
34007                         frameRateCategory = category
34008                                 | FRAME_RATE_CATEGORY_REASON_INVALID;
34009                     }
34010                 }
34011             } else {
34012                 // Category doesn't control it. It is directly controlled by frame rate
34013                 frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
34014                         | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34015             }
34016 
34017             int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
34018             int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
34019             viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
34020             mLastFrameRateCategory = frameRateCategory;
34021         }
34022         mLastFrameLeft = mLeft;
34023         mLastFrameTop = mTop;
34024     }
34025 
convertVelocityToFrameRate(float velocityPps)34026     private float convertVelocityToFrameRate(float velocityPps) {
34027         // From UXR study, premium experience is:
34028         // 1500+    dp/s: 120fps
34029         // 0 - 1500 dp/s:  80fps
34030         // OEMs are likely to modify this to balance battery and user experience for their
34031         // specific device.
34032         float density = mAttachInfo.mDensity;
34033         float velocityDps = velocityPps / density;
34034         return (velocityDps >= 1500f) ? MAX_FRAME_RATE : 80f;
34035     }
34036 
34037     /**
34038      * Set the current velocity of the View, we only track positive value.
34039      * We will use the velocity information to adjust the frame rate when applicable.
34040      * For example, we could potentially lower the frame rate when
34041      * the velocity of a fling gesture becomes slower.
34042      * Note that this is only valid till the next drawn frame.
34043      *
34044      * @param pixelsPerSecond how many pixels move per second.
34045      */
34046     @FlaggedApi(FLAG_VIEW_VELOCITY_API)
setFrameContentVelocity(float pixelsPerSecond)34047     public void setFrameContentVelocity(float pixelsPerSecond) {
34048         if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
34049             mFrameContentVelocity = Math.abs(pixelsPerSecond);
34050 
34051             if (sToolkitMetricsForFrameRateDecisionFlagValue) {
34052                 Trace.setCounter("Set frame velocity", (long) mFrameContentVelocity);
34053             }
34054         }
34055     }
34056 
34057     /**
34058      * Get the current velocity of the View.
34059      * The value should always be greater than or equal to 0.
34060      * Note that this is only valid till the next drawn frame.
34061      *
34062      * @return 0 by default, or value passed to {@link #setFrameContentVelocity(float)}.
34063      */
34064     @FlaggedApi(FLAG_VIEW_VELOCITY_API)
getFrameContentVelocity()34065     public float getFrameContentVelocity() {
34066         if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
34067             return Math.max(mFrameContentVelocity, 0f);
34068         }
34069         return 0;
34070     }
34071 
34072     /**
34073      * You can set the preferred frame rate for a View using a positive number
34074      * or by specifying the preferred frame rate category using constants, including
34075      * REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE, REQUESTED_FRAME_RATE_CATEGORY_LOW,
34076      * REQUESTED_FRAME_RATE_CATEGORY_NORMAL, REQUESTED_FRAME_RATE_CATEGORY_HIGH.
34077      * Keep in mind that the preferred frame rate affects the frame rate for the next frame,
34078      * so use this method carefully. It's important to note that the preference is valid as
34079      * long as the View is invalidated.
34080      *
34081      * @param frameRate the preferred frame rate of the view.
34082      */
34083     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
setRequestedFrameRate(float frameRate)34084     public void setRequestedFrameRate(float frameRate) {
34085         if (sToolkitSetFrameRateReadOnlyFlagValue) {
34086             mPreferredFrameRate = frameRate;
34087         }
34088     }
34089 
34090     /**
34091      * Get the current preferred frame rate of the View.
34092      * The value could be negative when preferred frame rate category is set
34093      * instead of perferred frame rate.
34094      * The frame rate category includes
34095      * REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE, REQUESTED_FRAME_RATE_CATEGORY_LOW,
34096      * REQUESTED_FRAME_RATE_CATEGORY_NORMAL, and REQUESTED_FRAME_RATE_CATEGORY_HIGH.
34097      * Note that the frame rate value is valid as long as the View is invalidated.
34098      *
34099      * @return REQUESTED_FRAME_RATE_CATEGORY_DEFAULT by default,
34100      * or value passed to {@link #setRequestedFrameRate(float)}.
34101      */
34102     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
getRequestedFrameRate()34103     public float getRequestedFrameRate() {
34104         if (sToolkitSetFrameRateReadOnlyFlagValue) {
34105             return mPreferredFrameRate;
34106         }
34107         return 0;
34108     }
34109 }
34110