• 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_HIGH_HINT;
26 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
27 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
28 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
29 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
30 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST;
31 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
32 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
33 import static android.view.accessibility.Flags.FLAG_DEPRECATE_ACCESSIBILITY_ANNOUNCEMENT_APIS;
34 import static android.view.accessibility.Flags.FLAG_SUPPLEMENTAL_DESCRIPTION;
35 import static android.view.accessibility.Flags.removeChildHoverCheckForTouchExploration;
36 import static android.view.accessibility.Flags.supplementalDescription;
37 import static android.view.accessibility.Flags.supportMultipleLabeledby;
38 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
39 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
40 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
41 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
42 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH;
43 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
44 import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API;
45 import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
46 import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
47 import static android.view.flags.Flags.calculateBoundsInParentFromBoundsInScreen;
48 import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout;
49 import static android.view.flags.Flags.sensitiveContentAppProtection;
50 import static android.view.flags.Flags.toolkitFrameRateAnimationBugfix25q1;
51 import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
52 import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
53 import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
54 import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
55 import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
56 import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
57 import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
58 import static android.view.flags.Flags.toolkitViewgroupSetRequestedFrameRateApi;
59 import static android.view.flags.Flags.viewVelocityApi;
60 import static android.view.inputmethod.Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR;
61 import static android.view.inputmethod.Flags.initiationWithoutInputConnection;
62 
63 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
64 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
65 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
66 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
67 import static com.android.window.flags.Flags.FLAG_DELEGATE_UNHANDLED_DRAGS;
68 import static com.android.window.flags.Flags.FLAG_SUPPORTS_DRAG_ASSISTANT_TO_MULTIWINDOW;
69 import static com.android.window.flags.Flags.reduceChangedExclusionRectsMsgs;
70 
71 import static java.lang.Math.max;
72 
73 import android.animation.AnimatorInflater;
74 import android.animation.StateListAnimator;
75 import android.annotation.AttrRes;
76 import android.annotation.CallSuper;
77 import android.annotation.ColorInt;
78 import android.annotation.DrawableRes;
79 import android.annotation.FlaggedApi;
80 import android.annotation.FloatRange;
81 import android.annotation.IdRes;
82 import android.annotation.IntDef;
83 import android.annotation.IntRange;
84 import android.annotation.LayoutRes;
85 import android.annotation.NonNull;
86 import android.annotation.Nullable;
87 import android.annotation.RequiresPermission;
88 import android.annotation.Size;
89 import android.annotation.StyleRes;
90 import android.annotation.SuppressLint;
91 import android.annotation.SystemApi;
92 import android.annotation.TestApi;
93 import android.annotation.UiContext;
94 import android.annotation.UiThread;
95 import android.app.PendingIntent;
96 import android.app.jank.AppJankStats;
97 import android.app.jank.JankTracker;
98 import android.compat.annotation.UnsupportedAppUsage;
99 import android.content.AutofillOptions;
100 import android.content.ClipData;
101 import android.content.ClipDescription;
102 import android.content.Context;
103 import android.content.ContextWrapper;
104 import android.content.Intent;
105 import android.content.IntentSender;
106 import android.content.res.ColorStateList;
107 import android.content.res.CompatibilityInfo;
108 import android.content.res.Configuration;
109 import android.content.res.Resources;
110 import android.content.res.TypedArray;
111 import android.credentials.CredentialManager;
112 import android.credentials.CredentialOption;
113 import android.credentials.GetCredentialException;
114 import android.credentials.GetCredentialRequest;
115 import android.credentials.GetCredentialResponse;
116 import android.graphics.Bitmap;
117 import android.graphics.BlendMode;
118 import android.graphics.Canvas;
119 import android.graphics.Color;
120 import android.graphics.Insets;
121 import android.graphics.Interpolator;
122 import android.graphics.LinearGradient;
123 import android.graphics.Matrix;
124 import android.graphics.Outline;
125 import android.graphics.Paint;
126 import android.graphics.PixelFormat;
127 import android.graphics.Point;
128 import android.graphics.PorterDuff;
129 import android.graphics.PorterDuffXfermode;
130 import android.graphics.RecordingCanvas;
131 import android.graphics.Rect;
132 import android.graphics.RectF;
133 import android.graphics.Region;
134 import android.graphics.RenderEffect;
135 import android.graphics.RenderNode;
136 import android.graphics.Shader;
137 import android.graphics.drawable.ColorDrawable;
138 import android.graphics.drawable.Drawable;
139 import android.graphics.drawable.GradientDrawable;
140 import android.hardware.display.DisplayManagerGlobal;
141 import android.hardware.input.InputManager;
142 import android.net.Uri;
143 import android.os.Build;
144 import android.os.Bundle;
145 import android.os.Handler;
146 import android.os.IBinder;
147 import android.os.Message;
148 import android.os.OutcomeReceiver;
149 import android.os.Parcel;
150 import android.os.Parcelable;
151 import android.os.RemoteCallback;
152 import android.os.RemoteException;
153 import android.os.SystemClock;
154 import android.os.Trace;
155 import android.service.credentials.CredentialProviderService;
156 import android.sysprop.DisplayProperties;
157 import android.text.InputType;
158 import android.text.TextUtils;
159 import android.util.ArraySet;
160 import android.util.AttributeSet;
161 import android.util.DisplayMetrics;
162 import android.util.FloatProperty;
163 import android.util.LayoutDirection;
164 import android.util.Log;
165 import android.util.LongSparseArray;
166 import android.util.LongSparseLongArray;
167 import android.util.Pair;
168 import android.util.Pools.SynchronizedPool;
169 import android.util.Property;
170 import android.util.SparseArray;
171 import android.util.SparseIntArray;
172 import android.util.StateSet;
173 import android.util.SuperNotCalledException;
174 import android.util.TimeUtils;
175 import android.util.TypedValue;
176 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
177 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
178 import android.view.AccessibilityIterators.TextSegmentIterator;
179 import android.view.AccessibilityIterators.WordTextSegmentIterator;
180 import android.view.ContextMenu.ContextMenuInfo;
181 import android.view.InputDevice.InputSourceClass;
182 import android.view.Window.OnContentApplyWindowInsetsListener;
183 import android.view.WindowInsets.Type;
184 import android.view.WindowInsetsAnimation.Bounds;
185 import android.view.WindowManager.LayoutParams;
186 import android.view.accessibility.AccessibilityEvent;
187 import android.view.accessibility.AccessibilityEventSource;
188 import android.view.accessibility.AccessibilityManager;
189 import android.view.accessibility.AccessibilityNodeIdManager;
190 import android.view.accessibility.AccessibilityNodeInfo;
191 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
192 import android.view.accessibility.AccessibilityNodeProvider;
193 import android.view.accessibility.AccessibilityWindowInfo;
194 import android.view.animation.Animation;
195 import android.view.animation.AnimationUtils;
196 import android.view.animation.Transformation;
197 import android.view.autofill.AutofillId;
198 import android.view.autofill.AutofillManager;
199 import android.view.autofill.AutofillValue;
200 import android.view.contentcapture.ContentCaptureContext;
201 import android.view.contentcapture.ContentCaptureManager;
202 import android.view.contentcapture.ContentCaptureSession;
203 import android.view.displayhash.DisplayHash;
204 import android.view.displayhash.DisplayHashManager;
205 import android.view.displayhash.DisplayHashResultCallback;
206 import android.view.inputmethod.EditorInfo;
207 import android.view.inputmethod.InputConnection;
208 import android.view.inputmethod.InputMethodManager;
209 import android.view.inspector.InspectableProperty;
210 import android.view.inspector.InspectableProperty.EnumEntry;
211 import android.view.inspector.InspectableProperty.FlagEntry;
212 import android.view.translation.TranslationCapability;
213 import android.view.translation.TranslationSpec.DataFormat;
214 import android.view.translation.ViewTranslationCallback;
215 import android.view.translation.ViewTranslationRequest;
216 import android.view.translation.ViewTranslationResponse;
217 import android.widget.Checkable;
218 import android.widget.ScrollBarDrawable;
219 import android.window.OnBackInvokedDispatcher;
220 
221 import com.android.internal.R;
222 import com.android.internal.util.ArrayUtils;
223 import com.android.internal.util.FrameworkStatsLog;
224 import com.android.internal.util.Preconditions;
225 import com.android.internal.view.ScrollCaptureInternal;
226 import com.android.internal.view.TooltipPopup;
227 import com.android.internal.view.menu.MenuBuilder;
228 import com.android.internal.widget.ScrollBarUtils;
229 
230 import com.google.android.collect.Lists;
231 import com.google.android.collect.Maps;
232 
233 import java.io.PrintWriter;
234 import java.lang.annotation.Retention;
235 import java.lang.annotation.RetentionPolicy;
236 import java.lang.ref.WeakReference;
237 import java.lang.reflect.Field;
238 import java.lang.reflect.InvocationTargetException;
239 import java.lang.reflect.Method;
240 import java.lang.reflect.Modifier;
241 import java.time.Duration;
242 import java.util.ArrayList;
243 import java.util.Arrays;
244 import java.util.Calendar;
245 import java.util.Collection;
246 import java.util.Collections;
247 import java.util.HashMap;
248 import java.util.List;
249 import java.util.Locale;
250 import java.util.Map;
251 import java.util.Objects;
252 import java.util.concurrent.CopyOnWriteArrayList;
253 import java.util.concurrent.Executor;
254 import java.util.concurrent.atomic.AtomicInteger;
255 import java.util.function.Consumer;
256 import java.util.function.Predicate;
257 
258 /**
259  * <p>
260  * This class represents the basic building block for user interface components. A View
261  * occupies a rectangular area on the screen and is responsible for drawing and
262  * event handling. View is the base class for <em>widgets</em>, which are
263  * used to create interactive UI components (buttons, text fields, etc.). The
264  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
265  * are invisible containers that hold other Views (or other ViewGroups) and define
266  * their layout properties.
267  * </p>
268  *
269  * <div class="special reference">
270  * <h3>Developer Guides</h3>
271  * <p>For information about using this class to develop your application's user interface,
272  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
273  * </div>
274  *
275  * <a name="Using"></a>
276  * <h3>Using Views</h3>
277  * <p>
278  * All of the views in a window are arranged in a single tree. You can add views
279  * either from code or by specifying a tree of views in one or more XML layout
280  * files. There are many specialized subclasses of views that act as controls or
281  * are capable of displaying text, images, or other content.
282  * </p>
283  * <p>
284  * Once you have created a tree of views, there are typically a few types of
285  * common operations you may wish to perform:
286  * <ul>
287  * <li><strong>Set properties:</strong> for example setting the text of a
288  * {@link android.widget.TextView}. The available properties and the methods
289  * that set them will vary among the different subclasses of views. Note that
290  * properties that are known at build time can be set in the XML layout
291  * files.</li>
292  * <li><strong>Set focus:</strong> The framework will handle moving focus in
293  * response to user input. To force focus to a specific view, call
294  * {@link #requestFocus}.</li>
295  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
296  * that will be notified when something interesting happens to the view. For
297  * example, all views will let you set a listener to be notified when the view
298  * gains or loses focus. You can register such a listener using
299  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
300  * Other view subclasses offer more specialized listeners. For example, a Button
301  * exposes a listener to notify clients when the button is clicked.</li>
302  * <li><strong>Set visibility:</strong> You can hide or show views using
303  * {@link #setVisibility(int)}.</li>
304  * </ul>
305  * </p>
306  * <p><em>
307  * Note: The Android framework is responsible for measuring, laying out and
308  * drawing views. You should not call methods that perform these actions on
309  * views yourself unless you are actually implementing a
310  * {@link android.view.ViewGroup}.
311  * </em></p>
312  *
313  * <a name="Lifecycle"></a>
314  * <h3>Implementing a Custom View</h3>
315  *
316  * <p>
317  * To implement a custom view, you will usually begin by providing overrides for
318  * some of the standard methods that the framework calls on all views. You do
319  * not need to override all of these methods. In fact, you can start by just
320  * overriding {@link #onDraw(android.graphics.Canvas)}.
321  * <table border="2" width="85%" align="center" cellpadding="5">
322  *     <thead>
323  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
324  *     </thead>
325  *
326  *     <tbody>
327  *     <tr>
328  *         <td rowspan="2">Creation</td>
329  *         <td>Constructors</td>
330  *         <td>There is a form of the constructor that are called when the view
331  *         is created from code and a form that is called when the view is
332  *         inflated from a layout file. The second form should parse and apply
333  *         any attributes defined in the layout file.
334  *         </td>
335  *     </tr>
336  *     <tr>
337  *         <td><code>{@link #onFinishInflate()}</code></td>
338  *         <td>Called after a view and all of its children has been inflated
339  *         from XML.</td>
340  *     </tr>
341  *
342  *     <tr>
343  *         <td rowspan="3">Layout</td>
344  *         <td><code>{@link #onMeasure(int, int)}</code></td>
345  *         <td>Called to determine the size requirements for this view and all
346  *         of its children.
347  *         </td>
348  *     </tr>
349  *     <tr>
350  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
351  *         <td>Called when this view should assign a size and position to all
352  *         of its children.
353  *         </td>
354  *     </tr>
355  *     <tr>
356  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
357  *         <td>Called when the size of this view has changed.
358  *         </td>
359  *     </tr>
360  *
361  *     <tr>
362  *         <td>Drawing</td>
363  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
364  *         <td>Called when the view should render its content.
365  *         </td>
366  *     </tr>
367  *
368  *     <tr>
369  *         <td rowspan="6">Event processing</td>
370  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
371  *         <td>Called when a new hardware key event occurs.
372  *         </td>
373  *     </tr>
374  *     <tr>
375  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
376  *         <td>Called when a hardware key up event occurs.
377  *         </td>
378  *     </tr>
379  *     <tr>
380  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
381  *         <td>Called when a trackball motion event occurs.
382  *         </td>
383  *     </tr>
384  *     <tr>
385  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
386  *         <td>Called when a motion event occurs with pointers down on the view.
387  *         </td>
388  *     </tr>
389  *     <tr>
390  *         <td><code>{@link #onGenericMotionEvent(MotionEvent)}</code></td>
391  *         <td>Called when a generic motion event occurs.
392  *         </td>
393  *     </tr>
394  *     <tr>
395  *         <td><code>{@link #onHoverEvent(MotionEvent)}</code></td>
396  *         <td>Called when a hover motion event occurs.
397  *         </td>
398  *     </tr>
399  *
400  *     <tr>
401  *         <td rowspan="2">Focus</td>
402  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
403  *         <td>Called when the view gains or loses focus.
404  *         </td>
405  *     </tr>
406  *
407  *     <tr>
408  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
409  *         <td>Called when the window containing the view gains or loses focus.
410  *         </td>
411  *     </tr>
412  *
413  *     <tr>
414  *         <td rowspan="3">Attaching</td>
415  *         <td><code>{@link #onAttachedToWindow()}</code></td>
416  *         <td>Called when the view is attached to a window.
417  *         </td>
418  *     </tr>
419  *
420  *     <tr>
421  *         <td><code>{@link #onDetachedFromWindow}</code></td>
422  *         <td>Called when the view is detached from its window.
423  *         </td>
424  *     </tr>
425  *
426  *     <tr>
427  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
428  *         <td>Called when the visibility of the window containing the view
429  *         has changed.
430  *         </td>
431  *     </tr>
432  *     </tbody>
433  *
434  * </table>
435  * </p>
436  *
437  * <a name="IDs"></a>
438  * <h3>IDs</h3>
439  * Views may have an integer id associated with them. These ids are typically
440  * assigned in the layout XML files, and are used to find specific views within
441  * the view tree. A common pattern is to:
442  * <ul>
443  * <li>Define a Button in the layout file and assign it a unique ID.
444  * <pre>
445  * &lt;Button
446  *     android:id="@+id/my_button"
447  *     android:layout_width="wrap_content"
448  *     android:layout_height="wrap_content"
449  *     android:text="@string/my_button_text"/&gt;
450  * </pre></li>
451  * <li>From the onCreate method of an Activity, find the Button
452  * <pre class="prettyprint">
453  *      Button myButton = findViewById(R.id.my_button);
454  * </pre></li>
455  * </ul>
456  * <p>
457  * View IDs need not be unique throughout the tree, but it is good practice to
458  * ensure that they are at least unique within the part of the tree you are
459  * searching.
460  * </p>
461  *
462  * <a name="Position"></a>
463  * <h3>Position</h3>
464  * <p>
465  * The geometry of a view is that of a rectangle. A view has a location,
466  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
467  * two dimensions, expressed as a width and a height. The unit for location
468  * and dimensions is the pixel.
469  * </p>
470  *
471  * <p>
472  * It is possible to retrieve the location of a view by invoking the methods
473  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
474  * coordinate of the rectangle representing the view. The latter returns the
475  * top, or Y, coordinate of the rectangle representing the view. These methods
476  * both return the location of the view relative to its parent. For instance,
477  * when getLeft() returns 20, that means the view is located 20 pixels to the
478  * right of the left edge of its direct parent.
479  * </p>
480  *
481  * <p>
482  * In addition, several convenience methods are offered to avoid unnecessary
483  * computations, namely {@link #getRight()} and {@link #getBottom()}.
484  * These methods return the coordinates of the right and bottom edges of the
485  * rectangle representing the view. For instance, calling {@link #getRight()}
486  * is similar to the following computation: <code>getLeft() + getWidth()</code>
487  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
488  * </p>
489  *
490  * <a name="SizePaddingMargins"></a>
491  * <h3>Size, padding and margins</h3>
492  * <p>
493  * The size of a view is expressed with a width and a height. A view actually
494  * possess two pairs of width and height values.
495  * </p>
496  *
497  * <p>
498  * The first pair is known as <em>measured width</em> and
499  * <em>measured height</em>. These dimensions define how big a view wants to be
500  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
501  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
502  * and {@link #getMeasuredHeight()}.
503  * </p>
504  *
505  * <p>
506  * The second pair is simply known as <em>width</em> and <em>height</em>, or
507  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
508  * dimensions define the actual size of the view on screen, at drawing time and
509  * after layout. These values may, but do not have to, be different from the
510  * measured width and height. The width and height can be obtained by calling
511  * {@link #getWidth()} and {@link #getHeight()}.
512  * </p>
513  *
514  * <p>
515  * To measure its dimensions, a view takes into account its padding. The padding
516  * is expressed in pixels for the left, top, right and bottom parts of the view.
517  * Padding can be used to offset the content of the view by a specific amount of
518  * pixels. For instance, a left padding of 2 will push the view's content by
519  * 2 pixels to the right of the left edge. Padding can be set using the
520  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
521  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
522  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
523  * {@link #getPaddingEnd()}.
524  * </p>
525  *
526  * <p>
527  * Even though a view can define a padding, it does not provide any support for
528  * margins. However, view groups provide such a support. Refer to
529  * {@link android.view.ViewGroup} and
530  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
531  * </p>
532  *
533  * <a name="Layout"></a>
534  * <h3>Layout</h3>
535  * <p>
536  * Layout is a two pass process: a measure pass and a layout pass. The measuring
537  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
538  * of the view tree. Each view pushes dimension specifications down the tree
539  * during the recursion. At the end of the measure pass, every view has stored
540  * its measurements. The second pass happens in
541  * {@link #layout(int,int,int,int)} and is also top-down. During
542  * this pass each parent is responsible for positioning all of its children
543  * using the sizes computed in the measure pass.
544  * </p>
545  *
546  * <p>
547  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
548  * {@link #getMeasuredHeight()} values must be set, along with those for all of
549  * that view's descendants. A view's measured width and measured height values
550  * must respect the constraints imposed by the view's parents. This guarantees
551  * that at the end of the measure pass, all parents accept all of their
552  * children's measurements. A parent view may call measure() more than once on
553  * its children. For example, the parent may measure each child once with
554  * unspecified dimensions to find out how big they want to be, then call
555  * measure() on them again with actual numbers if the sum of all the children's
556  * unconstrained sizes is too big or too small.
557  * </p>
558  *
559  * <p>
560  * The measure pass uses two classes to communicate dimensions. The
561  * {@link MeasureSpec} class is used by views to tell their parents how they
562  * want to be measured and positioned. The base LayoutParams class just
563  * describes how big the view wants to be for both width and height. For each
564  * dimension, it can specify one of:
565  * <ul>
566  * <li> an exact number
567  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
568  * (minus padding)
569  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
570  * enclose its content (plus padding).
571  * </ul>
572  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
573  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
574  * an X and Y value.
575  * </p>
576  *
577  * <p>
578  * MeasureSpecs are used to push requirements down the tree from parent to
579  * child. A MeasureSpec can be in one of three modes:
580  * <ul>
581  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
582  * of a child view. For example, a LinearLayout may call measure() on its child
583  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
584  * tall the child view wants to be given a width of 240 pixels.
585  * <li>EXACTLY: This is used by the parent to impose an exact size on the
586  * child. The child must use this size, and guarantee that all of its
587  * descendants will fit within this size.
588  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
589  * child. The child must guarantee that it and all of its descendants will fit
590  * within this size.
591  * </ul>
592  * </p>
593  *
594  * <p>
595  * To initiate a layout, call {@link #requestLayout}. This method is typically
596  * called by a view on itself when it believes that it can no longer fit within
597  * its current bounds.
598  * </p>
599  *
600  * <a name="Drawing"></a>
601  * <h3>Drawing</h3>
602  * <p>
603  * Drawing is handled by walking the tree and recording the drawing commands of
604  * any View that needs to update. After this, the drawing commands of the
605  * entire tree are issued to screen, clipped to the newly damaged area.
606  * </p>
607  *
608  * <p>
609  * The tree is largely recorded and drawn in order, with parents drawn before
610  * (i.e., behind) their children, with siblings drawn in the order they appear
611  * in the tree. If you set a background drawable for a View, then the View will
612  * draw it before calling back to its <code>onDraw()</code> method. The child
613  * drawing order can be overridden with
614  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
615  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
616  * </p>
617  *
618  * <p>
619  * To force a view to draw, call {@link #invalidate()}.
620  * </p>
621  *
622  * <a name="EventHandlingThreading"></a>
623  * <h3>Event Handling and Threading</h3>
624  * <p>
625  * The basic cycle of a view is as follows:
626  * <ol>
627  * <li>An event comes in and is dispatched to the appropriate view. The view
628  * handles the event and notifies any listeners.</li>
629  * <li>If in the course of processing the event, the view's bounds may need
630  * to be changed, the view will call {@link #requestLayout()}.</li>
631  * <li>Similarly, if in the course of processing the event the view's appearance
632  * may need to be changed, the view will call {@link #invalidate()}.</li>
633  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
634  * the framework will take care of measuring, laying out, and drawing the tree
635  * as appropriate.</li>
636  * </ol>
637  * </p>
638  *
639  * <p><em>Note: The entire view tree is single threaded. You must always be on
640  * the UI thread when calling any method on any view.</em>
641  * If you are doing work on other threads and want to update the state of a view
642  * from that thread, you should use a {@link Handler}.
643  * </p>
644  *
645  * <a name="FocusHandling"></a>
646  * <h3>Focus Handling</h3>
647  * <p>
648  * The framework will handle routine focus movement in response to user input.
649  * This includes changing the focus as views are removed or hidden, or as new
650  * views become available. Views indicate their willingness to take focus
651  * through the {@link #isFocusable} method. To change whether a view can take
652  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
653  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
654  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
655  * </p>
656  * <p>
657  * Focus movement is based on an algorithm which finds the nearest neighbor in a
658  * given direction. In rare cases, the default algorithm may not match the
659  * intended behavior of the developer. In these situations, you can provide
660  * explicit overrides by using these XML attributes in the layout file:
661  * <pre>
662  * nextFocusDown
663  * nextFocusLeft
664  * nextFocusRight
665  * nextFocusUp
666  * </pre>
667  * </p>
668  *
669  *
670  * <p>
671  * To get a particular view to take focus, call {@link #requestFocus()}.
672  * </p>
673  *
674  * <a name="TouchMode"></a>
675  * <h3>Touch Mode</h3>
676  * <p>
677  * When a user is navigating a user interface via directional keys such as a D-pad, it is
678  * necessary to give focus to actionable items such as buttons so the user can see
679  * what will take input.  If the device has touch capabilities, however, and the user
680  * begins interacting with the interface by touching it, it is no longer necessary to
681  * always highlight, or give focus to, a particular view.  This motivates a mode
682  * for interaction named 'touch mode'.
683  * </p>
684  * <p>
685  * For a touch capable device, once the user touches the screen, the device
686  * will enter touch mode.  From this point onward, only views for which
687  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
688  * Other views that are touchable, like buttons, will not take focus when touched; they will
689  * only fire the on click listeners.
690  * </p>
691  * <p>
692  * Any time a user hits a directional key, such as a D-pad direction, the view device will
693  * exit touch mode, and find a view to take focus, so that the user may resume interacting
694  * with the user interface without touching the screen again.
695  * </p>
696  * <p>
697  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
698  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
699  * </p>
700  *
701  * <a name="Scrolling"></a>
702  * <h3>Scrolling</h3>
703  * <p>
704  * The framework provides basic support for views that wish to internally
705  * scroll their content. This includes keeping track of the X and Y scroll
706  * offset as well as mechanisms for drawing scrollbars. See
707  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
708  * {@link #awakenScrollBars()} for more details.
709  * </p>
710  *
711  * <a name="Tags"></a>
712  * <h3>Tags</h3>
713  * <p>
714  * Unlike IDs, tags are not used to identify views. Tags are essentially an
715  * extra piece of information that can be associated with a view. They are most
716  * often used as a convenience to store data related to views in the views
717  * themselves rather than by putting them in a separate structure.
718  * </p>
719  * <p>
720  * Tags may be specified with character sequence values in layout XML as either
721  * a single tag using the {@link android.R.styleable#View_tag android:tag}
722  * attribute or multiple tags using the {@code <tag>} child element:
723  * <pre>
724  *     &lt;View ...
725  *           android:tag="@string/mytag_value" /&gt;
726  *     &lt;View ...&gt;
727  *         &lt;tag android:id="@+id/mytag"
728  *              android:value="@string/mytag_value" /&gt;
729  *     &lt;/View>
730  * </pre>
731  * </p>
732  * <p>
733  * Tags may also be specified with arbitrary objects from code using
734  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
735  * </p>
736  *
737  * <a name="Themes"></a>
738  * <h3>Themes</h3>
739  * <p>
740  * By default, Views are created using the theme of the Context object supplied
741  * to their constructor; however, a different theme may be specified by using
742  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
743  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
744  * code.
745  * </p>
746  * <p>
747  * When the {@link android.R.styleable#View_theme android:theme} attribute is
748  * used in XML, the specified theme is applied on top of the inflation
749  * context's theme (see {@link LayoutInflater}) and used for the view itself as
750  * well as any child elements.
751  * </p>
752  * <p>
753  * In the following example, both views will be created using the Material dark
754  * color scheme; however, because an overlay theme is used which only defines a
755  * subset of attributes, the value of
756  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
757  * the inflation context's theme (e.g. the Activity theme) will be preserved.
758  * <pre>
759  *     &lt;LinearLayout
760  *             ...
761  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
762  *         &lt;View ...&gt;
763  *     &lt;/LinearLayout&gt;
764  * </pre>
765  * </p>
766  *
767  * <a name="Properties"></a>
768  * <h3>Properties</h3>
769  * <p>
770  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
771  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
772  * available both in the {@link Property} form as well as in similarly-named setter/getter
773  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
774  * be used to set persistent state associated with these rendering-related properties on the view.
775  * The properties and methods can also be used in conjunction with
776  * {@link android.animation.Animator Animator}-based animations, described more in the
777  * <a href="#Animation">Animation</a> section.
778  * </p>
779  *
780  * <a name="Animation"></a>
781  * <h3>Animation</h3>
782  * <p>
783  * Starting with Android 3.0, the preferred way of animating views is to use the
784  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
785  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
786  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
787  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
788  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
789  * makes animating these View properties particularly easy and efficient.
790  * </p>
791  * <p>
792  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
793  * You can attach an {@link Animation} object to a view using
794  * {@link #setAnimation(Animation)} or
795  * {@link #startAnimation(Animation)}. The animation can alter the scale,
796  * rotation, translation and alpha of a view over time. If the animation is
797  * attached to a view that has children, the animation will affect the entire
798  * subtree rooted by that node. When an animation is started, the framework will
799  * take care of redrawing the appropriate views until the animation completes.
800  * </p>
801  *
802  * <a name="Security"></a>
803  * <h3>Security</h3>
804  * <p>
805  * Sometimes it is essential that an application be able to verify that an action
806  * is being performed with the full knowledge and consent of the user, such as
807  * granting a permission request, making a purchase or clicking on an advertisement.
808  * Unfortunately, a malicious application could try to spoof the user into
809  * performing these actions, unaware, by concealing the intended purpose of the view.
810  * As a remedy, the framework offers a touch filtering mechanism that can be used to
811  * improve the security of views that provide access to sensitive functionality.
812  * </p><p>
813  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
814  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
815  * will discard touches that are received whenever the view's window is obscured by
816  * another visible window at the touched location.  As a result, the view will not receive touches
817  * whenever the touch passed through a toast, dialog or other window that appears above the view's
818  * window.
819  * </p><p>
820  * For more fine-grained control over security, consider overriding the
821  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
822  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
823  * </p>
824  *
825  * @attr ref android.R.styleable#View_accessibilityHeading
826  * @attr ref android.R.styleable#View_allowClickWhenDisabled
827  * @attr ref android.R.styleable#View_alpha
828  * @attr ref android.R.styleable#View_background
829  * @attr ref android.R.styleable#View_clickable
830  * @attr ref android.R.styleable#View_clipToOutline
831  * @attr ref android.R.styleable#View_contentDescription
832  * @attr ref android.R.styleable#View_drawingCacheQuality
833  * @attr ref android.R.styleable#View_duplicateParentState
834  * @attr ref android.R.styleable#View_id
835  * @attr ref android.R.styleable#View_requiresFadingEdge
836  * @attr ref android.R.styleable#View_fadeScrollbars
837  * @attr ref android.R.styleable#View_fadingEdgeLength
838  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
839  * @attr ref android.R.styleable#View_fitsSystemWindows
840  * @attr ref android.R.styleable#View_isScrollContainer
841  * @attr ref android.R.styleable#View_focusable
842  * @attr ref android.R.styleable#View_focusableInTouchMode
843  * @attr ref android.R.styleable#View_focusedByDefault
844  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
845  * @attr ref android.R.styleable#View_keepScreenOn
846  * @attr ref android.R.styleable#View_keyboardNavigationCluster
847  * @attr ref android.R.styleable#View_layerType
848  * @attr ref android.R.styleable#View_layoutDirection
849  * @attr ref android.R.styleable#View_longClickable
850  * @attr ref android.R.styleable#View_minHeight
851  * @attr ref android.R.styleable#View_minWidth
852  * @attr ref android.R.styleable#View_nextClusterForward
853  * @attr ref android.R.styleable#View_nextFocusDown
854  * @attr ref android.R.styleable#View_nextFocusLeft
855  * @attr ref android.R.styleable#View_nextFocusRight
856  * @attr ref android.R.styleable#View_nextFocusUp
857  * @attr ref android.R.styleable#View_onClick
858  * @attr ref android.R.styleable#View_outlineSpotShadowColor
859  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
860  * @attr ref android.R.styleable#View_padding
861  * @attr ref android.R.styleable#View_paddingHorizontal
862  * @attr ref android.R.styleable#View_paddingVertical
863  * @attr ref android.R.styleable#View_paddingBottom
864  * @attr ref android.R.styleable#View_paddingLeft
865  * @attr ref android.R.styleable#View_paddingRight
866  * @attr ref android.R.styleable#View_paddingTop
867  * @attr ref android.R.styleable#View_paddingStart
868  * @attr ref android.R.styleable#View_paddingEnd
869  * @attr ref android.R.styleable#View_saveEnabled
870  * @attr ref android.R.styleable#View_rotation
871  * @attr ref android.R.styleable#View_rotationX
872  * @attr ref android.R.styleable#View_rotationY
873  * @attr ref android.R.styleable#View_scaleX
874  * @attr ref android.R.styleable#View_scaleY
875  * @attr ref android.R.styleable#View_scrollX
876  * @attr ref android.R.styleable#View_scrollY
877  * @attr ref android.R.styleable#View_scrollbarSize
878  * @attr ref android.R.styleable#View_scrollbarStyle
879  * @attr ref android.R.styleable#View_scrollbars
880  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
881  * @attr ref android.R.styleable#View_scrollbarFadeDuration
882  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
883  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
884  * @attr ref android.R.styleable#View_scrollbarThumbVertical
885  * @attr ref android.R.styleable#View_scrollbarTrackVertical
886  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
887  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
888  * @attr ref android.R.styleable#View_stateListAnimator
889  * @attr ref android.R.styleable#View_transitionName
890  * @attr ref android.R.styleable#View_soundEffectsEnabled
891  * @attr ref android.R.styleable#View_tag
892  * @attr ref android.R.styleable#View_textAlignment
893  * @attr ref android.R.styleable#View_textDirection
894  * @attr ref android.R.styleable#View_transformPivotX
895  * @attr ref android.R.styleable#View_transformPivotY
896  * @attr ref android.R.styleable#View_translationX
897  * @attr ref android.R.styleable#View_translationY
898  * @attr ref android.R.styleable#View_translationZ
899  * @attr ref android.R.styleable#View_visibility
900  * @attr ref android.R.styleable#View_theme
901  *
902  * @see android.view.ViewGroup
903  */
904 @UiThread
905 public class View implements Drawable.Callback, KeyEvent.Callback,
906         AccessibilityEventSource {
907     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
908     private static final boolean DBG = false;
909 
910     /** @hide */
911     public static boolean DEBUG_DRAW = false;
912 
913     /**
914      * The logging tag used by this class with android.util.Log.
915      */
916     protected static final String VIEW_LOG_TAG = "View";
917 
918     /**
919      * The logging tag used by this class when logging verbose, autofill-related messages.
920      */
921     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
922     // set if a session is not started.
923     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
924 
925     /**
926      * The logging tag used by this class when logging content capture-related messages.
927      */
928     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
929 
930     private static final boolean DEBUG_CONTENT_CAPTURE = false;
931 
932     /**
933      * When set to true, this view will save its attribute data.
934      *
935      * @hide
936      */
937     public static boolean sDebugViewAttributes = false;
938 
939     /**
940      * When set to this application package view will save its attribute data.
941      *
942      * @hide
943      */
944     public static String sDebugViewAttributesApplicationPackage;
945 
946     /**
947      * Used to mark a View that has no ID.
948      */
949     public static final int NO_ID = -1;
950 
951     /**
952      * Last ID that is given to Views that are no part of activities.
953      *
954      * {@hide}
955      */
956     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
957 
958     /**
959      * Attribute to find the autofilled highlight
960      *
961      * @see #getAutofilledDrawable()
962      */
963     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
964             new int[]{android.R.attr.autofilledHighlight};
965 
966     /**
967      * Signals that compatibility booleans have been initialized according to
968      * target SDK versions.
969      */
970     private static boolean sCompatibilityDone = false;
971 
972     /** @hide */
973     public HapticScrollFeedbackProvider mScrollFeedbackProvider = null;
974 
975     /**
976      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
977      */
978     private static boolean sAlwaysRemeasureExactly = false;
979 
980     /**
981      * When true calculates the bounds in parent from bounds in screen relative to its parents.
982      * This addresses the deprecated API (setBoundsInParent) in Compose, which causes empty
983      * getBoundsInParent call for Compose apps.
984      */
985     private static boolean sCalculateBoundsInParentFromBoundsInScreenFlagValue = false;
986 
987     /**
988      * When true makes it possible to use onMeasure caches also when the force layout flag is
989      * enabled. This helps avoiding multiple measures in the same frame with the same dimensions.
990      */
991     private static boolean sUseMeasureCacheDuringForceLayoutFlagValue;
992 
993     /**
994      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
995      * without throwing
996      */
997     static boolean sTextureViewIgnoresDrawableSetters = false;
998 
999     /**
1000      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
1001      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
1002      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
1003      * check is implemented for backwards compatibility.
1004      *
1005      * {@hide}
1006      */
1007     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
1008 
1009     /**
1010      * Prior to N, when drag enters into child of a view that has already received an
1011      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
1012      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
1013      * false from its event handler for these events.
1014      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
1015      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
1016      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
1017      */
1018     static boolean sCascadedDragDrop;
1019 
1020     /**
1021      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
1022      * to determine things like whether or not to permit item click events. We can't break
1023      * apps that do this just because more things (clickable things) are now auto-focusable
1024      * and they would get different results, so give old behavior to old apps.
1025      */
1026     static boolean sHasFocusableExcludeAutoFocusable;
1027 
1028     /**
1029      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
1030      * made focusable by default. As a result, apps could (incorrectly) change the clickable
1031      * setting of views off the UI thread. Now that clickable can effect the focusable state,
1032      * changing the clickable attribute off the UI thread will cause an exception (since changing
1033      * the focusable state checks). In order to prevent apps from crashing, we will handle this
1034      * specific case and just not notify parents on new focusables resulting from marking views
1035      * clickable from outside the UI thread.
1036      */
1037     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
1038 
1039     /**
1040      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
1041      * Float.NaN. If the app is targetting P or later then passing these values will result in an
1042      * exception being thrown. If the app is targetting an earlier SDK version, then we will
1043      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
1044      * these bogus values.
1045      */
1046     private static boolean sThrowOnInvalidFloatProperties;
1047 
1048     /**
1049      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
1050      * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead.
1051      */
1052     private static boolean sAcceptZeroSizeDragShadow;
1053 
1054     /**
1055      * When true, measure and layout passes of all the newly attached views will be logged with
1056      * {@link Trace}, so we can better debug jank due to complex view hierarchies.
1057      */
1058     private static boolean sTraceLayoutSteps;
1059 
1060     /**
1061      * When not null, emits a {@link Trace} instant event and the stacktrace every time a relayout
1062      * of a class having this name happens.
1063      */
1064     private static String sTraceRequestLayoutClass;
1065 
1066     @Nullable
1067     private ViewCredentialHandler mViewCredentialHandler;
1068 
1069     /** Used to avoid computing the full strings each time when layout tracing is enabled. */
1070     @Nullable
1071     private ViewTraversalTracingStrings mTracingStrings;
1072 
1073     /**
1074      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
1075      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
1076      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
1077      * further down the hierarchy. This violates the basic concepts of the view hierarchy, and
1078      * thus, the hierarchical dispatching mechanism was hard to use for apps.
1079      * <p>
1080      * In order to make window inset dispatching work properly, we dispatch window insets
1081      * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}.
1082      */
1083     static boolean sBrokenInsetsDispatch;
1084 
1085     /**
1086      * Prior to Q, calling
1087      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
1088      * did not call update the window format so the opacity of the background was not correctly
1089      * applied to the window. Some applications rely on this misbehavior to work properly.
1090      * <p>
1091      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
1092      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
1093      * which updates the window format.
1094      * @hide
1095      */
1096     protected static boolean sBrokenWindowBackground;
1097 
1098     /**
1099      * Prior to R, we were always forcing a layout of the entire hierarchy when insets changed from
1100      * the server. This is inefficient and not all apps use it. Instead, we want to rely on apps
1101      * calling {@link #requestLayout} when they need to relayout based on an insets change.
1102      */
1103     static boolean sForceLayoutWhenInsetsChanged;
1104 
1105     /** @hide */
1106     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
1107     @Retention(RetentionPolicy.SOURCE)
1108     public @interface Focusable {}
1109 
1110     /**
1111      * This view does not want keystrokes.
1112      * <p>
1113      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1114      * android:focusable}.
1115      */
1116     public static final int NOT_FOCUSABLE = 0x00000000;
1117 
1118     /**
1119      * This view wants keystrokes.
1120      * <p>
1121      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1122      * android:focusable}.
1123      */
1124     public static final int FOCUSABLE = 0x00000001;
1125 
1126     /**
1127      * This view determines focusability automatically. This is the default.
1128      * <p>
1129      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1130      * android:focusable}.
1131      */
1132     public static final int FOCUSABLE_AUTO = 0x00000010;
1133 
1134     /**
1135      * Mask for use with setFlags indicating bits used for focus.
1136      */
1137     private static final int FOCUSABLE_MASK = 0x00000011;
1138 
1139     /**
1140      * This view will adjust its padding to fit system windows (e.g. status bar)
1141      */
1142     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1143 
1144     /** @hide */
1145     @IntDef({VISIBLE, INVISIBLE, GONE})
1146     @Retention(RetentionPolicy.SOURCE)
1147     public @interface Visibility {}
1148 
1149     /**
1150      * This view is visible.
1151      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1152      * android:visibility}.
1153      */
1154     public static final int VISIBLE = 0x00000000;
1155 
1156     /**
1157      * This view is invisible, but it still takes up space for layout purposes.
1158      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1159      * android:visibility}.
1160      */
1161     public static final int INVISIBLE = 0x00000004;
1162 
1163     /**
1164      * This view is invisible, and it doesn't take any space for layout
1165      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1166      * android:visibility}.
1167      */
1168     public static final int GONE = 0x00000008;
1169 
1170     /**
1171      * Mask for use with setFlags indicating bits used for visibility.
1172      * {@hide}
1173      */
1174     static final int VISIBILITY_MASK = 0x0000000C;
1175 
1176     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1177 
1178     /**
1179      * Hint indicating that this view can be autofilled with an email address.
1180      *
1181      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1182      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1183      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1184      *
1185      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1186      */
1187     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1188 
1189     /**
1190      * Hint indicating that this view can be autofilled with a user's real name.
1191      *
1192      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1193      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1194      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1195      *
1196      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1197      */
1198     public static final String AUTOFILL_HINT_NAME = "name";
1199 
1200     /**
1201      * Hint indicating that this view can be autofilled with a username.
1202      *
1203      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1204      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1205      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1206      *
1207      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1208      */
1209     public static final String AUTOFILL_HINT_USERNAME = "username";
1210 
1211     /**
1212      * Hint indicating that this view can be autofilled with a password.
1213      *
1214      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1215      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1216      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1217      *
1218      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1219      */
1220     public static final String AUTOFILL_HINT_PASSWORD = "password";
1221 
1222     /**
1223      * Hint indicating that this view can be autofilled with a phone number.
1224      *
1225      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1226      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1227      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1228      *
1229      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1230      */
1231     public static final String AUTOFILL_HINT_PHONE = "phone";
1232 
1233     /**
1234      * Hint indicating that this view can be autofilled with a postal address.
1235      *
1236      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1237      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1238      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1239      *
1240      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1241      */
1242     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1243 
1244     /**
1245      * Hint indicating that this view can be autofilled with a postal code.
1246      *
1247      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1248      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1249      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1250      *
1251      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1252      */
1253     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1254 
1255     /**
1256      * Hint indicating that this view can be autofilled with a credit card number.
1257      *
1258      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1259      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1260      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1261      *
1262      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1263      */
1264     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1265 
1266     /**
1267      * Hint indicating that this view can be autofilled with a credit card security code.
1268      *
1269      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1270      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1271      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1272      *
1273      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1274      */
1275     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1276 
1277     /**
1278      * Hint indicating that this view can be autofilled with a credit card expiration date.
1279      *
1280      * <p>It should be used when the credit card expiration date is represented by just one view;
1281      * if it is represented by more than one (for example, one view for the month and another view
1282      * for the year), then each of these views should use the hint specific for the unit
1283      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1284      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1285      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1286      *
1287      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1288      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1289      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1290      *
1291      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1292      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1293      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1294      * the following options:
1295      *
1296      * <ul>
1297      *   <li>{@code "04/2020"}
1298      *   <li>{@code "4/2020"}
1299      *   <li>{@code "2020/04"}
1300      *   <li>{@code "2020/4"}
1301      *   <li>{@code "April/2020"}
1302      *   <li>{@code "Apr/2020"}
1303      * </ul>
1304      *
1305      * <p>You define a date autofill value for the view by overriding the following methods:
1306      *
1307      * <ol>
1308      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1309      *   <li>{@link #getAutofillValue()} to return a
1310      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1311      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1312      * </ol>
1313      *
1314      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1315      */
1316     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1317             "creditCardExpirationDate";
1318 
1319     /**
1320      * Hint indicating that this view can be autofilled with a credit card expiration month.
1321      *
1322      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1323      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1324      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1325      *
1326      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1327      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1328      * ambiguity when the autofill service provides a value for it. To understand why a
1329      * value can be ambiguous, consider "January", which could be represented as either of
1330      *
1331      * <ul>
1332      *   <li>{@code "1"}: recommended way.
1333      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1334      *   <li>{@code "January"}: full name, in English.
1335      *   <li>{@code "jan"}: abbreviated name, in English.
1336      *   <li>{@code "Janeiro"}: full name, in another language.
1337      * </ul>
1338      *
1339      * <p>Another recommended approach is to use a date autofill value - see
1340      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1341      *
1342      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1343      */
1344     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1345             "creditCardExpirationMonth";
1346 
1347     /**
1348      * Hint indicating that this view can be autofilled with a credit card expiration year.
1349      *
1350      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1351      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1352      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1353      *
1354      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1355      */
1356     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1357             "creditCardExpirationYear";
1358 
1359     /**
1360      * Hint indicating that this view can be autofilled with a credit card expiration day.
1361      *
1362      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1363      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1364      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1365      *
1366      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1367      */
1368     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1369 
1370     /**
1371      * A hint indicating that this view can be autofilled with a password.
1372      *
1373      * This is a heuristic-based hint that is meant to be used by UI Toolkit developers when a
1374      * view is a password field but doesn't specify a
1375      * <code>{@value View#AUTOFILL_HINT_PASSWORD}</code>.
1376      * @hide
1377      */
1378     // TODO(229765029): unhide this for UI toolkit
1379     public static final String AUTOFILL_HINT_PASSWORD_AUTO = "passwordAuto";
1380 
1381     /**
1382      * Hint indicating that the developer intends to fill this view with output from
1383      * CredentialManager.
1384      *
1385      * @hide
1386      */
1387     public static final String AUTOFILL_HINT_CREDENTIAL_MANAGER = "credential";
1388 
1389     /**
1390      * Hints for the autofill services that describes the content of the view.
1391      */
1392     private @Nullable String[] mAutofillHints;
1393 
1394     /**
1395      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1396      */
1397     private AutofillId mAutofillId;
1398 
1399     /** @hide */
1400     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1401             AUTOFILL_TYPE_NONE,
1402             AUTOFILL_TYPE_TEXT,
1403             AUTOFILL_TYPE_TOGGLE,
1404             AUTOFILL_TYPE_LIST,
1405             AUTOFILL_TYPE_DATE,
1406     })
1407     @Retention(RetentionPolicy.SOURCE)
1408     public @interface AutofillType {}
1409 
1410     /**
1411      * Autofill type for views that cannot be autofilled.
1412      *
1413      * <p>Typically used when the view is read-only; for example, a text label.
1414      *
1415      * @see #getAutofillType()
1416      */
1417     public static final int AUTOFILL_TYPE_NONE = 0;
1418 
1419     /**
1420      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1421      *
1422      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1423      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1424      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1425      *
1426      * @see #getAutofillType()
1427      */
1428     public static final int AUTOFILL_TYPE_TEXT = 1;
1429 
1430     /**
1431      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1432      *
1433      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1434      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1435      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1436      *
1437      * @see #getAutofillType()
1438      */
1439     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1440 
1441     /**
1442      * Autofill type for a selection list field, which is filled by an {@code int}
1443      * representing the element index inside the list (starting at {@code 0}).
1444      *
1445      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1446      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1447      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1448      *
1449      * <p>The available options in the selection list are typically provided by
1450      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1451      *
1452      * @see #getAutofillType()
1453      */
1454     public static final int AUTOFILL_TYPE_LIST = 3;
1455 
1456     /**
1457      * Autofill type for a field that contains a date, which is represented by a long representing
1458      * the number of milliseconds since the standard base time known as "the epoch", namely
1459      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1460      *
1461      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1462      * {@link AutofillValue#forDate(long)}, and the values passed to
1463      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1464      *
1465      * @see #getAutofillType()
1466      */
1467     public static final int AUTOFILL_TYPE_DATE = 4;
1468 
1469 
1470     /** @hide */
1471     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1472             IMPORTANT_FOR_AUTOFILL_AUTO,
1473             IMPORTANT_FOR_AUTOFILL_YES,
1474             IMPORTANT_FOR_AUTOFILL_NO,
1475             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1476             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1477     })
1478     @Retention(RetentionPolicy.SOURCE)
1479     public @interface AutofillImportance {}
1480 
1481     /**
1482      * Automatically determine whether a view is important for autofill.
1483      *
1484      * @see #isImportantForAutofill()
1485      * @see #setImportantForAutofill(int)
1486      */
1487     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1488 
1489     /**
1490      * The view is important for autofill, and its children (if any) will be traversed.
1491      *
1492      * @see #isImportantForAutofill()
1493      * @see #setImportantForAutofill(int)
1494      */
1495     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1496 
1497     /**
1498      * The view is not important for autofill, but its children (if any) will be traversed.
1499      *
1500      * @see #isImportantForAutofill()
1501      * @see #setImportantForAutofill(int)
1502      */
1503     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1504 
1505     /**
1506      * The view is important for autofill, but its children (if any) will not be traversed.
1507      *
1508      * @see #isImportantForAutofill()
1509      * @see #setImportantForAutofill(int)
1510      */
1511     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1512 
1513     /**
1514      * The view is not important for autofill, and its children (if any) will not be traversed.
1515      *
1516      * @see #isImportantForAutofill()
1517      * @see #setImportantForAutofill(int)
1518      */
1519     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1520 
1521     /** @hide */
1522     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1523             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1524     })
1525     @Retention(RetentionPolicy.SOURCE)
1526     public @interface AutofillFlags {}
1527 
1528     /**
1529      * Flag requesting you to add views that are marked as not important for autofill
1530      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1531      */
1532     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1533 
1534     /** @hide */
1535     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1536             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1537             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1538             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1539             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1540             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1541     })
1542     @Retention(RetentionPolicy.SOURCE)
1543     public @interface ContentCaptureImportance {}
1544 
1545     /**
1546      * Automatically determine whether a view is important for content capture.
1547      *
1548      * @see #isImportantForContentCapture()
1549      * @see #setImportantForContentCapture(int)
1550      */
1551     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1552 
1553     /**
1554      * The view is important for content capture, and its children (if any) will be traversed.
1555      *
1556      * @see #isImportantForContentCapture()
1557      * @see #setImportantForContentCapture(int)
1558      */
1559     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1560 
1561     /**
1562      * The view is not important for content capture, but its children (if any) will be traversed.
1563      *
1564      * @see #isImportantForContentCapture()
1565      * @see #setImportantForContentCapture(int)
1566      */
1567     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1568 
1569     /**
1570      * The view is important for content capture, but its children (if any) will not be traversed.
1571      *
1572      * @see #isImportantForContentCapture()
1573      * @see #setImportantForContentCapture(int)
1574      */
1575     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1576 
1577     /**
1578      * The view is not important for content capture, and its children (if any) will not be
1579      * traversed.
1580      *
1581      * @see #isImportantForContentCapture()
1582      * @see #setImportantForContentCapture(int)
1583      */
1584     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1585 
1586     /** {@hide} */
1587     @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
1588             value = {
1589                     SCROLL_CAPTURE_HINT_AUTO,
1590                     SCROLL_CAPTURE_HINT_EXCLUDE,
1591                     SCROLL_CAPTURE_HINT_INCLUDE,
1592                     SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
1593     })
1594     @Retention(RetentionPolicy.SOURCE)
1595     public @interface ScrollCaptureHint {}
1596 
1597     /**
1598      * The content of this view will be considered for scroll capture if scrolling is possible.
1599      *
1600      * @see #getScrollCaptureHint()
1601      * @see #setScrollCaptureHint(int)
1602      */
1603     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
1604 
1605     /**
1606      * Explicitly exclude this view as a potential scroll capture target. The system will not
1607      * consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
1608      * takes precedence over.
1609      *
1610      * @see #getScrollCaptureHint()
1611      * @see #setScrollCaptureHint(int)
1612      */
1613     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
1614 
1615     /**
1616      * Explicitly include this view as a potential scroll capture target. When locating a scroll
1617      * capture target, this view will be prioritized before others without this flag. Mutually
1618      * exclusive with {@link #SCROLL_CAPTURE_HINT_EXCLUDE}, which takes precedence.
1619      *
1620      * @see #getScrollCaptureHint()
1621      * @see #setScrollCaptureHint(int)
1622      */
1623     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
1624 
1625     /**
1626      * Explicitly exclude all children of this view as potential scroll capture targets. This view
1627      * is unaffected. Note: Excluded children are not considered, regardless of {@link
1628      * #SCROLL_CAPTURE_HINT_INCLUDE}.
1629      *
1630      * @see #getScrollCaptureHint()
1631      * @see #setScrollCaptureHint(int)
1632      */
1633     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
1634 
1635     /**
1636      * This view is enabled. Interpretation varies by subclass.
1637      * Use with ENABLED_MASK when calling setFlags.
1638      * {@hide}
1639      */
1640     static final int ENABLED = 0x00000000;
1641 
1642     /**
1643      * This view is disabled. Interpretation varies by subclass.
1644      * Use with ENABLED_MASK when calling setFlags.
1645      * {@hide}
1646      */
1647     static final int DISABLED = 0x00000020;
1648 
1649     /**
1650      * Mask for use with setFlags indicating bits used for indicating whether
1651      * this view is enabled
1652      * {@hide}
1653      */
1654     static final int ENABLED_MASK = 0x00000020;
1655 
1656     /**
1657      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1658      * called and further optimizations will be performed. It is okay to have
1659      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1660      * {@hide}
1661      */
1662     static final int WILL_NOT_DRAW = 0x00000080;
1663 
1664     /**
1665      * Mask for use with setFlags indicating bits used for indicating whether
1666      * this view is will draw
1667      * {@hide}
1668      */
1669     static final int DRAW_MASK = 0x00000080;
1670 
1671     /**
1672      * <p>This view doesn't show scrollbars.</p>
1673      * {@hide}
1674      */
1675     static final int SCROLLBARS_NONE = 0x00000000;
1676 
1677     /**
1678      * <p>This view shows horizontal scrollbars.</p>
1679      * {@hide}
1680      */
1681     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1682 
1683     /**
1684      * <p>This view shows vertical scrollbars.</p>
1685      * {@hide}
1686      */
1687     static final int SCROLLBARS_VERTICAL = 0x00000200;
1688 
1689     /**
1690      * <p>Mask for use with setFlags indicating bits used for indicating which
1691      * scrollbars are enabled.</p>
1692      * {@hide}
1693      */
1694     static final int SCROLLBARS_MASK = 0x00000300;
1695 
1696     /**
1697      * Indicates that the view should filter touches when its window is obscured.
1698      * Refer to the class comments for more information about this security feature.
1699      * {@hide}
1700      */
1701     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1702 
1703     /**
1704      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1705      * that they are optional and should be skipped if the window has
1706      * requested system UI flags that ignore those insets for layout.
1707      * <p>
1708      * This is only used for support library as of Android R. The framework now uses
1709      * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
1710      * insets path that loses insets information.
1711      */
1712     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1713 
1714     /**
1715      * <p>This view doesn't show fading edges.</p>
1716      * {@hide}
1717      */
1718     static final int FADING_EDGE_NONE = 0x00000000;
1719 
1720     /**
1721      * <p>This view shows horizontal fading edges.</p>
1722      * {@hide}
1723      */
1724     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1725 
1726     /**
1727      * <p>This view shows vertical fading edges.</p>
1728      * {@hide}
1729      */
1730     static final int FADING_EDGE_VERTICAL = 0x00002000;
1731 
1732     /**
1733      * <p>Mask for use with setFlags indicating bits used for indicating which
1734      * fading edges are enabled.</p>
1735      * {@hide}
1736      */
1737     static final int FADING_EDGE_MASK = 0x00003000;
1738 
1739     /**
1740      * <p>Indicates this view can be clicked. When clickable, a View reacts
1741      * to clicks by notifying the OnClickListener.<p>
1742      * {@hide}
1743      */
1744     static final int CLICKABLE = 0x00004000;
1745 
1746     /**
1747      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1748      * {@hide}
1749      */
1750     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1751 
1752     /**
1753      * <p>Indicates that no icicle should be saved for this view.<p>
1754      * {@hide}
1755      */
1756     static final int SAVE_DISABLED = 0x000010000;
1757 
1758     /**
1759      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1760      * property.</p>
1761      * {@hide}
1762      */
1763     static final int SAVE_DISABLED_MASK = 0x000010000;
1764 
1765     /**
1766      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1767      * {@hide}
1768      */
1769     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1770 
1771     /**
1772      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1773      * {@hide}
1774      */
1775     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1776 
1777     /** @hide */
1778     @Retention(RetentionPolicy.SOURCE)
1779     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1780             DRAWING_CACHE_QUALITY_LOW,
1781             DRAWING_CACHE_QUALITY_HIGH,
1782             DRAWING_CACHE_QUALITY_AUTO
1783     })
1784     public @interface DrawingCacheQuality {}
1785 
1786     /**
1787      * <p>Enables low 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_LOW = 0x00080000;
1804 
1805     /**
1806      * <p>Enables high 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_HIGH = 0x00100000;
1823 
1824     /**
1825      * <p>Enables automatic quality mode for the drawing cache.</p>
1826      *
1827      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1828      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1829      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1830      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1831      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1832      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1833      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1834      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1835      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1836      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1837      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1838      * reports or unit testing the {@link PixelCopy} API is recommended.
1839      */
1840     @Deprecated
1841     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1842 
1843     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1844             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1845     };
1846 
1847     /**
1848      * <p>Mask for use with setFlags indicating bits used for the cache
1849      * quality property.</p>
1850      * {@hide}
1851      */
1852     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1853 
1854     /**
1855      * <p>
1856      * Indicates this view can be long clicked. When long clickable, a View
1857      * reacts to long clicks by notifying the OnLongClickListener or showing a
1858      * context menu.
1859      * </p>
1860      * {@hide}
1861      */
1862     static final int LONG_CLICKABLE = 0x00200000;
1863 
1864     /**
1865      * <p>Indicates that this view gets its drawable states from its direct parent
1866      * and ignores its original internal states.</p>
1867      *
1868      * @hide
1869      */
1870     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1871 
1872     /**
1873      * <p>
1874      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1875      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1876      * OnContextClickListener.
1877      * </p>
1878      * {@hide}
1879      */
1880     static final int CONTEXT_CLICKABLE = 0x00800000;
1881 
1882     /** @hide */
1883     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1884             SCROLLBARS_INSIDE_OVERLAY,
1885             SCROLLBARS_INSIDE_INSET,
1886             SCROLLBARS_OUTSIDE_OVERLAY,
1887             SCROLLBARS_OUTSIDE_INSET
1888     })
1889     @Retention(RetentionPolicy.SOURCE)
1890     public @interface ScrollBarStyle {}
1891 
1892     /**
1893      * The scrollbar style to display the scrollbars inside the content area,
1894      * without increasing the padding. The scrollbars will be overlaid with
1895      * translucency on the view's content.
1896      */
1897     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1898 
1899     /**
1900      * The scrollbar style to display the scrollbars inside the padded area,
1901      * increasing the padding of the view. The scrollbars will not overlap the
1902      * content area of the view.
1903      */
1904     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1905 
1906     /**
1907      * The scrollbar style to display the scrollbars at the edge of the view,
1908      * without increasing the padding. The scrollbars will be overlaid with
1909      * translucency.
1910      */
1911     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1912 
1913     /**
1914      * The scrollbar style to display the scrollbars at the edge of the view,
1915      * increasing the padding of the view. The scrollbars will only overlap the
1916      * background, if any.
1917      */
1918     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1919 
1920     /**
1921      * Mask to check if the scrollbar style is overlay or inset.
1922      * {@hide}
1923      */
1924     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1925 
1926     /**
1927      * Mask to check if the scrollbar style is inside or outside.
1928      * {@hide}
1929      */
1930     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1931 
1932     /**
1933      * Mask for scrollbar style.
1934      * {@hide}
1935      */
1936     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1937 
1938     /**
1939      * View flag indicating that the screen should remain on while the
1940      * window containing this view is visible to the user.  This effectively
1941      * takes care of automatically setting the WindowManager's
1942      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1943      */
1944     public static final int KEEP_SCREEN_ON = 0x04000000;
1945 
1946     /**
1947      * View flag indicating whether this view should have sound effects enabled
1948      * for events such as clicking and touching.
1949      */
1950     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1951 
1952     /**
1953      * View flag indicating whether this view should have haptic feedback
1954      * enabled for events such as long presses.
1955      */
1956     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1957 
1958     /**
1959      * <p>Indicates that the view hierarchy should stop saving state when
1960      * it reaches this view.  If state saving is initiated immediately at
1961      * the view, it will be allowed.
1962      * {@hide}
1963      */
1964     static final int PARENT_SAVE_DISABLED = 0x20000000;
1965 
1966     /**
1967      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1968      * {@hide}
1969      */
1970     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1971 
1972     private static Paint sDebugPaint;
1973 
1974     /**
1975      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1976      * {@hide}
1977      */
1978     static final int TOOLTIP = 0x40000000;
1979 
1980     /** @hide */
1981     @IntDef(prefix = { "CONTENT_SENSITIVITY_" }, value = {
1982             CONTENT_SENSITIVITY_AUTO,
1983             CONTENT_SENSITIVITY_SENSITIVE,
1984             CONTENT_SENSITIVITY_NOT_SENSITIVE
1985     })
1986     @Retention(RetentionPolicy.SOURCE)
1987     public @interface ContentSensitivity {}
1988 
1989     /**
1990      * Content sensitivity is determined by the framework. The framework uses a heuristic to
1991      * determine if this view displays sensitive content.
1992      * Autofill hints i.e. {@link #getAutofillHints()}  are used in the heuristic
1993      * to determine if this view should be considered as a sensitive view.
1994      * <p>
1995      * {@link #AUTOFILL_HINT_USERNAME},
1996      * {@link #AUTOFILL_HINT_PASSWORD},
1997      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER},
1998      * {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
1999      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
2000      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
2001      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
2002      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}
2003      * are considered sensitive hints by the framework, and the list may include more hints
2004      * in the future.
2005      *
2006      * <p> The window hosting a sensitive view will be marked as secure during an active media
2007      * projection session. This would be equivalent to applying
2008      * {@link android.view.WindowManager.LayoutParams#FLAG_SECURE} to the window.
2009      *
2010      * @see #getContentSensitivity()
2011      */
2012     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
2013     public static final int CONTENT_SENSITIVITY_AUTO = 0x0;
2014 
2015     /**
2016      * The view displays sensitive content.
2017      *
2018      * <p> The window hosting a sensitive view will be marked as secure during an active media
2019      * projection session. This would be equivalent to applying
2020      * {@link android.view.WindowManager.LayoutParams#FLAG_SECURE} to the window.
2021      *
2022      * @see #getContentSensitivity()
2023      */
2024     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
2025     public static final int CONTENT_SENSITIVITY_SENSITIVE = 0x1;
2026 
2027     /**
2028      * The view doesn't display sensitive content.
2029      *
2030      * @see #getContentSensitivity()
2031      */
2032     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
2033     public static final int CONTENT_SENSITIVITY_NOT_SENSITIVE = 0x2;
2034 
2035     /** @hide */
2036     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
2037             FOCUSABLES_ALL,
2038             FOCUSABLES_TOUCH_MODE
2039     })
2040     @Retention(RetentionPolicy.SOURCE)
2041     public @interface FocusableMode {}
2042 
2043     /**
2044      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
2045      * should add all focusable Views regardless if they are focusable in touch mode.
2046      */
2047     public static final int FOCUSABLES_ALL = 0x00000000;
2048 
2049     /**
2050      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
2051      * should add only Views focusable in touch mode.
2052      */
2053     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
2054 
2055     /** @hide */
2056     @IntDef(prefix = { "FOCUS_" }, value = {
2057             FOCUS_BACKWARD,
2058             FOCUS_FORWARD,
2059             FOCUS_LEFT,
2060             FOCUS_UP,
2061             FOCUS_RIGHT,
2062             FOCUS_DOWN
2063     })
2064     @Retention(RetentionPolicy.SOURCE)
2065     public @interface FocusDirection {}
2066 
2067     /** @hide */
2068     @IntDef(prefix = { "FOCUS_" }, value = {
2069             FOCUS_LEFT,
2070             FOCUS_UP,
2071             FOCUS_RIGHT,
2072             FOCUS_DOWN
2073     })
2074     @Retention(RetentionPolicy.SOURCE)
2075     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
2076 
2077     /**
2078      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
2079      * item.
2080      */
2081     public static final int FOCUS_BACKWARD = 0x00000001;
2082 
2083     /**
2084      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
2085      * item.
2086      */
2087     public static final int FOCUS_FORWARD = 0x00000002;
2088 
2089     /**
2090      * Use with {@link #focusSearch(int)}. Move focus to the left.
2091      */
2092     public static final int FOCUS_LEFT = 0x00000011;
2093 
2094     /**
2095      * Use with {@link #focusSearch(int)}. Move focus up.
2096      */
2097     public static final int FOCUS_UP = 0x00000021;
2098 
2099     /**
2100      * Use with {@link #focusSearch(int)}. Move focus to the right.
2101      */
2102     public static final int FOCUS_RIGHT = 0x00000042;
2103 
2104     /**
2105      * Use with {@link #focusSearch(int)}. Move focus down.
2106      */
2107     public static final int FOCUS_DOWN = 0x00000082;
2108 
2109     /**
2110      * Bits of {@link #getMeasuredWidthAndState()} and
2111      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
2112      */
2113     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
2114 
2115     /**
2116      * Bits of {@link #getMeasuredWidthAndState()} and
2117      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
2118      */
2119     public static final int MEASURED_STATE_MASK = 0xff000000;
2120 
2121     /**
2122      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
2123      * for functions that combine both width and height into a single int,
2124      * such as {@link #getMeasuredState()} and the childState argument of
2125      * {@link #resolveSizeAndState(int, int, int)}.
2126      */
2127     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
2128 
2129     /**
2130      * Bit of {@link #getMeasuredWidthAndState()} and
2131      * {@link #getMeasuredWidthAndState()} that indicates the measured size
2132      * is smaller that the space the view would like to have.
2133      */
2134     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
2135 
2136     /**
2137      * Base View state sets
2138      */
2139     // Singles
2140     /**
2141      * Indicates the view has no states set. States are used with
2142      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2143      * view depending on its state.
2144      *
2145      * @see android.graphics.drawable.Drawable
2146      * @see #getDrawableState()
2147      */
2148     protected static final int[] EMPTY_STATE_SET;
2149     /**
2150      * Indicates the view is enabled. States are used with
2151      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2152      * view depending on its state.
2153      *
2154      * @see android.graphics.drawable.Drawable
2155      * @see #getDrawableState()
2156      */
2157     protected static final int[] ENABLED_STATE_SET;
2158     /**
2159      * Indicates the view is focused. States are used with
2160      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2161      * view depending on its state.
2162      *
2163      * @see android.graphics.drawable.Drawable
2164      * @see #getDrawableState()
2165      */
2166     protected static final int[] FOCUSED_STATE_SET;
2167     /**
2168      * Indicates the view is selected. States are used with
2169      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2170      * view depending on its state.
2171      *
2172      * @see android.graphics.drawable.Drawable
2173      * @see #getDrawableState()
2174      */
2175     protected static final int[] SELECTED_STATE_SET;
2176     /**
2177      * Indicates the view is pressed. States are used with
2178      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2179      * view depending on its state.
2180      *
2181      * @see android.graphics.drawable.Drawable
2182      * @see #getDrawableState()
2183      */
2184     protected static final int[] PRESSED_STATE_SET;
2185     /**
2186      * Indicates the view's window has focus. States are used with
2187      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2188      * view depending on its state.
2189      *
2190      * @see android.graphics.drawable.Drawable
2191      * @see #getDrawableState()
2192      */
2193     protected static final int[] WINDOW_FOCUSED_STATE_SET;
2194     // Doubles
2195     /**
2196      * Indicates the view is enabled and has the focus.
2197      *
2198      * @see #ENABLED_STATE_SET
2199      * @see #FOCUSED_STATE_SET
2200      */
2201     protected static final int[] ENABLED_FOCUSED_STATE_SET;
2202     /**
2203      * Indicates the view is enabled and selected.
2204      *
2205      * @see #ENABLED_STATE_SET
2206      * @see #SELECTED_STATE_SET
2207      */
2208     protected static final int[] ENABLED_SELECTED_STATE_SET;
2209     /**
2210      * Indicates the view is enabled and that its window has focus.
2211      *
2212      * @see #ENABLED_STATE_SET
2213      * @see #WINDOW_FOCUSED_STATE_SET
2214      */
2215     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
2216     /**
2217      * Indicates the view is focused and selected.
2218      *
2219      * @see #FOCUSED_STATE_SET
2220      * @see #SELECTED_STATE_SET
2221      */
2222     protected static final int[] FOCUSED_SELECTED_STATE_SET;
2223     /**
2224      * Indicates the view has the focus and that its window has the focus.
2225      *
2226      * @see #FOCUSED_STATE_SET
2227      * @see #WINDOW_FOCUSED_STATE_SET
2228      */
2229     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
2230     /**
2231      * Indicates the view is selected and that its window has the focus.
2232      *
2233      * @see #SELECTED_STATE_SET
2234      * @see #WINDOW_FOCUSED_STATE_SET
2235      */
2236     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2237     // Triples
2238     /**
2239      * Indicates the view is enabled, focused and selected.
2240      *
2241      * @see #ENABLED_STATE_SET
2242      * @see #FOCUSED_STATE_SET
2243      * @see #SELECTED_STATE_SET
2244      */
2245     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2246     /**
2247      * Indicates the view is enabled, focused and its window has the focus.
2248      *
2249      * @see #ENABLED_STATE_SET
2250      * @see #FOCUSED_STATE_SET
2251      * @see #WINDOW_FOCUSED_STATE_SET
2252      */
2253     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2254     /**
2255      * Indicates the view is enabled, selected and its window has the focus.
2256      *
2257      * @see #ENABLED_STATE_SET
2258      * @see #SELECTED_STATE_SET
2259      * @see #WINDOW_FOCUSED_STATE_SET
2260      */
2261     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2262     /**
2263      * Indicates the view is focused, selected and its window has the focus.
2264      *
2265      * @see #FOCUSED_STATE_SET
2266      * @see #SELECTED_STATE_SET
2267      * @see #WINDOW_FOCUSED_STATE_SET
2268      */
2269     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2270     /**
2271      * Indicates the view is enabled, focused, selected and its window
2272      * has the focus.
2273      *
2274      * @see #ENABLED_STATE_SET
2275      * @see #FOCUSED_STATE_SET
2276      * @see #SELECTED_STATE_SET
2277      * @see #WINDOW_FOCUSED_STATE_SET
2278      */
2279     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2280     /**
2281      * Indicates the view is pressed and its window has the focus.
2282      *
2283      * @see #PRESSED_STATE_SET
2284      * @see #WINDOW_FOCUSED_STATE_SET
2285      */
2286     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2287     /**
2288      * Indicates the view is pressed and selected.
2289      *
2290      * @see #PRESSED_STATE_SET
2291      * @see #SELECTED_STATE_SET
2292      */
2293     protected static final int[] PRESSED_SELECTED_STATE_SET;
2294     /**
2295      * Indicates the view is pressed, selected and its window has the focus.
2296      *
2297      * @see #PRESSED_STATE_SET
2298      * @see #SELECTED_STATE_SET
2299      * @see #WINDOW_FOCUSED_STATE_SET
2300      */
2301     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2302     /**
2303      * Indicates the view is pressed and focused.
2304      *
2305      * @see #PRESSED_STATE_SET
2306      * @see #FOCUSED_STATE_SET
2307      */
2308     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2309     /**
2310      * Indicates the view is pressed, focused and its window has the focus.
2311      *
2312      * @see #PRESSED_STATE_SET
2313      * @see #FOCUSED_STATE_SET
2314      * @see #WINDOW_FOCUSED_STATE_SET
2315      */
2316     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2317     /**
2318      * Indicates the view is pressed, focused and selected.
2319      *
2320      * @see #PRESSED_STATE_SET
2321      * @see #SELECTED_STATE_SET
2322      * @see #FOCUSED_STATE_SET
2323      */
2324     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2325     /**
2326      * Indicates the view is pressed, focused, selected and its window has the focus.
2327      *
2328      * @see #PRESSED_STATE_SET
2329      * @see #FOCUSED_STATE_SET
2330      * @see #SELECTED_STATE_SET
2331      * @see #WINDOW_FOCUSED_STATE_SET
2332      */
2333     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2334     /**
2335      * Indicates the view is pressed and enabled.
2336      *
2337      * @see #PRESSED_STATE_SET
2338      * @see #ENABLED_STATE_SET
2339      */
2340     protected static final int[] PRESSED_ENABLED_STATE_SET;
2341     /**
2342      * Indicates the view is pressed, enabled and its window has the focus.
2343      *
2344      * @see #PRESSED_STATE_SET
2345      * @see #ENABLED_STATE_SET
2346      * @see #WINDOW_FOCUSED_STATE_SET
2347      */
2348     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2349     /**
2350      * Indicates the view is pressed, enabled and selected.
2351      *
2352      * @see #PRESSED_STATE_SET
2353      * @see #ENABLED_STATE_SET
2354      * @see #SELECTED_STATE_SET
2355      */
2356     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2357     /**
2358      * Indicates the view is pressed, enabled, selected and its window has the
2359      * focus.
2360      *
2361      * @see #PRESSED_STATE_SET
2362      * @see #ENABLED_STATE_SET
2363      * @see #SELECTED_STATE_SET
2364      * @see #WINDOW_FOCUSED_STATE_SET
2365      */
2366     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2367     /**
2368      * Indicates the view is pressed, enabled and focused.
2369      *
2370      * @see #PRESSED_STATE_SET
2371      * @see #ENABLED_STATE_SET
2372      * @see #FOCUSED_STATE_SET
2373      */
2374     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2375     /**
2376      * Indicates the view is pressed, enabled, focused and its window has the
2377      * focus.
2378      *
2379      * @see #PRESSED_STATE_SET
2380      * @see #ENABLED_STATE_SET
2381      * @see #FOCUSED_STATE_SET
2382      * @see #WINDOW_FOCUSED_STATE_SET
2383      */
2384     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2385     /**
2386      * Indicates the view is pressed, enabled, focused and selected.
2387      *
2388      * @see #PRESSED_STATE_SET
2389      * @see #ENABLED_STATE_SET
2390      * @see #SELECTED_STATE_SET
2391      * @see #FOCUSED_STATE_SET
2392      */
2393     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2394     /**
2395      * Indicates the view is pressed, enabled, focused, selected and its window
2396      * has the focus.
2397      *
2398      * @see #PRESSED_STATE_SET
2399      * @see #ENABLED_STATE_SET
2400      * @see #SELECTED_STATE_SET
2401      * @see #FOCUSED_STATE_SET
2402      * @see #WINDOW_FOCUSED_STATE_SET
2403      */
2404     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2405 
2406     /**
2407      * This indicates that the frame rate category was chosen for an unknown reason.
2408      * @hide
2409      */
2410     public static final int FRAME_RATE_CATEGORY_REASON_UNKNOWN = 0x0000_0000;
2411 
2412     /**
2413      * This indicates that the frame rate category was chosen because it was a small area update.
2414      * @hide
2415      */
2416     public static final int FRAME_RATE_CATEGORY_REASON_SMALL = 0x0100_0000;
2417 
2418     /**
2419      * This indicates that the frame rate category was chosen because it was an intermittent update.
2420      * @hide
2421      */
2422     public static final int FRAME_RATE_CATEGORY_REASON_INTERMITTENT = 0x0200_0000;
2423 
2424     /**
2425      * This indicates that the frame rate category was chosen because it was a large View.
2426      * @hide
2427      */
2428     public static final int FRAME_RATE_CATEGORY_REASON_LARGE = 0x03000000;
2429 
2430     /**
2431      * This indicates that the frame rate category was chosen because it was requested.
2432      * @hide
2433      */
2434     public static final int FRAME_RATE_CATEGORY_REASON_REQUESTED = 0x0400_0000;
2435 
2436     /**
2437      * This indicates that the frame rate category was chosen because an invalid frame rate was
2438      * requested.
2439      * @hide
2440      */
2441     public static final int FRAME_RATE_CATEGORY_REASON_INVALID = 0x0500_0000;
2442 
2443     /**
2444      * This indicates that the frame rate category was chosen because the view has a velocity
2445      * @hide
2446      */
2447     public static final int FRAME_RATE_CATEGORY_REASON_VELOCITY = 0x0600_0000;
2448 
2449     /**
2450      * This indicates that the frame rate category was chosen because it is currently boosting.
2451      * @hide
2452      */
2453     public static final int FRAME_RATE_CATEGORY_REASON_BOOST = 0x0800_0000;
2454 
2455     /**
2456      * This indicates that the frame rate category was chosen because it is currently having
2457      * touch boost.
2458      * @hide
2459      */
2460     public static final int FRAME_RATE_CATEGORY_REASON_TOUCH = 0x0900_0000;
2461 
2462     /**
2463      * This indicates that the frame rate category was chosen because it is currently having
2464      * touch boost.
2465      * @hide
2466      */
2467     public static final int FRAME_RATE_CATEGORY_REASON_CONFLICTED = 0x0A00_0000;
2468 
2469     private static final int FRAME_RATE_CATEGORY_REASON_MASK = 0xFFFF_0000;
2470 
2471     /**
2472      * @hide
2473      */
2474     protected static boolean sToolkitSetFrameRateReadOnlyFlagValue;
2475     private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
2476     private static final boolean sToolkitFrameRateDefaultNormalReadOnlyFlagValue =
2477             toolkitFrameRateDefaultNormalReadOnly();
2478     private static final boolean sToolkitFrameRateBySizeReadOnlyFlagValue =
2479             toolkitFrameRateBySizeReadOnly();
2480     private static final boolean sToolkitFrameRateSmallUsesPercentReadOnlyFlagValue =
2481             toolkitFrameRateSmallUsesPercentReadOnly();
2482     private static final boolean sToolkitFrameRateViewEnablingReadOnlyFlagValue =
2483             toolkitFrameRateViewEnablingReadOnly();
2484     private static boolean sToolkitFrameRateVelocityMappingReadOnlyFlagValue =
2485             toolkitFrameRateVelocityMappingReadOnly();
2486     private static boolean sToolkitFrameRateAnimationBugfix25q1FlagValue =
2487             toolkitFrameRateAnimationBugfix25q1();
2488     private static boolean sToolkitViewGroupFrameRateApiFlagValue =
2489             toolkitViewgroupSetRequestedFrameRateApi();
2490 
2491     // Used to set frame rate compatibility.
2492     @Surface.FrameRateCompatibility int mFrameRateCompatibility =
2493             FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
2494 
2495     static {
2496         EMPTY_STATE_SET = StateSet.get(0);
2497 
2498         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2499 
2500         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2501         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2502                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2503 
2504         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2505         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2506                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2507         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2508                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2509         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2510                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2511                         | StateSet.VIEW_STATE_FOCUSED);
2512 
2513         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2514         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2515                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2516         ENABLED_SELECTED_STATE_SET = StateSet.get(
2517                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2518         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2519                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2520                         | StateSet.VIEW_STATE_ENABLED);
2521         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2522                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2523         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2524                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2525                         | StateSet.VIEW_STATE_ENABLED);
2526         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2527                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2528                         | StateSet.VIEW_STATE_ENABLED);
2529         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2530                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2531                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2532 
2533         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2534         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2535                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2536         PRESSED_SELECTED_STATE_SET = StateSet.get(
2537                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2538         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2539                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2540                         | StateSet.VIEW_STATE_PRESSED);
2541         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2542                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2543         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2544                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2545                         | StateSet.VIEW_STATE_PRESSED);
2546         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2547                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2548                         | StateSet.VIEW_STATE_PRESSED);
2549         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2550                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2551                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2552         PRESSED_ENABLED_STATE_SET = StateSet.get(
2553                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2554         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2555                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2556                         | StateSet.VIEW_STATE_PRESSED);
2557         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2558                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2559                         | StateSet.VIEW_STATE_PRESSED);
2560         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2561                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2562                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2563         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2564                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2565                         | StateSet.VIEW_STATE_PRESSED);
2566         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2567                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2568                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2569         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2570                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2571                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2572         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2573                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2574                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2575                         | StateSet.VIEW_STATE_PRESSED);
2576 
2577         sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
2578         sToolkitMetricsForFrameRateDecisionFlagValue = toolkitMetricsForFrameRateDecision();
2579         sCalculateBoundsInParentFromBoundsInScreenFlagValue =
2580                 calculateBoundsInParentFromBoundsInScreen();
2581         sUseMeasureCacheDuringForceLayoutFlagValue = enableUseMeasureCacheDuringForceLayout();
2582     }
2583 
2584     /**
2585      * Accessibility event types that are dispatched for text population.
2586      */
2587     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2588             AccessibilityEvent.TYPE_VIEW_CLICKED
2589             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2590             | AccessibilityEvent.TYPE_VIEW_SELECTED
2591             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2592             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2593             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2594             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2595             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2596             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2597             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2598             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2599 
2600     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2601 
2602     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2603 
2604     /**
2605      * Temporary Rect currently for use in setBackground().  This will probably
2606      * be extended in the future to hold our own class with more than just
2607      * a Rect. :)
2608      */
2609     static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
2610 
2611     /**
2612      * Map used to store views' tags.
2613      */
2614     @UnsupportedAppUsage
2615     private SparseArray<Object> mKeyedTags;
2616 
2617     /**
2618      * The next available accessibility id.
2619      */
2620     private static int sNextAccessibilityViewId;
2621 
2622     /**
2623      * The animation currently associated with this view.
2624      * @hide
2625      */
2626     protected Animation mCurrentAnimation = null;
2627 
2628     /**
2629      * Width as measured during measure pass.
2630      * {@hide}
2631      */
2632     @ViewDebug.ExportedProperty(category = "measurement")
2633     @UnsupportedAppUsage
2634     int mMeasuredWidth;
2635 
2636     /**
2637      * Height as measured during measure pass.
2638      * {@hide}
2639      */
2640     @ViewDebug.ExportedProperty(category = "measurement")
2641     @UnsupportedAppUsage
2642     int mMeasuredHeight;
2643 
2644     /**
2645      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2646      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2647      * its display list. This flag, used only when hw accelerated, allows us to clear the
2648      * flag while retaining this information until it's needed (at getDisplayList() time and
2649      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2650      *
2651      * {@hide}
2652      */
2653     @UnsupportedAppUsage
2654     boolean mRecreateDisplayList = false;
2655 
2656     /**
2657      * The view's identifier.
2658      * {@hide}
2659      *
2660      * @see #setId(int)
2661      * @see #getId()
2662      */
2663     @IdRes
2664     @ViewDebug.ExportedProperty(resolveId = true)
2665     int mID = NO_ID;
2666 
2667     /** The ID of this view for autofill purposes.
2668      * <ul>
2669      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2670      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2671      *                                                  unique in the process. This might change
2672      *                                                  over activity lifecycle events.
2673      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2674      *                                                  unique in the activity. This stays the same
2675      *                                                  over activity lifecycle events.
2676      */
2677     private int mAutofillViewId = NO_ID;
2678 
2679     // ID for accessibility purposes. This ID must be unique for every window
2680     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2681     private int mAccessibilityViewId = NO_ID;
2682 
2683     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2684 
2685     /**
2686      * The view's tag.
2687      * {@hide}
2688      *
2689      * @see #setTag(Object)
2690      * @see #getTag()
2691      */
2692     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2693     protected Object mTag = null;
2694 
2695     /*
2696      * Masks for mPrivateFlags, as generated by dumpFlags():
2697      *
2698      * |-------|-------|-------|-------|
2699      *                                 1 PFLAG_WANTS_FOCUS
2700      *                                1  PFLAG_FOCUSED
2701      *                               1   PFLAG_SELECTED
2702      *                              1    PFLAG_IS_ROOT_NAMESPACE
2703      *                             1     PFLAG_HAS_BOUNDS
2704      *                            1      PFLAG_DRAWN
2705      *                           1       PFLAG_DRAW_ANIMATION
2706      *                          1        PFLAG_SKIP_DRAW
2707      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2708      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2709      *                      1            PFLAG_MEASURED_DIMENSION_SET
2710      *                     1             PFLAG_FORCE_LAYOUT
2711      *                    1              PFLAG_LAYOUT_REQUIRED
2712      *                   1               PFLAG_PRESSED
2713      *                  1                PFLAG_DRAWING_CACHE_VALID
2714      *                 1                 PFLAG_ANIMATION_STARTED
2715      *                1                  PFLAG_SAVE_STATE_CALLED
2716      *               1                   PFLAG_ALPHA_SET
2717      *              1                    PFLAG_SCROLL_CONTAINER
2718      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2719      *            1                      PFLAG_DIRTY
2720      *            1                      PFLAG_DIRTY_MASK
2721      *          1                        PFLAG_OPAQUE_BACKGROUND
2722      *         1                         PFLAG_OPAQUE_SCROLLBARS
2723      *         11                        PFLAG_OPAQUE_MASK
2724      *        1                          PFLAG_PREPRESSED
2725      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2726      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2727      *     1                             PFLAG_HOVERED
2728      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2729      *   1                               PFLAG_ACTIVATED
2730      *  1                                PFLAG_INVALIDATED
2731      * |-------|-------|-------|-------|
2732      */
2733     /** {@hide} */
2734     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2735     /** {@hide} */
2736     static final int PFLAG_FOCUSED                     = 0x00000002;
2737     /** {@hide} */
2738     static final int PFLAG_SELECTED                    = 0x00000004;
2739     /** {@hide} */
2740     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2741     /** {@hide} */
2742     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2743     /** {@hide} */
2744     static final int PFLAG_DRAWN                       = 0x00000020;
2745     /**
2746      * When this flag is set, this view is running an animation on behalf of its
2747      * children and should therefore not cancel invalidate requests, even if they
2748      * lie outside of this view's bounds.
2749      *
2750      * {@hide}
2751      */
2752     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2753     /** {@hide} */
2754     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2755     /** {@hide} */
2756     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2757     /** {@hide} */
2758     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2759     /** {@hide} */
2760     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2761     /** {@hide} */
2762     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2763     /** {@hide} */
2764     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2765 
2766     private static final int PFLAG_PRESSED             = 0x00004000;
2767 
2768     /** {@hide} */
2769     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2770     /**
2771      * Flag used to indicate that this view should be drawn once more (and only once
2772      * more) after its animation has completed.
2773      * {@hide}
2774      */
2775     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2776 
2777     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2778 
2779     /**
2780      * Indicates that the View returned true when onSetAlpha() was called and that
2781      * the alpha must be restored.
2782      * {@hide}
2783      */
2784     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2785 
2786     /**
2787      * Set by {@link #setScrollContainer(boolean)}.
2788      */
2789     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2790 
2791     /**
2792      * Set by {@link #setScrollContainer(boolean)}.
2793      */
2794     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2795 
2796     /**
2797      * View flag indicating whether this view was invalidated (fully or partially.)
2798      *
2799      * @hide
2800      */
2801     static final int PFLAG_DIRTY                       = 0x00200000;
2802 
2803     /**
2804      * Mask for {@link #PFLAG_DIRTY}.
2805      *
2806      * @hide
2807      */
2808     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2809 
2810     /**
2811      * Indicates whether the background is opaque.
2812      *
2813      * @hide
2814      */
2815     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2816 
2817     /**
2818      * Indicates whether the scrollbars are opaque.
2819      *
2820      * @hide
2821      */
2822     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2823 
2824     /**
2825      * Indicates whether the view is opaque.
2826      *
2827      * @hide
2828      */
2829     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2830 
2831     /**
2832      * Indicates a prepressed state;
2833      * the short time between ACTION_DOWN and recognizing
2834      * a 'real' press. Prepressed is used to recognize quick taps
2835      * even when they are shorter than ViewConfiguration.getTapTimeout().
2836      *
2837      * @hide
2838      */
2839     private static final int PFLAG_PREPRESSED          = 0x02000000;
2840 
2841     /**
2842      * Indicates whether the view is temporarily detached.
2843      *
2844      * @hide
2845      */
2846     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2847 
2848     /**
2849      * Indicates that we should awaken scroll bars once attached
2850      *
2851      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2852      * during window attachment and it is no longer needed. Feel free to repurpose it.
2853      *
2854      * @hide
2855      */
2856     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2857 
2858     /**
2859      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2860      * @hide
2861      */
2862     private static final int PFLAG_HOVERED             = 0x10000000;
2863 
2864     /**
2865      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2866      */
2867     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2868 
2869     /** {@hide} */
2870     static final int PFLAG_ACTIVATED                   = 0x40000000;
2871 
2872     /**
2873      * Indicates that this view was specifically invalidated, not just dirtied because some
2874      * child view was invalidated. The flag is used to determine when we need to recreate
2875      * a view's display list (as opposed to just returning a reference to its existing
2876      * display list).
2877      *
2878      * @hide
2879      */
2880     static final int PFLAG_INVALIDATED                 = 0x80000000;
2881 
2882     /* End of masks for mPrivateFlags */
2883 
2884     /*
2885      * Masks for mPrivateFlags2, as generated by dumpFlags():
2886      *
2887      * |-------|-------|-------|-------|
2888      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2889      *                                1  PFLAG2_DRAG_HOVERED
2890      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2891      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2892      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2893      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2894      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2895      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2896      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2897      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2898      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2899      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2900      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2901      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2902      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2903      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2904      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2905      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2906      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2907      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2908      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2909      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2910      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2911      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2912      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2913      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2914      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2915      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2916      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2917      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2918      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2919      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2920      *    1                              PFLAG2_PADDING_RESOLVED
2921      *   1                               PFLAG2_DRAWABLE_RESOLVED
2922      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2923      * |-------|-------|-------|-------|
2924      */
2925 
2926     /**
2927      * Indicates that this view has reported that it can accept the current drag's content.
2928      * Cleared when the drag operation concludes.
2929      * @hide
2930      */
2931     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2932 
2933     /**
2934      * Indicates that this view is currently directly under the drag location in a
2935      * drag-and-drop operation involving content that it can accept.  Cleared when
2936      * the drag exits the view, or when the drag operation concludes.
2937      * @hide
2938      */
2939     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2940 
2941     /** @hide */
2942     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2943             LAYOUT_DIRECTION_LTR,
2944             LAYOUT_DIRECTION_RTL,
2945             LAYOUT_DIRECTION_INHERIT,
2946             LAYOUT_DIRECTION_LOCALE
2947     })
2948     @Retention(RetentionPolicy.SOURCE)
2949     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2950     public @interface LayoutDir {}
2951 
2952     /** @hide */
2953     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2954             LAYOUT_DIRECTION_LTR,
2955             LAYOUT_DIRECTION_RTL
2956     })
2957     @Retention(RetentionPolicy.SOURCE)
2958     public @interface ResolvedLayoutDir {}
2959 
2960     /**
2961      * A flag to indicate that the layout direction of this view has not been defined yet.
2962      * @hide
2963      */
2964     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2965 
2966     /**
2967      * Horizontal layout direction of this view is from Left to Right.
2968      * Use with {@link #setLayoutDirection}.
2969      */
2970     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2971 
2972     /**
2973      * Horizontal layout direction of this view is from Right to Left.
2974      * Use with {@link #setLayoutDirection}.
2975      */
2976     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2977 
2978     /**
2979      * Horizontal layout direction of this view is inherited from its parent.
2980      * Use with {@link #setLayoutDirection}.
2981      */
2982     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2983 
2984     /**
2985      * Horizontal layout direction of this view is from deduced from the default language
2986      * script for the locale. Use with {@link #setLayoutDirection}.
2987      */
2988     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2989 
2990     /**
2991      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2992      * @hide
2993      */
2994     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2995 
2996     /**
2997      * Mask for use with private flags indicating bits used for horizontal layout direction.
2998      * @hide
2999      */
3000     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
3001 
3002     /**
3003      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
3004      * right-to-left direction.
3005      * @hide
3006      */
3007     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
3008 
3009     /**
3010      * Indicates whether the view horizontal layout direction has been resolved.
3011      * @hide
3012      */
3013     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
3014 
3015     /**
3016      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
3017      * @hide
3018      */
3019     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
3020             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
3021 
3022     /*
3023      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
3024      * flag value.
3025      * @hide
3026      */
3027     private static final int[] LAYOUT_DIRECTION_FLAGS = {
3028             LAYOUT_DIRECTION_LTR,
3029             LAYOUT_DIRECTION_RTL,
3030             LAYOUT_DIRECTION_INHERIT,
3031             LAYOUT_DIRECTION_LOCALE
3032     };
3033 
3034     /**
3035      * Default horizontal layout direction.
3036      */
3037     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
3038 
3039     /**
3040      * Default horizontal layout direction.
3041      * @hide
3042      */
3043     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
3044 
3045     /**
3046      * Text direction is inherited through {@link ViewGroup}
3047      */
3048     public static final int TEXT_DIRECTION_INHERIT = 0;
3049 
3050     /**
3051      * Text direction is using "first strong algorithm". The first strong directional character
3052      * determines the paragraph direction. If there is no strong directional character, the
3053      * paragraph direction is the view's resolved layout direction.
3054      */
3055     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
3056 
3057     /**
3058      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
3059      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
3060      * If there are neither, the paragraph direction is the view's resolved layout direction.
3061      */
3062     public static final int TEXT_DIRECTION_ANY_RTL = 2;
3063 
3064     /**
3065      * Text direction is forced to LTR.
3066      */
3067     public static final int TEXT_DIRECTION_LTR = 3;
3068 
3069     /**
3070      * Text direction is forced to RTL.
3071      */
3072     public static final int TEXT_DIRECTION_RTL = 4;
3073 
3074     /**
3075      * Text direction is coming from the system Locale.
3076      */
3077     public static final int TEXT_DIRECTION_LOCALE = 5;
3078 
3079     /**
3080      * Text direction is using "first strong algorithm". The first strong directional character
3081      * determines the paragraph direction. If there is no strong directional character, the
3082      * paragraph direction is LTR.
3083      */
3084     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
3085 
3086     /**
3087      * Text direction is using "first strong algorithm". The first strong directional character
3088      * determines the paragraph direction. If there is no strong directional character, the
3089      * paragraph direction is RTL.
3090      */
3091     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
3092 
3093     /**
3094      * Default text direction is inherited
3095      */
3096     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
3097 
3098     /**
3099      * Default resolved text direction
3100      * @hide
3101      */
3102     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
3103 
3104     /**
3105      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
3106      * @hide
3107      */
3108     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
3109 
3110     /**
3111      * Mask for use with private flags indicating bits used for text direction.
3112      * @hide
3113      */
3114     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
3115             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
3116 
3117     /**
3118      * Array of text direction flags for mapping attribute "textDirection" to correct
3119      * flag value.
3120      * @hide
3121      */
3122     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
3123             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3124             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3125             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3126             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3127             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3128             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3129             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
3130             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
3131     };
3132 
3133     /**
3134      * Indicates whether the view text direction has been resolved.
3135      * @hide
3136      */
3137     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
3138             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
3139 
3140     /**
3141      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
3142      * @hide
3143      */
3144     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
3145 
3146     /**
3147      * Mask for use with private flags indicating bits used for resolved text direction.
3148      * @hide
3149      */
3150     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
3151             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
3152 
3153     /**
3154      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
3155      * @hide
3156      */
3157     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
3158             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
3159 
3160     /** @hide */
3161     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
3162             TEXT_ALIGNMENT_INHERIT,
3163             TEXT_ALIGNMENT_GRAVITY,
3164             TEXT_ALIGNMENT_CENTER,
3165             TEXT_ALIGNMENT_TEXT_START,
3166             TEXT_ALIGNMENT_TEXT_END,
3167             TEXT_ALIGNMENT_VIEW_START,
3168             TEXT_ALIGNMENT_VIEW_END
3169     })
3170     @Retention(RetentionPolicy.SOURCE)
3171     public @interface TextAlignment {}
3172 
3173     /**
3174      * Default text alignment. The text alignment of this View is inherited from its parent.
3175      * Use with {@link #setTextAlignment(int)}
3176      */
3177     public static final int TEXT_ALIGNMENT_INHERIT = 0;
3178 
3179     /**
3180      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
3181      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
3182      *
3183      * Use with {@link #setTextAlignment(int)}
3184      */
3185     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
3186 
3187     /**
3188      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
3189      *
3190      * Use with {@link #setTextAlignment(int)}
3191      */
3192     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
3193 
3194     /**
3195      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
3196      *
3197      * Use with {@link #setTextAlignment(int)}
3198      */
3199     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
3200 
3201     /**
3202      * Center the paragraph, e.g. ALIGN_CENTER.
3203      *
3204      * Use with {@link #setTextAlignment(int)}
3205      */
3206     public static final int TEXT_ALIGNMENT_CENTER = 4;
3207 
3208     /**
3209      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
3210      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
3211      *
3212      * Use with {@link #setTextAlignment(int)}
3213      */
3214     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
3215 
3216     /**
3217      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
3218      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
3219      *
3220      * Use with {@link #setTextAlignment(int)}
3221      */
3222     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
3223 
3224     /**
3225      * Default text alignment is inherited
3226      */
3227     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3228 
3229     /**
3230      * Default resolved text alignment
3231      * @hide
3232      */
3233     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3234 
3235     /**
3236       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
3237       * @hide
3238       */
3239     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
3240 
3241     /**
3242       * Mask for use with private flags indicating bits used for text alignment.
3243       * @hide
3244       */
3245     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3246 
3247     /**
3248      * Array of text direction flags for mapping attribute "textAlignment" to correct
3249      * flag value.
3250      * @hide
3251      */
3252     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
3253             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3254             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3255             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3256             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3257             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3258             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3259             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
3260     };
3261 
3262     /**
3263      * Indicates whether the view text alignment has been resolved.
3264      * @hide
3265      */
3266     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3267 
3268     /**
3269      * Bit shift to get the resolved text alignment.
3270      * @hide
3271      */
3272     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
3273 
3274     /**
3275      * Mask for use with private flags indicating bits used for text alignment.
3276      * @hide
3277      */
3278     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
3279             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3280 
3281     /**
3282      * Indicates whether if the view text alignment has been resolved to gravity
3283      */
3284     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
3285             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3286 
3287     // Accessiblity constants for mPrivateFlags2
3288 
3289     /**
3290      * Shift for the bits in {@link #mPrivateFlags2} related to the
3291      * "importantForAccessibility" attribute.
3292      */
3293     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
3294 
3295     /**
3296      * Automatically determine whether a view is important for accessibility.
3297      */
3298     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
3299 
3300     /**
3301      * The view is important for accessibility.
3302      */
3303     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
3304 
3305     /**
3306      * The view is not important for accessibility.
3307      */
3308     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
3309 
3310     /**
3311      * The view is not important for accessibility, nor are any of its
3312      * descendant views.
3313      */
3314     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
3315 
3316     /**
3317      * The default whether the view is important for accessibility.
3318      */
3319     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3320 
3321     /**
3322      * Automatically determine whether the view should only allow interactions from
3323      * {@link android.accessibilityservice.AccessibilityService}s with the
3324      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
3325      * set to true.
3326      *
3327      * <p>
3328      * Accessibility interactions from services without {@code isAccessibilityTool} set to true are
3329      * disallowed for any of the following conditions:
3330      * <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
3331      * <li>any parent of this view returns true from {@link #isAccessibilityDataSensitive()}.</li>
3332      * </p>
3333      */
3334     public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
3335 
3336     /**
3337      * Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
3338      * with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
3339      * property set to true.
3340      */
3341     public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
3342 
3343     /**
3344      * Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
3345      * regardless of their
3346      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
3347      */
3348     public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
3349 
3350     /** @hide */
3351     @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
3352             ACCESSIBILITY_DATA_SENSITIVE_AUTO,
3353             ACCESSIBILITY_DATA_SENSITIVE_YES,
3354             ACCESSIBILITY_DATA_SENSITIVE_NO,
3355     })
3356     @Retention(RetentionPolicy.SOURCE)
3357     public @interface AccessibilityDataSensitive {}
3358 
3359     /**
3360      * Mask for obtaining the bits which specify how to determine
3361      * whether a view is important for accessibility.
3362      */
3363     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
3364         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
3365         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
3366         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3367 
3368     /**
3369      * Shift for the bits in {@link #mPrivateFlags2} related to the
3370      * "accessibilityLiveRegion" attribute.
3371      */
3372     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3373 
3374     /**
3375      * Live region mode specifying that accessibility services should not
3376      * automatically announce changes to this view. This is the default live
3377      * region mode for most views.
3378      * <p>
3379      * Use with {@link #setAccessibilityLiveRegion(int)}.
3380      */
3381     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3382 
3383     /**
3384      * Live region mode specifying that accessibility services should notify users of changes to
3385      * this view.
3386      * <p>
3387      * Use with {@link #setAccessibilityLiveRegion(int)}.
3388      */
3389     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3390 
3391     /**
3392      * Live region mode specifying that accessibility services should immediately notify users of
3393      * changes to this view. For example, a screen reader may interrupt ongoing speech to
3394      * immediately announce these changes.
3395      * <p>
3396      * Use with {@link #setAccessibilityLiveRegion(int)}.
3397      */
3398     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3399 
3400     /**
3401      * The default whether the view is important for accessibility.
3402      */
3403     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3404 
3405     /**
3406      * Mask for obtaining the bits which specify a view's accessibility live
3407      * region mode.
3408      */
3409     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3410             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3411             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3412 
3413     /**
3414      * Flag indicating whether a view has accessibility focus.
3415      */
3416     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3417 
3418     /**
3419      * Flag whether the accessibility state of the subtree rooted at this view changed.
3420      */
3421     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3422 
3423     /**
3424      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3425      * is used to check whether later changes to the view's transform should invalidate the
3426      * view to force the quickReject test to run again.
3427      */
3428     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3429 
3430     /**
3431      * Flag indicating that start/end padding has been resolved into left/right padding
3432      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3433      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3434      * during measurement. In some special cases this is required such as when an adapter-based
3435      * view measures prospective children without attaching them to a window.
3436      */
3437     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3438 
3439     /**
3440      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3441      */
3442     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3443 
3444     /**
3445      * Indicates that the view is tracking some sort of transient state
3446      * that the app should not need to be aware of, but that the framework
3447      * should take special care to preserve.
3448      */
3449     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3450 
3451     /**
3452      * Group of bits indicating that RTL properties resolution is done.
3453      */
3454     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3455             PFLAG2_TEXT_DIRECTION_RESOLVED |
3456             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3457             PFLAG2_PADDING_RESOLVED |
3458             PFLAG2_DRAWABLE_RESOLVED;
3459 
3460     // There are a couple of flags left in mPrivateFlags2
3461 
3462     /* End of masks for mPrivateFlags2 */
3463 
3464     /*
3465      * Masks for mPrivateFlags3, as generated by dumpFlags():
3466      *
3467      * |-------|-------|-------|-------|
3468      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3469      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3470      *                               1   PFLAG3_IS_LAID_OUT
3471      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3472      *                             1     PFLAG3_CALLED_SUPER
3473      *                            1      PFLAG3_APPLYING_INSETS
3474      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3475      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3476      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3477      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3478      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3479      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3480      *                     1             PFLAG3_SCROLL_INDICATOR_START
3481      *                    1              PFLAG3_SCROLL_INDICATOR_END
3482      *                   1               PFLAG3_ASSIST_BLOCKED
3483      *                  1                PFLAG3_CLUSTER
3484      *                 1                 PFLAG3_IS_AUTOFILLED
3485      *                1                  PFLAG3_FINGER_DOWN
3486      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3487      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3488      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3489      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3490      *        1                          PFLAG3_TEMPORARY_DETACH
3491      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3492      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3493      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3494      *    1                              PFLAG3_AGGREGATED_VISIBLE
3495      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3496      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3497      * |-------|-------|-------|-------|
3498      */
3499 
3500     /**
3501      * Flag indicating that view has a transform animation set on it. This is used to track whether
3502      * an animation is cleared between successive frames, in order to tell the associated
3503      * DisplayList to clear its animation matrix.
3504      */
3505     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3506 
3507     /**
3508      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3509      * animation is cleared between successive frames, in order to tell the associated
3510      * DisplayList to restore its alpha value.
3511      */
3512     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3513 
3514     /**
3515      * Flag indicating that the view has been through at least one layout since it
3516      * was last attached to a window.
3517      */
3518     static final int PFLAG3_IS_LAID_OUT = 0x4;
3519 
3520     /**
3521      * Flag indicating that a call to measure() was skipped and should be done
3522      * instead when layout() is invoked.
3523      */
3524     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3525 
3526     /**
3527      * Flag indicating that an overridden method correctly called down to
3528      * the superclass implementation as required by the API spec.
3529      */
3530     static final int PFLAG3_CALLED_SUPER = 0x10;
3531 
3532     /**
3533      * Flag indicating that we're in the process of applying window insets.
3534      */
3535     static final int PFLAG3_APPLYING_INSETS = 0x20;
3536 
3537     /**
3538      * Flag indicating that we're in the process of fitting system windows using the old method.
3539      */
3540     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3541 
3542     /**
3543      * Flag indicating that nested scrolling is enabled for this view.
3544      * The view will optionally cooperate with views up its parent chain to allow for
3545      * integrated nested scrolling along the same axis.
3546      */
3547     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3548 
3549     /**
3550      * Flag indicating that the bottom scroll indicator should be displayed
3551      * when this view can scroll up.
3552      */
3553     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3554 
3555     /**
3556      * Flag indicating that the bottom scroll indicator should be displayed
3557      * when this view can scroll down.
3558      */
3559     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3560 
3561     /**
3562      * Flag indicating that the left scroll indicator should be displayed
3563      * when this view can scroll left.
3564      */
3565     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3566 
3567     /**
3568      * Flag indicating that the right scroll indicator should be displayed
3569      * when this view can scroll right.
3570      */
3571     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3572 
3573     /**
3574      * Flag indicating that the start scroll indicator should be displayed
3575      * when this view can scroll in the start direction.
3576      */
3577     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3578 
3579     /**
3580      * Flag indicating that the end scroll indicator should be displayed
3581      * when this view can scroll in the end direction.
3582      */
3583     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3584 
3585     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3586 
3587     static final int SCROLL_INDICATORS_NONE = 0x0000;
3588 
3589     /**
3590      * Mask for use with setFlags indicating bits used for indicating which
3591      * scroll indicators are enabled.
3592      */
3593     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3594             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3595             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3596             | PFLAG3_SCROLL_INDICATOR_END;
3597 
3598     /**
3599      * Left-shift required to translate between public scroll indicator flags
3600      * and internal PFLAGS3 flags. When used as a right-shift, translates
3601      * PFLAGS3 flags to public flags.
3602      */
3603     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3604 
3605     /** @hide */
3606     @Retention(RetentionPolicy.SOURCE)
3607     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3608             SCROLL_INDICATOR_TOP,
3609             SCROLL_INDICATOR_BOTTOM,
3610             SCROLL_INDICATOR_LEFT,
3611             SCROLL_INDICATOR_RIGHT,
3612             SCROLL_INDICATOR_START,
3613             SCROLL_INDICATOR_END,
3614     })
3615     public @interface ScrollIndicators {}
3616 
3617     /**
3618      * Scroll indicator direction for the top edge of the view.
3619      *
3620      * @see #setScrollIndicators(int)
3621      * @see #setScrollIndicators(int, int)
3622      * @see #getScrollIndicators()
3623      */
3624     public static final int SCROLL_INDICATOR_TOP =
3625             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3626 
3627     /**
3628      * Scroll indicator direction for the bottom edge of the view.
3629      *
3630      * @see #setScrollIndicators(int)
3631      * @see #setScrollIndicators(int, int)
3632      * @see #getScrollIndicators()
3633      */
3634     public static final int SCROLL_INDICATOR_BOTTOM =
3635             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3636 
3637     /**
3638      * Scroll indicator direction for the left edge of the view.
3639      *
3640      * @see #setScrollIndicators(int)
3641      * @see #setScrollIndicators(int, int)
3642      * @see #getScrollIndicators()
3643      */
3644     public static final int SCROLL_INDICATOR_LEFT =
3645             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3646 
3647     /**
3648      * Scroll indicator direction for the right edge of the view.
3649      *
3650      * @see #setScrollIndicators(int)
3651      * @see #setScrollIndicators(int, int)
3652      * @see #getScrollIndicators()
3653      */
3654     public static final int SCROLL_INDICATOR_RIGHT =
3655             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3656 
3657     /**
3658      * Scroll indicator direction for the starting edge of the view.
3659      * <p>
3660      * Resolved according to the view's layout direction, see
3661      * {@link #getLayoutDirection()} for more information.
3662      *
3663      * @see #setScrollIndicators(int)
3664      * @see #setScrollIndicators(int, int)
3665      * @see #getScrollIndicators()
3666      */
3667     public static final int SCROLL_INDICATOR_START =
3668             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3669 
3670     /**
3671      * Scroll indicator direction for the ending edge of the view.
3672      * <p>
3673      * Resolved according to the view's layout direction, see
3674      * {@link #getLayoutDirection()} for more information.
3675      *
3676      * @see #setScrollIndicators(int)
3677      * @see #setScrollIndicators(int, int)
3678      * @see #getScrollIndicators()
3679      */
3680     public static final int SCROLL_INDICATOR_END =
3681             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3682 
3683     /**
3684      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3685      * into this view.<p>
3686      */
3687     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3688 
3689     /**
3690      * Flag indicating that the view is a root of a keyboard navigation cluster.
3691      *
3692      * @see #isKeyboardNavigationCluster()
3693      * @see #setKeyboardNavigationCluster(boolean)
3694      */
3695     private static final int PFLAG3_CLUSTER = 0x8000;
3696 
3697     /**
3698      * Flag indicating that the view is autofilled
3699      *
3700      * @see #isAutofilled()
3701      * @see #setAutofilled(boolean, boolean)
3702      */
3703     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3704 
3705     /**
3706      * Indicates that the user is currently touching the screen.
3707      * Currently used for the tooltip positioning only.
3708      */
3709     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3710 
3711     /**
3712      * Flag indicating that this view is the default-focus view.
3713      *
3714      * @see #isFocusedByDefault()
3715      * @see #setFocusedByDefault(boolean)
3716      */
3717     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3718 
3719     /**
3720      * Shift for the bits in {@link #mPrivateFlags3} related to the
3721      * "importantForAutofill" attribute.
3722      */
3723     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3724 
3725     /**
3726      * Mask for obtaining the bits which specify how to determine
3727      * whether a view is important for autofill.
3728      */
3729     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3730             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3731             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3732             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3733             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3734 
3735     /**
3736      * Whether this view has rendered elements that overlap (see {@link
3737      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3738      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3739      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3740      * determined by whatever {@link #hasOverlappingRendering()} returns.
3741      */
3742     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3743 
3744     /**
3745      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3746      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3747      */
3748     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3749 
3750     /**
3751      * Flag indicating that the view is temporarily detached from the parent view.
3752      *
3753      * @see #onStartTemporaryDetach()
3754      * @see #onFinishTemporaryDetach()
3755      */
3756     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3757 
3758     /**
3759      * Flag indicating that the view does not wish to be revealed within its parent
3760      * hierarchy when it gains focus. Expressed in the negative since the historical
3761      * default behavior is to reveal on focus; this flag suppresses that behavior.
3762      *
3763      * @see #setRevealOnFocusHint(boolean)
3764      * @see #getRevealOnFocusHint()
3765      */
3766     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3767 
3768     /**
3769      * Flag indicating that when layout is completed we should notify
3770      * that the view was entered for autofill purposes. To minimize
3771      * showing autofill for views not visible to the user we evaluate
3772      * user visibility which cannot be done until the view is laid out.
3773      */
3774     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3775 
3776     /**
3777      * Works like focusable for screen readers, but without the side effects on input focus.
3778      * @see #setScreenReaderFocusable(boolean)
3779      */
3780     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3781 
3782     /**
3783      * The last aggregated visibility. Used to detect when it truly changes.
3784      */
3785     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3786 
3787     /**
3788      * Used to indicate that {@link #mAutofillId} was explicitly set through
3789      * {@link #setAutofillId(AutofillId)}.
3790      */
3791     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3792 
3793     /**
3794      * Indicates if the View is a heading for accessibility purposes
3795      */
3796     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3797 
3798     /* End of masks for mPrivateFlags3 */
3799 
3800     /*
3801      * Masks for mPrivateFlags4, as generated by dumpFlags():
3802      *
3803      * |-------|-------|-------|-------|
3804      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3805      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3806      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3807      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3808      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3809      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3810      *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
3811      *                       1          PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
3812      *                     11           PFLAG4_SCROLL_CAPTURE_HINT_MASK
3813      *                    1             PFLAG4_ALLOW_CLICK_WHEN_DISABLED
3814      *                   1              PFLAG4_DETACHED
3815      *                  1               PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
3816      *                 1                PFLAG4_DRAG_A11Y_STARTED
3817      *                1                 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
3818      *               1                  PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER
3819      *              1                   PFLAG4_TRAVERSAL_TRACING_ENABLED
3820      *             1                    PFLAG4_RELAYOUT_TRACING_ENABLED
3821      *            1                     PFLAG4_ROTARY_HAPTICS_DETERMINED
3822      *           1                      PFLAG4_ROTARY_HAPTICS_ENABLED
3823      *          1                       PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT
3824      *         1                        PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT
3825      *       11                         PFLAG4_CONTENT_SENSITIVITY_MASK
3826      *      1                           PFLAG4_IS_COUNTED_AS_SENSITIVE
3827      *     1                            PFLAG4_HAS_DRAWN
3828      *    1                             PFLAG4_HAS_MOVED
3829      *   1                              PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION
3830      *  1                               PFLAG4_FORCED_OVERRIDE_FRAME_RATE
3831      * 1                                PFLAG4_SELF_REQUESTED_FRAME_RATE
3832      * |-------|-------|-------|-------|
3833      */
3834 
3835     /**
3836      * Mask for obtaining the bits which specify how to determine
3837      * whether a view is important for autofill.
3838      *
3839      * <p>NOTE: the important for content capture values were the first flags added and are set in
3840      * the rightmost position, so we don't need to shift them
3841      */
3842     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3843             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3844             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3845             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3846             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3847 
3848     /*
3849      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3850      * should be called.
3851      *
3852      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3853      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3854      */
3855     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3856     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3857 
3858     /*
3859      * Flags used to cache the value returned by isImportantForContentCapture while the view
3860      * hierarchy is being traversed.
3861      */
3862     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3863     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3864 
3865     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3866             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3867             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3868 
3869     /**
3870      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3871      */
3872     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3873 
3874     /**
3875      * Flag indicating the field should not have yellow highlight when autofilled.
3876      */
3877     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3878 
3879     /**
3880      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3881      */
3882     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3883 
3884     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3885             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3886             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3887 
3888     /**
3889      * Indicates if the view can receive click events when disabled.
3890      */
3891     private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
3892 
3893     /**
3894      * Indicates if the view is just detached.
3895      */
3896     private static final int PFLAG4_DETACHED = 0x000002000;
3897 
3898     /**
3899      * Indicates that the view has transient state because the system is translating it.
3900      */
3901     private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
3902 
3903     /**
3904      * Indicates that the view has started a drag with {@link AccessibilityAction#ACTION_DRAG_START}
3905      */
3906     private static final int PFLAG4_DRAG_A11Y_STARTED = 0x000008000;
3907 
3908     /**
3909      * Indicates that the view enables auto handwriting initiation.
3910      */
3911     private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
3912 
3913     /**
3914      * Indicates that the view is important for Credential Manager.
3915      */
3916     private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000;
3917 
3918     /**
3919      * When set, measure and layout passes of this view will be logged with {@link Trace}, so we
3920      * can better debug jank due to complex view hierarchies.
3921      */
3922     private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
3923 
3924     /**
3925      * When set, emits a {@link Trace} instant event and stacktrace every time a requestLayout of
3926      * this class happens.
3927      */
3928     private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
3929 
3930     /** Indicates if rotary scroll haptics support for the view has been determined. */
3931     private static final int PFLAG4_ROTARY_HAPTICS_DETERMINED = 0x100000;
3932 
3933     /**
3934      * Indicates if rotary scroll haptics is enabled for this view.
3935      * The source of truth for this info is a ViewConfiguration API; this bit only caches the value.
3936      */
3937     private static final int PFLAG4_ROTARY_HAPTICS_ENABLED = 0x200000;
3938 
3939     /** Indicates if there has been a scroll event since the last rotary input. */
3940     private static final int PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT = 0x400000;
3941 
3942     /**
3943      * Indicates if there has been a rotary input that may generate a scroll event.
3944      * This flag is important so that a scroll event can be properly attributed to a rotary input.
3945      */
3946     private static final int PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT = 0x800000;
3947 
3948     private static final int PFLAG4_CONTENT_SENSITIVITY_SHIFT = 24;
3949 
3950     /**
3951      * Mask for obtaining the bits which specify how to determine whether a view
3952      * displays sensitive content or not.
3953      */
3954     private static final int PFLAG4_CONTENT_SENSITIVITY_MASK =
3955             (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE
3956                     | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT;
3957 
3958     /**
3959      * Whether this view has been counted as a sensitive view or not.
3960      *
3961      * @see AttachInfo#mSensitiveViewsCount
3962      */
3963     private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000;
3964 
3965     /**
3966      * Whether this view has been drawn once with updateDisplayListIfDirty() or not.
3967      * Used by VRR to for quick detection of scrolling.
3968      */
3969     private static final int PFLAG4_HAS_DRAWN = 0x8000000;
3970 
3971     /**
3972      * Whether this view has been moved with either setTranslationX/Y or setLeft/Top.
3973      * Used by VRR to for quick detection of scrolling.
3974      */
3975     private static final int PFLAG4_HAS_MOVED = 0x10000000;
3976 
3977     /**
3978      * Whether the invalidateViewProperty is involked at current frame.
3979      */
3980     private static final int PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION = 0x20000000;
3981 
3982     /**
3983      * When set, this indicates whether the frame rate of the children should be
3984      * forcibly overridden, even if it has been explicitly configured by a user request.
3985      */
3986     private static final int PFLAG4_FORCED_OVERRIDE_FRAME_RATE = 0x40000000;
3987 
3988     /**
3989      * When set, this indicates that the frame rate is configured based on a user request.
3990      */
3991     private static final int PFLAG4_SELF_REQUESTED_FRAME_RATE = 0x80000000;
3992 
3993     /* End of masks for mPrivateFlags4 */
3994 
3995     /** @hide */
3996     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3997     /** @hide */
3998     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3999     /** @hide */
4000     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
4001 
4002     /** @hide */
4003     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
4004             VIEW_STRUCTURE_FOR_ASSIST,
4005             VIEW_STRUCTURE_FOR_AUTOFILL,
4006             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
4007     })
4008     @Retention(RetentionPolicy.SOURCE)
4009     public @interface ViewStructureType {}
4010 
4011     /**
4012      * Always allow a user to over-scroll this view, provided it is a
4013      * view that can scroll.
4014      *
4015      * @see #getOverScrollMode()
4016      * @see #setOverScrollMode(int)
4017      */
4018     public static final int OVER_SCROLL_ALWAYS = 0;
4019 
4020     /**
4021      * Allow a user to over-scroll this view only if the content is large
4022      * enough to meaningfully scroll, provided it is a view that can scroll.
4023      *
4024      * @see #getOverScrollMode()
4025      * @see #setOverScrollMode(int)
4026      */
4027     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
4028 
4029     /**
4030      * Never allow a user to over-scroll this view.
4031      *
4032      * @see #getOverScrollMode()
4033      * @see #setOverScrollMode(int)
4034      */
4035     public static final int OVER_SCROLL_NEVER = 2;
4036 
4037     /**
4038      * Special constant for {@link #setSystemUiVisibility(int)}: View has
4039      * requested the system UI (status bar) to be visible (the default).
4040      *
4041      * @see #setSystemUiVisibility(int)
4042      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
4043      * instead.
4044      */
4045     @Deprecated
4046     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
4047 
4048     /**
4049      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
4050      * system UI to enter an unobtrusive "low profile" mode.
4051      *
4052      * <p>This is for use in games, book readers, video players, or any other
4053      * "immersive" application where the usual system chrome is deemed too distracting.
4054      *
4055      * <p>In low profile mode, the status bar and/or navigation icons may dim.
4056      *
4057      * @see #setSystemUiVisibility(int)
4058      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
4059      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
4060      * {@link Type#systemBars()}.
4061      */
4062     @Deprecated
4063     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
4064 
4065     /**
4066      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
4067      * system navigation be temporarily hidden.
4068      *
4069      * <p>This is an even less obtrusive state than that called for by
4070      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
4071      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
4072      * those to disappear. This is useful (in conjunction with the
4073      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
4074      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
4075      * window flags) for displaying content using every last pixel on the display.
4076      *
4077      * <p>There is a limitation: because navigation controls are so important, the least user
4078      * interaction will cause them to reappear immediately.  When this happens, both
4079      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
4080      * so that both elements reappear at the same time.
4081      *
4082      * @see #setSystemUiVisibility(int)
4083      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
4084      * instead.
4085      */
4086     @Deprecated
4087     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
4088 
4089     /**
4090      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
4091      * into the normal fullscreen mode so that its content can take over the screen
4092      * while still allowing the user to interact with the application.
4093      *
4094      * <p>This has the same visual effect as
4095      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
4096      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
4097      * meaning that non-critical screen decorations (such as the status bar) will be
4098      * hidden while the user is in the View's window, focusing the experience on
4099      * that content.  Unlike the window flag, if you are using ActionBar in
4100      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
4101      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
4102      * hide the action bar.
4103      *
4104      * <p>This approach to going fullscreen is best used over the window flag when
4105      * it is a transient state -- that is, the application does this at certain
4106      * points in its user interaction where it wants to allow the user to focus
4107      * on content, but not as a continuous state.  For situations where the application
4108      * would like to simply stay full screen the entire time (such as a game that
4109      * wants to take over the screen), the
4110      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
4111      * is usually a better approach.  The state set here will be removed by the system
4112      * in various situations (such as the user moving to another application) like
4113      * the other system UI states.
4114      *
4115      * <p>When using this flag, the application should provide some easy facility
4116      * for the user to go out of it.  A common example would be in an e-book
4117      * reader, where tapping on the screen brings back whatever screen and UI
4118      * decorations that had been hidden while the user was immersed in reading
4119      * the book.
4120      *
4121      * @see #setSystemUiVisibility(int)
4122      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
4123      * instead.
4124      */
4125     @Deprecated
4126     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
4127 
4128     /**
4129      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
4130      * flags, we would like a stable view of the content insets given to
4131      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
4132      * will always represent the worst case that the application can expect
4133      * as a continuous state.  In the stock Android UI this is the space for
4134      * the system bar, nav bar, and status bar, but not more transient elements
4135      * such as an input method.
4136      *
4137      * The stable layout your UI sees is based on the system UI modes you can
4138      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
4139      * then you will get a stable layout for changes of the
4140      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
4141      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
4142      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
4143      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
4144      * with a stable layout.  (Note that you should avoid using
4145      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
4146      *
4147      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
4148      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
4149      * then a hidden status bar will be considered a "stable" state for purposes
4150      * here.  This allows your UI to continually hide the status bar, while still
4151      * using the system UI flags to hide the action bar while still retaining
4152      * a stable layout.  Note that changing the window fullscreen flag will never
4153      * provide a stable layout for a clean transition.
4154      *
4155      * <p>If you are using ActionBar in
4156      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
4157      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
4158      * insets it adds to those given to the application.
4159      *
4160      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
4161      * insets that don't change when system bars change visibility state.
4162      */
4163     @Deprecated
4164     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
4165 
4166     /**
4167      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
4168      * to be laid out as if it has requested
4169      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
4170      * allows it to avoid artifacts when switching in and out of that mode, at
4171      * the expense that some of its user interface may be covered by screen
4172      * decorations when they are shown.  You can perform layout of your inner
4173      * UI elements to account for the navigation system UI through the
4174      * {@link #fitSystemWindows(Rect)} method.
4175      *
4176      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
4177      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
4178      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
4179      */
4180     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
4181 
4182     /**
4183      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
4184      * to be laid out as if it has requested
4185      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
4186      * allows it to avoid artifacts when switching in and out of that mode, at
4187      * the expense that some of its user interface may be covered by screen
4188      * decorations when they are shown.  You can perform layout of your inner
4189      * UI elements to account for non-fullscreen system UI through the
4190      * {@link #fitSystemWindows(Rect)} method.
4191      *
4192      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
4193      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
4194      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
4195      *  layoutInDisplayCutoutMode} is
4196      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
4197      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
4198      *
4199      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
4200      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
4201      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
4202      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
4203      *
4204      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
4205      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
4206      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
4207      */
4208     @Deprecated
4209     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
4210 
4211     /**
4212      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
4213      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
4214      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
4215      * user interaction.
4216      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
4217      * has an effect when used in combination with that flag.</p>
4218      *
4219      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_DEFAULT} instead.
4220      */
4221     @Deprecated
4222     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
4223 
4224     /**
4225      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
4226      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
4227      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
4228      * experience while also hiding the system bars.  If this flag is not set,
4229      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
4230      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
4231      * if the user swipes from the top of the screen.
4232      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
4233      * system gestures, such as swiping from the top of the screen.  These transient system bars
4234      * will overlay app's content, may have some degree of transparency, and will automatically
4235      * hide after a short timeout.
4236      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
4237      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
4238      * with one or both of those flags.</p>
4239      *
4240      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
4241      */
4242     @Deprecated
4243     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
4244 
4245     /**
4246      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
4247      * is compatible with light status bar backgrounds.
4248      *
4249      * <p>For this to take effect, the window must request
4250      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
4251      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
4252      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
4253      *         FLAG_TRANSLUCENT_STATUS}.
4254      *
4255      * @see android.R.attr#windowLightStatusBar
4256      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
4257      */
4258     @Deprecated
4259     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
4260 
4261     /**
4262      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
4263      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
4264      */
4265     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
4266 
4267     /**
4268      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
4269      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
4270      */
4271     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
4272 
4273     /**
4274      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
4275      * that is compatible with light navigation bar backgrounds.
4276      *
4277      * <p>For this to take effect, the window must request
4278      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
4279      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
4280      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
4281      *         FLAG_TRANSLUCENT_NAVIGATION}.
4282      *
4283      * @see android.R.attr#windowLightNavigationBar
4284      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
4285      */
4286     @Deprecated
4287     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
4288 
4289     /**
4290      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
4291      */
4292     @Deprecated
4293     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
4294 
4295     /**
4296      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
4297      */
4298     @Deprecated
4299     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
4300 
4301     /**
4302      * @hide
4303      *
4304      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4305      * out of the public fields to keep the undefined bits out of the developer's way.
4306      *
4307      * Flag to make the status bar not expandable.  Unless you also
4308      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
4309      */
4310     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4311     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
4312 
4313     /**
4314      * @hide
4315      *
4316      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4317      * out of the public fields to keep the undefined bits out of the developer's way.
4318      *
4319      * Flag to hide notification icons and scrolling ticker text.
4320      */
4321     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
4322 
4323     /**
4324      * @hide
4325      *
4326      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4327      * out of the public fields to keep the undefined bits out of the developer's way.
4328      *
4329      * Flag to disable incoming notification alerts.  This will not block
4330      * icons, but it will block sound, vibrating and other visual or aural notifications.
4331      */
4332     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
4333 
4334     /**
4335      * @hide
4336      *
4337      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4338      * out of the public fields to keep the undefined bits out of the developer's way.
4339      *
4340      * Flag to hide only the scrolling ticker.  Note that
4341      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
4342      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
4343      */
4344     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
4345 
4346     /**
4347      * @hide
4348      *
4349      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4350      * out of the public fields to keep the undefined bits out of the developer's way.
4351      *
4352      * Flag to hide the center system info area.
4353      */
4354     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
4355 
4356     /**
4357      * @hide
4358      *
4359      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4360      * out of the public fields to keep the undefined bits out of the developer's way.
4361      *
4362      * Flag to hide only the home button.  Don't use this
4363      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4364      */
4365     @UnsupportedAppUsage
4366     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
4367 
4368     /**
4369      * @hide
4370      *
4371      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4372      * out of the public fields to keep the undefined bits out of the developer's way.
4373      *
4374      * Flag to hide only the back button. Don't use this
4375      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4376      */
4377     @UnsupportedAppUsage
4378     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
4379 
4380     /**
4381      * @hide
4382      *
4383      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4384      * out of the public fields to keep the undefined bits out of the developer's way.
4385      *
4386      * Flag to hide only the clock.  You might use this if your activity has
4387      * its own clock making the status bar's clock redundant.
4388      */
4389     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
4390 
4391     /**
4392      * @hide
4393      *
4394      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4395      * out of the public fields to keep the undefined bits out of the developer's way.
4396      *
4397      * Flag to hide only the recent apps button. Don't use this
4398      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4399      */
4400     @UnsupportedAppUsage
4401     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
4402 
4403     /**
4404      * @hide
4405      *
4406      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4407      * out of the public fields to keep the undefined bits out of the developer's way.
4408      *
4409      * Flag to disable the global search gesture. Don't use this
4410      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4411      */
4412     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
4413 
4414     /**
4415      * @hide
4416      *
4417      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4418      * out of the public fields to keep the undefined bits out of the developer's way.
4419      *
4420      * Flag to disable the ongoing call chip.
4421      */
4422     public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
4423 
4424     /**
4425      * @hide
4426      */
4427     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4428 
4429     /**
4430      * These are the system UI flags that can be cleared by events outside
4431      * of an application.  Currently this is just the ability to tap on the
4432      * screen while hiding the navigation bar to have it return.
4433      * @hide
4434      */
4435     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4436             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4437             | SYSTEM_UI_FLAG_FULLSCREEN;
4438 
4439     /**
4440      * Flags that can impact the layout in relation to system UI.
4441      *
4442      * @deprecated System UI layout flags are deprecated.
4443      */
4444     @Deprecated
4445     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4446             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4447             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4448 
4449     /** @hide */
4450     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4451             FIND_VIEWS_WITH_TEXT,
4452             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4453     })
4454     @Retention(RetentionPolicy.SOURCE)
4455     public @interface FindViewFlags {}
4456 
4457     /**
4458      * Find views that render the specified text.
4459      *
4460      * @see #findViewsWithText(ArrayList, CharSequence, int)
4461      */
4462     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4463 
4464     /**
4465      * Find find views that contain the specified content description.
4466      *
4467      * @see #findViewsWithText(ArrayList, CharSequence, int)
4468      */
4469     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4470 
4471     /**
4472      * Find views that contain {@link AccessibilityNodeProvider}. Such
4473      * a View is a root of virtual view hierarchy and may contain the searched
4474      * text. If this flag is set Views with providers are automatically
4475      * added and it is a responsibility of the client to call the APIs of
4476      * the provider to determine whether the virtual tree rooted at this View
4477      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4478      * representing the virtual views with this text.
4479      *
4480      * @see #findViewsWithText(ArrayList, CharSequence, int)
4481      *
4482      * @hide
4483      */
4484     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4485 
4486     /**
4487      * The undefined cursor position.
4488      *
4489      * @hide
4490      */
4491     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4492 
4493     /**
4494      * Indicates that the screen has changed state and is now off.
4495      *
4496      * @see #onScreenStateChanged(int)
4497      */
4498     public static final int SCREEN_STATE_OFF = 0x0;
4499 
4500     /**
4501      * Indicates that the screen has changed state and is now on.
4502      *
4503      * @see #onScreenStateChanged(int)
4504      */
4505     public static final int SCREEN_STATE_ON = 0x1;
4506 
4507     /**
4508      * Indicates no axis of view scrolling.
4509      */
4510     public static final int SCROLL_AXIS_NONE = 0;
4511 
4512     /**
4513      * Indicates scrolling along the horizontal axis.
4514      */
4515     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4516 
4517     /**
4518      * Indicates scrolling along the vertical axis.
4519      */
4520     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4521 
4522     /**
4523      * Controls the over-scroll mode for this view.
4524      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4525      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4526      * and {@link #OVER_SCROLL_NEVER}.
4527      */
4528     private int mOverScrollMode;
4529 
4530     /**
4531      * The parent this view is attached to.
4532      * {@hide}
4533      *
4534      * @see #getParent()
4535      */
4536     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4537     protected ViewParent mParent;
4538 
4539     /**
4540      * {@hide}
4541      *
4542      * Not available for general use. If you need help, hang up and then dial one of the following
4543      * public APIs:
4544      *
4545      * @see #isAttachedToWindow() for current attach state
4546      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4547      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4548      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4549      * @see #getHandler() for posting messages to this view's UI thread/looper
4550      * @see #getParent() for interacting with the parent chain
4551      * @see #getWindowToken() for the current window token
4552      * @see #getRootView() for the view at the root of the attached hierarchy
4553      * @see #getDisplay() for the Display this view is presented on
4554      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4555      * @see #hasWindowFocus() for whether the attached window is currently focused
4556      * @see #getWindowVisibility() for checking the visibility of the attached window
4557      */
4558     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4559     AttachInfo mAttachInfo;
4560 
4561     /**
4562      * {@hide}
4563      */
4564     @ViewDebug.ExportedProperty(flagMapping = {
4565         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4566                 name = "FORCE_LAYOUT"),
4567         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4568                 name = "LAYOUT_REQUIRED"),
4569         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4570             name = "DRAWING_CACHE_INVALID", outputIf = false),
4571         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4572         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4573         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4574     }, formatToHexString = true)
4575 
4576     /* @hide */
4577     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4578     public int mPrivateFlags;
4579     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4580     int mPrivateFlags2;
4581     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4582     int mPrivateFlags3;
4583 
4584     private int mPrivateFlags4;
4585 
4586     /**
4587      * This view's request for the visibility of the status bar.
4588      * @hide
4589      */
4590     @ViewDebug.ExportedProperty(flagMapping = {
4591             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4592                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4593                     name = "LOW_PROFILE"),
4594             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4595                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4596                     name = "HIDE_NAVIGATION"),
4597             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4598                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4599                     name = "FULLSCREEN"),
4600             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4601                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4602                     name = "LAYOUT_STABLE"),
4603             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4604                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4605                     name = "LAYOUT_HIDE_NAVIGATION"),
4606             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4607                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4608                     name = "LAYOUT_FULLSCREEN"),
4609             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4610                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4611                     name = "IMMERSIVE"),
4612             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4613                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4614                     name = "IMMERSIVE_STICKY"),
4615             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4616                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4617                     name = "LIGHT_STATUS_BAR"),
4618             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4619                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4620                     name = "LIGHT_NAVIGATION_BAR"),
4621             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4622                     equals = STATUS_BAR_DISABLE_EXPAND,
4623                     name = "STATUS_BAR_DISABLE_EXPAND"),
4624             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4625                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4626                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4627             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4628                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4629                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4630             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4631                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4632                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4633             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4634                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4635                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4636             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4637                     equals = STATUS_BAR_DISABLE_HOME,
4638                     name = "STATUS_BAR_DISABLE_HOME"),
4639             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4640                     equals = STATUS_BAR_DISABLE_BACK,
4641                     name = "STATUS_BAR_DISABLE_BACK"),
4642             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4643                     equals = STATUS_BAR_DISABLE_CLOCK,
4644                     name = "STATUS_BAR_DISABLE_CLOCK"),
4645             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4646                     equals = STATUS_BAR_DISABLE_RECENT,
4647                     name = "STATUS_BAR_DISABLE_RECENT"),
4648             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4649                     equals = STATUS_BAR_DISABLE_SEARCH,
4650                     name = "STATUS_BAR_DISABLE_SEARCH"),
4651             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4652                     equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4653                     name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
4654     }, formatToHexString = true)
4655     @SystemUiVisibility
4656     int mSystemUiVisibility;
4657 
4658     /**
4659      * @hide
4660      */
4661     @IntDef(flag = true, prefix = "", value = {
4662             SYSTEM_UI_FLAG_LOW_PROFILE,
4663             SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4664             SYSTEM_UI_FLAG_FULLSCREEN,
4665             SYSTEM_UI_FLAG_LAYOUT_STABLE,
4666             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4667             SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4668             SYSTEM_UI_FLAG_IMMERSIVE,
4669             SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4670             SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4671             SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4672             STATUS_BAR_DISABLE_EXPAND,
4673             STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4674             STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4675             STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4676             STATUS_BAR_DISABLE_SYSTEM_INFO,
4677             STATUS_BAR_DISABLE_HOME,
4678             STATUS_BAR_DISABLE_BACK,
4679             STATUS_BAR_DISABLE_CLOCK,
4680             STATUS_BAR_DISABLE_RECENT,
4681             STATUS_BAR_DISABLE_SEARCH,
4682             STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4683     })
4684     @Retention(RetentionPolicy.SOURCE)
4685     public @interface SystemUiVisibility {}
4686 
4687     /**
4688      * Reference count for transient state.
4689      * @see #setHasTransientState(boolean)
4690      */
4691     int mTransientStateCount = 0;
4692 
4693     /**
4694      * Count of how many windows this view has been attached to.
4695      */
4696     int mWindowAttachCount;
4697 
4698     /**
4699      * The layout parameters associated with this view and used by the parent
4700      * {@link android.view.ViewGroup} to determine how this view should be
4701      * laid out.
4702      *
4703      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4704      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4705      * state correctness of the class.
4706      * {@hide}
4707      */
4708     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4709     protected ViewGroup.LayoutParams mLayoutParams;
4710 
4711     /**
4712      * The view flags hold various views states.
4713      *
4714      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4715      * triggering updates.
4716      * {@hide}
4717      */
4718     @ViewDebug.ExportedProperty(formatToHexString = true)
4719     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4720     int mViewFlags;
4721 
4722     static class TransformationInfo {
4723         /**
4724          * The transform matrix for the View. This transform is calculated internally
4725          * based on the translation, rotation, and scale properties.
4726          *
4727          * Do *not* use this variable directly; instead call getMatrix(), which will
4728          * load the value from the View's RenderNode.
4729          */
4730         private final Matrix mMatrix = new Matrix();
4731 
4732         /**
4733          * The inverse transform matrix for the View. This transform is calculated
4734          * internally based on the translation, rotation, and scale properties.
4735          *
4736          * Do *not* use this variable directly; instead call getInverseMatrix(),
4737          * which will load the value from the View's RenderNode.
4738          */
4739         private Matrix mInverseMatrix;
4740 
4741         /**
4742          * The opacity of the View. This is a value from 0 to 1, where 0 means
4743          * completely transparent and 1 means completely opaque.
4744          */
4745         @ViewDebug.ExportedProperty
4746         private float mAlpha = 1f;
4747 
4748         /**
4749          * The opacity of the view as manipulated by the Fade transition. This is a
4750          * property only used by transitions, which is composited with the other alpha
4751          * values to calculate the final visual alpha value.
4752          */
4753         float mTransitionAlpha = 1f;
4754     }
4755 
4756     /** @hide */
4757     @UnsupportedAppUsage
4758     public TransformationInfo mTransformationInfo;
4759 
4760     /**
4761      * Current clip bounds. to which all drawing of this view are constrained.
4762      */
4763     @ViewDebug.ExportedProperty(category = "drawing")
4764     Rect mClipBounds = null;
4765 
4766     private boolean mLastIsOpaque;
4767 
4768     /**
4769      * The distance in pixels from the left edge of this view's parent
4770      * to the left edge of this view.
4771      * {@hide}
4772      */
4773     @ViewDebug.ExportedProperty(category = "layout")
4774     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4775     protected int mLeft;
4776     /**
4777      * The mLeft from the previous frame. Used for detecting movement for purposes of variable
4778      * refresh rate.
4779      */
4780     private int mLastFrameLeft;
4781     /**
4782      * The distance in pixels from the left edge of this view's parent
4783      * to the right edge of this view.
4784      * {@hide}
4785      */
4786     @ViewDebug.ExportedProperty(category = "layout")
4787     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4788     protected int mRight;
4789     /**
4790      * The distance in pixels from the top edge of this view's parent
4791      * to the top edge of this view.
4792      * {@hide}
4793      */
4794     @ViewDebug.ExportedProperty(category = "layout")
4795     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4796     protected int mTop;
4797     /**
4798      * The mTop from the previous frame. Used for detecting movement for purposes of variable
4799      * refresh rate.
4800      */
4801     private int mLastFrameTop;
4802     /**
4803      * The distance in pixels from the top edge of this view's parent
4804      * to the bottom edge of this view.
4805      * {@hide}
4806      */
4807     @ViewDebug.ExportedProperty(category = "layout")
4808     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4809     protected int mBottom;
4810 
4811     /**
4812      * The offset, in pixels, by which the content of this view is scrolled
4813      * horizontally.
4814      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4815      * accessing these directly.
4816      * {@hide}
4817      */
4818     @ViewDebug.ExportedProperty(category = "scrolling")
4819     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4820     protected int mScrollX;
4821     /**
4822      * The offset, in pixels, by which the content of this view is scrolled
4823      * vertically.
4824      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4825      * accessing these directly.
4826      * {@hide}
4827      */
4828     @ViewDebug.ExportedProperty(category = "scrolling")
4829     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4830     protected int mScrollY;
4831 
4832     /**
4833      * The final computed left padding in pixels that is used for drawing. This is the distance in
4834      * pixels between the left edge of this view and the left edge of its content.
4835      * {@hide}
4836      */
4837     @ViewDebug.ExportedProperty(category = "padding")
4838     @UnsupportedAppUsage
4839     protected int mPaddingLeft = 0;
4840     /**
4841      * The final computed right padding in pixels that is used for drawing. This is the distance in
4842      * pixels between the right edge of this view and the right edge of its content.
4843      * {@hide}
4844      */
4845     @ViewDebug.ExportedProperty(category = "padding")
4846     @UnsupportedAppUsage
4847     protected int mPaddingRight = 0;
4848     /**
4849      * The final computed top padding in pixels that is used for drawing. This is the distance in
4850      * pixels between the top edge of this view and the top edge of its content.
4851      * {@hide}
4852      */
4853     @ViewDebug.ExportedProperty(category = "padding")
4854     @UnsupportedAppUsage
4855     protected int mPaddingTop;
4856     /**
4857      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4858      * pixels between the bottom edge of this view and the bottom edge of its content.
4859      * {@hide}
4860      */
4861     @ViewDebug.ExportedProperty(category = "padding")
4862     @UnsupportedAppUsage
4863     protected int mPaddingBottom;
4864 
4865     /**
4866      * The amount of pixel offset applied to the left edge of this view's handwriting bounds.
4867      */
4868     private float mHandwritingBoundsOffsetLeft;
4869 
4870     /**
4871      * The amount of pixel offset applied to the top edge of this view's handwriting bounds.
4872      */
4873     private float mHandwritingBoundsOffsetTop;
4874 
4875     /**
4876      * The amount of pixel offset applied to the right edge of this view's handwriting bounds.
4877      */
4878     private float mHandwritingBoundsOffsetRight;
4879 
4880     /**
4881      * The amount of pixel offset applied to the bottom edge of this view's handwriting bounds.
4882      */
4883     private float mHandwritingBoundsOffsetBottom;
4884 
4885     /**
4886      * The layout insets in pixels, that is the distance in pixels between the
4887      * visible edges of this view its bounds.
4888      */
4889     private Insets mLayoutInsets;
4890 
4891     /**
4892      * Briefly describes the state of the view and is primarily used for accessibility support.
4893      */
4894     private CharSequence mStateDescription;
4895 
4896     /**
4897      * Briefly describes the view and is primarily used for accessibility support.
4898      */
4899     private CharSequence mContentDescription;
4900 
4901     /**
4902      * Brief supplemental information for view and is primarily used for accessibility support.
4903      */
4904     private CharSequence mSupplementalDescription;
4905 
4906     /**
4907      * If this view represents a distinct part of the window, it can have a title that labels the
4908      * area.
4909      */
4910     private CharSequence mAccessibilityPaneTitle;
4911 
4912     /**
4913      * Describes whether this view should only allow interactions from
4914      * {@link android.accessibilityservice.AccessibilityService}s with the
4915      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
4916      * set to true.
4917      */
4918     private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
4919     /** Used to calculate and cache {@link #isAccessibilityDataSensitive()}. */
4920     private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
4921 
4922     /**
4923      * Specifies the id of a view for which this view serves as a label for
4924      * accessibility purposes.
4925      */
4926     private int mLabelForId = View.NO_ID;
4927 
4928     /**
4929      * Predicate for matching labeled view id with its label for
4930      * accessibility purposes.
4931      */
4932     private MatchLabelForPredicate mMatchLabelForPredicate;
4933 
4934     /**
4935      * Specifies a view before which this one is visited in accessibility traversal.
4936      */
4937     private int mAccessibilityTraversalBeforeId = NO_ID;
4938 
4939     /**
4940      * Specifies a view after which this one is visited in accessibility traversal.
4941      */
4942     private int mAccessibilityTraversalAfterId = NO_ID;
4943 
4944     /**
4945      * Predicate for matching a view by its id.
4946      */
4947     private MatchIdPredicate mMatchIdPredicate;
4948 
4949     /**
4950      * The right padding after RTL resolution, but before taking account of scroll bars.
4951      *
4952      * @hide
4953      */
4954     @ViewDebug.ExportedProperty(category = "padding")
4955     protected int mUserPaddingRight;
4956 
4957     /**
4958      * The resolved bottom padding before taking account of scroll bars.
4959      *
4960      * @hide
4961      */
4962     @ViewDebug.ExportedProperty(category = "padding")
4963     protected int mUserPaddingBottom;
4964 
4965     /**
4966      * The left padding after RTL resolution, but before taking account of scroll bars.
4967      *
4968      * @hide
4969      */
4970     @ViewDebug.ExportedProperty(category = "padding")
4971     protected int mUserPaddingLeft;
4972 
4973     /**
4974      * Cache the paddingStart set by the user to append to the scrollbar's size.
4975      *
4976      */
4977     @ViewDebug.ExportedProperty(category = "padding")
4978     int mUserPaddingStart;
4979 
4980     /**
4981      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4982      *
4983      */
4984     @ViewDebug.ExportedProperty(category = "padding")
4985     int mUserPaddingEnd;
4986 
4987     /**
4988      * The left padding as set by a setter method, a background's padding, or via XML property
4989      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4990      *
4991      * @hide
4992      */
4993     int mUserPaddingLeftInitial;
4994 
4995     /**
4996      * The right padding as set by a setter method, a background's padding, or via XML property
4997      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4998      *
4999      * @hide
5000      */
5001     int mUserPaddingRightInitial;
5002 
5003     /**
5004      * Default undefined padding
5005      */
5006     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
5007 
5008     /**
5009      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
5010      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
5011      */
5012     private boolean mLeftPaddingDefined = false;
5013 
5014     /**
5015      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
5016      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
5017      */
5018     private boolean mRightPaddingDefined = false;
5019 
5020     /**
5021      * @hide
5022      */
5023     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
5024     /**
5025      * @hide
5026      */
5027     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
5028 
5029     private LongSparseLongArray mMeasureCache;
5030 
5031     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
5032     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5033     private Drawable mBackground;
5034     private TintInfo mBackgroundTint;
5035 
5036     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
5037     private ForegroundInfo mForegroundInfo;
5038 
5039     private Drawable mScrollIndicatorDrawable;
5040 
5041     /**
5042      * RenderNode used for backgrounds.
5043      * <p>
5044      * When non-null and valid, this is expected to contain an up-to-date copy
5045      * of the background drawable. It is cleared on temporary detach, and reset
5046      * on cleanup.
5047      * @hide
5048      */
5049     RenderNode mBackgroundRenderNode;
5050 
5051     @UnsupportedAppUsage
5052     private int mBackgroundResource;
5053     private boolean mBackgroundSizeChanged;
5054 
5055     /** The default focus highlight.
5056      * @see #mDefaultFocusHighlightEnabled
5057      * @see Drawable#hasFocusStateSpecified()
5058      */
5059     private Drawable mDefaultFocusHighlight;
5060     private Drawable mDefaultFocusHighlightCache;
5061     private boolean mDefaultFocusHighlightSizeChanged;
5062     /**
5063      * True if the default focus highlight is needed on the target device.
5064      */
5065     private static boolean sUseDefaultFocusHighlight;
5066 
5067     /**
5068      * True if zero-sized views can be focused.
5069      */
5070     private static boolean sCanFocusZeroSized;
5071 
5072     /**
5073      * Always assign focus if a focusable View is available.
5074      */
5075     private static boolean sAlwaysAssignFocus;
5076 
5077     private String mTransitionName;
5078 
5079     static class TintInfo {
5080         ColorStateList mTintList;
5081         BlendMode mBlendMode;
5082         boolean mHasTintMode;
5083         boolean mHasTintList;
5084     }
5085 
5086     private static class ForegroundInfo {
5087         private Drawable mDrawable;
5088         private TintInfo mTintInfo;
5089         private int mGravity = Gravity.FILL;
5090         private boolean mInsidePadding = true;
5091         private boolean mBoundsChanged = true;
5092         private final Rect mSelfBounds = new Rect();
5093         private final Rect mOverlayBounds = new Rect();
5094     }
5095 
5096     static class ListenerInfo {
5097 
5098         @UnsupportedAppUsage
ListenerInfo()5099         ListenerInfo() {
5100         }
5101 
5102         /**
5103          * Listener used to dispatch focus change events.
5104          * This field should be made private, so it is hidden from the SDK.
5105          * {@hide}
5106          */
5107         @UnsupportedAppUsage
5108         protected OnFocusChangeListener mOnFocusChangeListener;
5109 
5110         /**
5111          * Listeners for layout change events.
5112          */
5113         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
5114 
5115         protected OnScrollChangeListener mOnScrollChangeListener;
5116 
5117         /**
5118          * Listeners for attach events.
5119          */
5120         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
5121 
5122         /**
5123          * Listener used to dispatch click events.
5124          * This field should be made private, so it is hidden from the SDK.
5125          * {@hide}
5126          */
5127         @UnsupportedAppUsage
5128         public OnClickListener mOnClickListener;
5129 
5130         /**
5131          * Listener used to dispatch long click events.
5132          * This field should be made private, so it is hidden from the SDK.
5133          * {@hide}
5134          */
5135         @UnsupportedAppUsage
5136         protected OnLongClickListener mOnLongClickListener;
5137 
5138         /**
5139          * Listener used to dispatch context click events. This field should be made private, so it
5140          * is hidden from the SDK.
5141          * {@hide}
5142          */
5143         protected OnContextClickListener mOnContextClickListener;
5144 
5145         /**
5146          * Listener used to build the context menu.
5147          * This field should be made private, so it is hidden from the SDK.
5148          * {@hide}
5149          */
5150         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5151         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
5152 
5153         @UnsupportedAppUsage
5154         private OnKeyListener mOnKeyListener;
5155 
5156         @UnsupportedAppUsage
5157         private OnTouchListener mOnTouchListener;
5158 
5159         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5160         private OnHoverListener mOnHoverListener;
5161 
5162         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5163         private OnGenericMotionListener mOnGenericMotionListener;
5164 
5165         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5166         private OnDragListener mOnDragListener;
5167 
5168         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
5169 
5170         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
5171 
5172         OnCapturedPointerListener mOnCapturedPointerListener;
5173 
5174         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
5175 
5176         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
5177 
5178         /**
5179          * This lives here since it's only valid for interactive views. This list is null
5180          * until its first use.
5181          */
5182         private ArrayList<Rect> mSystemGestureExclusionRects = null;
5183         private ArrayList<Rect> mKeepClearRects = null;
5184         private ArrayList<Rect> mUnrestrictedKeepClearRects = null;
5185         private boolean mPreferKeepClear = false;
5186         private Rect mHandwritingArea = null;
5187 
5188         /**
5189          * Used to track {@link #mSystemGestureExclusionRects}, {@link #mKeepClearRects} and
5190          * {@link #mHandwritingArea}.
5191          */
5192         public RenderNode.PositionUpdateListener mPositionUpdateListener;
5193         private Runnable mPositionChangedUpdate;
5194 
5195         /**
5196          * Allows the application to implement custom scroll capture support.
5197          */
5198         ScrollCaptureCallback mScrollCaptureCallback;
5199 
5200         @Nullable
5201         private OnReceiveContentListener mOnReceiveContentListener;
5202     }
5203 
5204     @UnsupportedAppUsage
5205     ListenerInfo mListenerInfo;
5206 
5207     private static class TooltipInfo {
5208         /**
5209          * Text to be displayed in a tooltip popup.
5210          */
5211         @Nullable
5212         CharSequence mTooltipText;
5213 
5214         /**
5215          * View-relative position of the tooltip anchor point.
5216          */
5217         int mAnchorX;
5218         int mAnchorY;
5219 
5220         /**
5221          * The tooltip popup.
5222          */
5223         @Nullable
5224         TooltipPopup mTooltipPopup;
5225 
5226         /**
5227          * Set to true if the tooltip was shown as a result of a long click.
5228          */
5229         boolean mTooltipFromLongClick;
5230 
5231         /**
5232          * Keep these Runnables so that they can be used to reschedule.
5233          */
5234         Runnable mShowTooltipRunnable;
5235         Runnable mHideTooltipRunnable;
5236 
5237         /**
5238          * Hover move is ignored if it is within this distance in pixels from the previous one.
5239          */
5240         int mHoverSlop;
5241 
5242         /**
5243          * Update the anchor position if it significantly (that is by at least mHoverSlop)
5244          * different from the previously stored position. Ignoring insignificant changes
5245          * filters out the jitter which is typical for such input sources as stylus.
5246          *
5247          * @return True if the position has been updated.
5248          */
updateAnchorPos(MotionEvent event)5249         private boolean updateAnchorPos(MotionEvent event) {
5250             final int newAnchorX = (int) event.getX();
5251             final int newAnchorY = (int) event.getY();
5252             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
5253                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
5254                 return false;
5255             }
5256             mAnchorX = newAnchorX;
5257             mAnchorY = newAnchorY;
5258             return true;
5259         }
5260 
5261         /**
5262          *  Clear the anchor position to ensure that the next change is considered significant.
5263          */
clearAnchorPos()5264         private void clearAnchorPos() {
5265             mAnchorX = Integer.MAX_VALUE;
5266             mAnchorY = Integer.MAX_VALUE;
5267         }
5268     }
5269 
5270     TooltipInfo mTooltipInfo;
5271 
5272     // Temporary values used to hold (x,y) coordinates when delegating from the
5273     // two-arg performLongClick() method to the legacy no-arg version.
5274     private float mLongClickX = Float.NaN;
5275     private float mLongClickY = Float.NaN;
5276 
5277     /**
5278      * The application environment this view lives in.
5279      * This field should be made private, so it is hidden from the SDK.
5280      * {@hide}
5281      */
5282     @ViewDebug.ExportedProperty(deepExport = true)
5283     @UnsupportedAppUsage
5284     @UiContext
5285     protected Context mContext;
5286 
5287     @UnsupportedAppUsage
5288     private final Resources mResources;
5289 
5290     @UnsupportedAppUsage
5291     private ScrollabilityCache mScrollCache;
5292 
5293     private int[] mDrawableState = null;
5294 
5295     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
5296 
5297     /**
5298      * Animator that automatically runs based on state changes.
5299      */
5300     private StateListAnimator mStateListAnimator;
5301 
5302     /**
5303      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
5304      * the user may specify which view to go to next.
5305      */
5306     private int mNextFocusLeftId = View.NO_ID;
5307 
5308     /**
5309      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
5310      * the user may specify which view to go to next.
5311      */
5312     private int mNextFocusRightId = View.NO_ID;
5313 
5314     /**
5315      * When this view has focus and the next focus is {@link #FOCUS_UP},
5316      * the user may specify which view to go to next.
5317      */
5318     private int mNextFocusUpId = View.NO_ID;
5319 
5320     /**
5321      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
5322      * the user may specify which view to go to next.
5323      */
5324     private int mNextFocusDownId = View.NO_ID;
5325 
5326     /**
5327      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
5328      * the user may specify which view to go to next.
5329      */
5330     int mNextFocusForwardId = View.NO_ID;
5331 
5332     /**
5333      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
5334      *
5335      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
5336      */
5337     int mNextClusterForwardId = View.NO_ID;
5338 
5339     /**
5340      * Whether this View should use a default focus highlight when it gets focused but doesn't
5341      * have {@link android.R.attr#state_focused} defined in its background.
5342      */
5343     boolean mDefaultFocusHighlightEnabled = true;
5344 
5345     private CheckForLongPress mPendingCheckForLongPress;
5346     @UnsupportedAppUsage
5347     private CheckForTap mPendingCheckForTap = null;
5348     private PerformClick mPerformClick;
5349     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
5350     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
5351     private UnsetPressedState mUnsetPressedState;
5352 
5353     /**
5354      * Whether the long press's action has been invoked.  The tap's action is invoked on the
5355      * up event while a long press is invoked as soon as the long press duration is reached, so
5356      * a long press could be performed before the tap is checked, in which case the tap's action
5357      * should not be invoked.
5358      */
5359     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5360     private boolean mHasPerformedLongPress;
5361 
5362     /**
5363      * Whether a context click button is currently pressed down. This is true when the stylus is
5364      * touching the screen and the primary button has been pressed, or if a mouse's right button is
5365      * pressed. This is false once the button is released or if the stylus has been lifted.
5366      */
5367     private boolean mInContextButtonPress;
5368 
5369     /**
5370      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
5371      * true after a stylus button press has occured, when the next up event should not be recognized
5372      * as a tap.
5373      */
5374     private boolean mIgnoreNextUpEvent;
5375 
5376     /**
5377      * The minimum height of the view. We'll try our best to have the height
5378      * of this view to at least this amount.
5379      */
5380     @ViewDebug.ExportedProperty(category = "measurement")
5381     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
5382     private int mMinHeight;
5383 
5384     /**
5385      * The minimum width of the view. We'll try our best to have the width
5386      * of this view to at least this amount.
5387      */
5388     @ViewDebug.ExportedProperty(category = "measurement")
5389     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
5390     private int mMinWidth;
5391 
5392     /**
5393      * The delegate to handle touch events that are physically in this view
5394      * but should be handled by another view.
5395      */
5396     private TouchDelegate mTouchDelegate = null;
5397 
5398     /**
5399      * While touch exploration is in use, set to true when hovering across boundaries and
5400      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
5401      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
5402      * {@link MotionEvent#ACTION_HOVER_EXIT}.
5403      * Note that children of view group are excluded in the touch area.
5404      * @see #dispatchTouchExplorationHoverEvent
5405      */
5406     private boolean mHoveringTouchDelegate = false;
5407 
5408     // These two fields are set if the view is a handwriting delegator.
5409     private Runnable mHandwritingDelegatorCallback;
5410     private String mAllowedHandwritingDelegatePackageName;
5411 
5412     // These three fields are set if the view is a handwriting delegate.
5413     private boolean mIsHandwritingDelegate;
5414     private String mAllowedHandwritingDelegatorPackageName;
5415     private @InputMethodManager.HandwritingDelegateFlags int mHandwritingDelegateFlags;
5416 
5417     /**
5418      * Solid color to use as a background when creating the drawing cache. Enables
5419      * the cache to use 16 bit bitmaps instead of 32 bit.
5420      */
5421     private int mDrawingCacheBackgroundColor = 0;
5422 
5423     /**
5424      * Special tree observer used when mAttachInfo is null.
5425      */
5426     private ViewTreeObserver mFloatingTreeObserver;
5427 
5428     /**
5429      * Cache the touch slop from the context that created the view.
5430      */
5431     private int mTouchSlop;
5432 
5433     /**
5434      * Cache the ambiguous gesture multiplier from the context that created the view.
5435      */
5436     private float mAmbiguousGestureMultiplier;
5437 
5438     /**
5439      * Object that handles automatic animation of view properties.
5440      */
5441     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5442     private ViewPropertyAnimator mAnimator = null;
5443 
5444     /**
5445      * List of registered FrameMetricsObservers.
5446      */
5447     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
5448 
5449     /**
5450      * Flag indicating that a drag can cross window boundaries.  When
5451      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5452      * with this flag set, all visible applications with targetSdkVersion >=
5453      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
5454      * in the drag operation and receive the dragged content.
5455      *
5456      * <p>If this is the only flag set, then the drag recipient will only have access to text data
5457      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
5458      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
5459      */
5460     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
5461 
5462     /**
5463      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5464      * request read access to the content URI(s) contained in the {@link ClipData} object.
5465      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5466      */
5467     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5468 
5469     /**
5470      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5471      * request write access to the content URI(s) contained in the {@link ClipData} object.
5472      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5473      */
5474     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5475 
5476     /**
5477      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5478      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5479      * reboots until explicitly revoked with
5480      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5481      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5482      */
5483     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5484             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5485 
5486     /**
5487      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5488      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5489      * match against the original granted URI.
5490      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5491      */
5492     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5493             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5494 
5495     /**
5496      * Flag indicating that the drag shadow will be opaque.  When
5497      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5498      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5499      */
5500     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5501 
5502     /**
5503      * Flag indicating that the drag was initiated with
5504      * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START}. When
5505      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called, this
5506      * is used by the system to perform a drag without animations.
5507      */
5508     public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
5509 
5510     /**
5511      * Flag indicating that the caller desires to take ownership of the drag surface for handling
5512      * the animation associated with an unhandled drag.  It is mainly useful if the view starting
5513      * a global drag changes visibility during the gesture and the default animation of animating
5514      * the surface back to the origin is not sufficient.
5515      *
5516      * The calling app must hold the {@link android.Manifest.permission#START_TASKS_FROM_RECENTS}
5517      * permission and will receive the drag surface as a part of
5518      * {@link action.view.DragEvent#ACTION_DRAG_ENDED} only if the drag event's
5519      * {@link action.view.DragEvent#getDragResult()} is {@code false}.  The caller is responsible
5520      * for removing the surface after its animation.
5521      *
5522      * This flag has no effect if the system decides that a cancel-drag animation does not need to
5523      * occur.
5524      * @hide
5525      */
5526     public static final int DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION = 1 << 11;
5527 
5528     /**
5529      * Flag indicating that a drag can cross window boundaries (within the same application).  When
5530      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5531      * with this flag set, only visible windows belonging to the same application (ie. share the
5532      * same UID) with targetSdkVersion >= {@link android.os.Build.VERSION_CODES#N API 24} will be
5533      * able to participate in the drag operation and receive the dragged content.
5534      *
5535      * If both DRAG_FLAG_GLOBAL_SAME_APPLICATION and DRAG_FLAG_GLOBAL are set, then
5536      * DRAG_FLAG_GLOBAL_SAME_APPLICATION takes precedence and the drag will only go to visible
5537      * windows from the same application.
5538      */
5539     @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS)
5540     public static final int DRAG_FLAG_GLOBAL_SAME_APPLICATION = 1 << 12;
5541 
5542     /**
5543      * Flag indicating that an unhandled drag should be delegated to the system to be started if no
5544      * visible window wishes to handle the drop. When using this flag, the caller must provide
5545      * ClipData with an Item that contains an immutable IntentSender to an activity to be launched
5546      * (not a broadcast, service, etc).  See
5547      * {@link ClipData.Item.Builder#setIntentSender(IntentSender)}.
5548      *
5549      * The system can decide to launch the intent or not based on factors like the current screen
5550      * size or windowing mode. If the system does not launch the intent, it will be canceled via the
5551      * normal drag and drop flow.
5552      */
5553     @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS)
5554     public static final int DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG = 1 << 13;
5555 
5556     /**
5557      * Flag indicating that this drag will result in the caller activity's task to be hidden for the
5558      * duration of the drag, which means that the source activity will not receive drag events for
5559      * the current drag gesture. Only the current
5560      * {@link android.service.voice.VoiceInteractionService} may use this flag.
5561      */
5562     @FlaggedApi(FLAG_SUPPORTS_DRAG_ASSISTANT_TO_MULTIWINDOW)
5563     public static final int DRAG_FLAG_HIDE_CALLING_TASK_ON_DRAG_START = 1 << 14;
5564 
5565     /**
5566      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5567      */
5568     private float mVerticalScrollFactor;
5569 
5570     /**
5571      * Position of the vertical scroll bar.
5572      */
5573     @UnsupportedAppUsage
5574     private int mVerticalScrollbarPosition;
5575 
5576     /**
5577      * Position the scroll bar at the default position as determined by the system.
5578      */
5579     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5580 
5581     /**
5582      * Position the scroll bar along the left edge.
5583      */
5584     public static final int SCROLLBAR_POSITION_LEFT = 1;
5585 
5586     /**
5587      * Position the scroll bar along the right edge.
5588      */
5589     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5590 
5591     /**
5592      * Indicates that the view does not have a layer.
5593      *
5594      * @see #getLayerType()
5595      * @see #setLayerType(int, android.graphics.Paint)
5596      * @see #LAYER_TYPE_SOFTWARE
5597      * @see #LAYER_TYPE_HARDWARE
5598      */
5599     public static final int LAYER_TYPE_NONE = 0;
5600 
5601     /**
5602      * <p>Indicates that the view has a software layer. A software layer is backed
5603      * by a bitmap and causes the view to be rendered using Android's software
5604      * rendering pipeline, even if hardware acceleration is enabled.</p>
5605      *
5606      * <p>Software layers have various usages:</p>
5607      * <p>When the application is not using hardware acceleration, a software layer
5608      * is useful to apply a specific color filter and/or blending mode and/or
5609      * translucency to a view and all its children.</p>
5610      * <p>When the application is using hardware acceleration, a software layer
5611      * is useful to render drawing primitives not supported by the hardware
5612      * accelerated pipeline. It can also be used to cache a complex view tree
5613      * into a texture and reduce the complexity of drawing operations. For instance,
5614      * when animating a complex view tree with a translation, a software layer can
5615      * be used to render the view tree only once.</p>
5616      * <p>Software layers should be avoided when the affected view tree updates
5617      * often. Every update will require to re-render the software layer, which can
5618      * potentially be slow (particularly when hardware acceleration is turned on
5619      * since the layer will have to be uploaded into a hardware texture after every
5620      * update.)</p>
5621      *
5622      * @see #getLayerType()
5623      * @see #setLayerType(int, android.graphics.Paint)
5624      * @see #LAYER_TYPE_NONE
5625      * @see #LAYER_TYPE_HARDWARE
5626      */
5627     public static final int LAYER_TYPE_SOFTWARE = 1;
5628 
5629     /**
5630      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5631      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5632      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5633      * rendering pipeline, but only if hardware acceleration is turned on for the
5634      * view hierarchy. When hardware acceleration is turned off, hardware layers
5635      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5636      *
5637      * <p>A hardware layer is useful to apply a specific color filter and/or
5638      * blending mode and/or translucency to a view and all its children.</p>
5639      * <p>A hardware layer can be used to cache a complex view tree into a
5640      * texture and reduce the complexity of drawing operations. For instance,
5641      * when animating a complex view tree with a translation, a hardware layer can
5642      * be used to render the view tree only once.</p>
5643      * <p>A hardware layer can also be used to increase the rendering quality when
5644      * rotation transformations are applied on a view. It can also be used to
5645      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5646      *
5647      * @see #getLayerType()
5648      * @see #setLayerType(int, android.graphics.Paint)
5649      * @see #LAYER_TYPE_NONE
5650      * @see #LAYER_TYPE_SOFTWARE
5651      */
5652     public static final int LAYER_TYPE_HARDWARE = 2;
5653 
5654     /** @hide */
5655     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5656             LAYER_TYPE_NONE,
5657             LAYER_TYPE_SOFTWARE,
5658             LAYER_TYPE_HARDWARE
5659     })
5660     @Retention(RetentionPolicy.SOURCE)
5661     public @interface LayerType {}
5662 
5663     int mLayerType = LAYER_TYPE_NONE;
5664     Paint mLayerPaint;
5665 
5666     /**
5667      * Set to true when drawing cache is enabled and cannot be created.
5668      *
5669      * @hide
5670      */
5671     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5672     public boolean mCachingFailed;
5673     @UnsupportedAppUsage
5674     private Bitmap mDrawingCache;
5675     @UnsupportedAppUsage
5676     private Bitmap mUnscaledDrawingCache;
5677 
5678     /**
5679      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5680      * <p>
5681      * When non-null and valid, this is expected to contain an up-to-date copy
5682      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5683      * cleanup.
5684      */
5685     @UnsupportedAppUsage
5686     final RenderNode mRenderNode;
5687 
5688     /**
5689      * Set to true when the view is sending hover accessibility events because it
5690      * is the innermost hovered view.
5691      */
5692     private boolean mSendingHoverAccessibilityEvents;
5693 
5694     /**
5695      * Delegate for injecting accessibility functionality.
5696      */
5697     @UnsupportedAppUsage
5698     AccessibilityDelegate mAccessibilityDelegate;
5699 
5700     /**
5701      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5702      * and add/remove objects to/from the overlay directly through the Overlay methods.
5703      */
5704     ViewOverlay mOverlay;
5705 
5706     /**
5707      * The currently active parent view for receiving delegated nested scrolling events.
5708      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5709      * by {@link #stopNestedScroll()} at the same point where we clear
5710      * requestDisallowInterceptTouchEvent.
5711      */
5712     private ViewParent mNestedScrollingParent;
5713 
5714     /**
5715      * Consistency verifier for debugging purposes.
5716      * @hide
5717      */
5718     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5719             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5720                     new InputEventConsistencyVerifier(this, 0) : null;
5721 
5722     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5723 
5724     private int[] mTempNestedScrollConsumed;
5725 
5726     /**
5727      * An overlay is going to draw this View instead of being drawn as part of this
5728      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5729      * when this view is invalidated.
5730      */
5731     GhostView mGhostView;
5732 
5733     /**
5734      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5735      * @hide
5736      */
5737     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5738     public String[] mAttributes;
5739 
5740     /**
5741      * Maps a Resource id to its name.
5742      */
5743     private static SparseArray<String> mAttributeMap;
5744 
5745     /**
5746      * Queue of pending runnables. Used to postpone calls to post() until this
5747      * view is attached and has a handler.
5748      */
5749     private HandlerActionQueue mRunQueue;
5750 
5751     /**
5752      * The pointer icon when the mouse hovers on this view. The default is null.
5753      */
5754     private PointerIcon mMousePointerIcon;
5755 
5756     /**
5757      * @hide
5758      */
5759     @UnsupportedAppUsage
5760     String mStartActivityRequestWho;
5761 
5762     @Nullable
5763     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5764 
5765     /** Used to delay visibility updates sent to the autofill manager */
5766     private Handler mVisibilityChangeForAutofillHandler;
5767 
5768     /**
5769      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5770      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5771      */
5772     @Nullable
5773     private ContentCaptureSession mContentCaptureSession;
5774 
5775     /**
5776      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5777      */
5778     private boolean mContentCaptureSessionCached;
5779 
5780     @LayoutRes
5781     private int mSourceLayoutId = ID_NULL;
5782 
5783     @Nullable
5784     private SparseIntArray mAttributeSourceResId;
5785 
5786     @Nullable
5787     private SparseArray<int[]> mAttributeResolutionStacks;
5788 
5789     @StyleRes
5790     private int mExplicitStyle;
5791 
5792     /**
5793      * Specifies which input source classes should provide unbuffered input events to this view
5794      *
5795      * @see View#requestUnbufferedDispatch(int)
5796      */
5797     @InputSourceClass
5798     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5799 
5800     @Nullable
5801     private String[] mReceiveContentMimeTypes;
5802 
5803     @Nullable
5804     private ViewTranslationCallback mViewTranslationCallback;
5805 
5806     private float mFrameContentVelocity = -1;
5807 
5808     @Nullable
5809 
5810     private ViewTranslationResponse mViewTranslationResponse;
5811 
5812     /**
5813      * The size in DP that is considered small for VRR purposes, if square.
5814      */
5815     private static final float FRAME_RATE_SQUARE_SMALL_SIZE_DP = 40f;
5816 
5817     /**
5818      * The size in DP that is considered small for VRR purposes in the narrow dimension. Used for
5819      * narrow Views like a progress bar.
5820      */
5821     private static final float FRAME_RATE_NARROW_SIZE_DP = 10f;
5822 
5823     /**
5824      * A threshold value to determine the frame rate category of the View based on the size.
5825      */
5826     private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
5827 
5828     static final float MAX_FRAME_RATE = 120;
5829 
5830     // The preferred frame rate of the view that is mainly used for
5831     // touch boosting, view velocity handling, and TextureView.
5832     private float mPreferredFrameRate = REQUESTED_FRAME_RATE_CATEGORY_DEFAULT;
5833 
5834     private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
5835 
5836     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5837     public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
5838     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5839     public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1;
5840     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5841     public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2;
5842     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5843     public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3;
5844     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
5845     public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4;
5846 
5847     private int mSizeBasedFrameRateCategoryAndReason;
5848 
5849     /**
5850      * Simple constructor to use when creating a view from code.
5851      *
5852      * @param context The Context the view is running in, through which it can
5853      *        access the current theme, resources, etc.
5854      */
View(Context context)5855     public View(Context context) {
5856         mContext = context;
5857         mResources = context != null ? context.getResources() : null;
5858         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5859         // Set some flags defaults
5860         mPrivateFlags2 =
5861                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5862                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5863                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5864                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5865                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5866                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5867 
5868         final ViewConfiguration configuration = ViewConfiguration.get(context);
5869         mTouchSlop = configuration.getScaledTouchSlop();
5870         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5871 
5872         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5873         mUserPaddingStart = UNDEFINED_PADDING;
5874         mUserPaddingEnd = UNDEFINED_PADDING;
5875         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5876 
5877         if (!sCompatibilityDone && context != null) {
5878             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5879 
5880             // Old versions of the platform would give different results from
5881             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5882             // modes, so we always need to run an additional EXACTLY pass.
5883             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5884 
5885             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5886             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5887             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5888 
5889             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5890             // in apps so we target check it to avoid breaking existing apps.
5891             sPreserveMarginParamsInLayoutParamConversion =
5892                     targetSdkVersion >= Build.VERSION_CODES.N;
5893 
5894             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5895 
5896             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5897 
5898             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5899 
5900             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5901                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5902 
5903             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5904 
5905             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5906 
5907             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5908 
5909             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5910 
5911             sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
5912 
5913             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5914 
5915             GradientDrawable.sWrapNegativeAngleMeasurements =
5916                     targetSdkVersion >= Build.VERSION_CODES.Q;
5917 
5918             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5919 
5920             sCompatibilityDone = true;
5921         }
5922     }
5923 
5924     /**
5925      * Constructor that is called when inflating a view from XML. This is called
5926      * when a view is being constructed from an XML file, supplying attributes
5927      * that were specified in the XML file. This version uses a default style of
5928      * 0, so the only attribute values applied are those in the Context's Theme
5929      * and the given AttributeSet.
5930      *
5931      * <p>
5932      * The method onFinishInflate() will be called after all children have been
5933      * added.
5934      *
5935      * @param context The Context the view is running in, through which it can
5936      *        access the current theme, resources, etc.
5937      * @param attrs The attributes of the XML tag that is inflating the view.
5938      * @see #View(Context, AttributeSet, int)
5939      */
5940     public View(Context context, @Nullable AttributeSet attrs) {
5941         this(context, attrs, 0);
5942     }
5943 
5944     /**
5945      * Perform inflation from XML and apply a class-specific base style from a
5946      * theme attribute. This constructor of View allows subclasses to use their
5947      * own base style when they are inflating. For example, a Button class's
5948      * constructor would call this version of the super class constructor and
5949      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5950      * allows the theme's button style to modify all of the base view attributes
5951      * (in particular its background) as well as the Button class's attributes.
5952      *
5953      * @param context The Context the view is running in, through which it can
5954      *        access the current theme, resources, etc.
5955      * @param attrs The attributes of the XML tag that is inflating the view.
5956      * @param defStyleAttr An attribute in the current theme that contains a
5957      *        reference to a style resource that supplies default values for
5958      *        the view. Can be 0 to not look for defaults.
5959      * @see #View(Context, AttributeSet)
5960      */
5961     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5962         this(context, attrs, defStyleAttr, 0);
5963     }
5964 
5965     /**
5966      * Perform inflation from XML and apply a class-specific base style from a
5967      * theme attribute or style resource. This constructor of View allows
5968      * subclasses to use their own base style when they are inflating.
5969      * <p>
5970      * When determining the final value of a particular attribute, there are
5971      * four inputs that come into play:
5972      * <ol>
5973      * <li>Any attribute values in the given AttributeSet.
5974      * <li>The style resource specified in the AttributeSet (named "style").
5975      * <li>The default style specified by <var>defStyleAttr</var>.
5976      * <li>The default style specified by <var>defStyleRes</var>.
5977      * <li>The base values in this theme.
5978      * </ol>
5979      * <p>
5980      * Each of these inputs is considered in-order, with the first listed taking
5981      * precedence over the following ones. In other words, if in the
5982      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5983      * , then the button's text will <em>always</em> be black, regardless of
5984      * what is specified in any of the styles.
5985      *
5986      * @param context The Context the view is running in, through which it can
5987      *        access the current theme, resources, etc.
5988      * @param attrs The attributes of the XML tag that is inflating the view.
5989      * @param defStyleAttr An attribute in the current theme that contains a
5990      *        reference to a style resource that supplies default values for
5991      *        the view. Can be 0 to not look for defaults.
5992      * @param defStyleRes A resource identifier of a style resource that
5993      *        supplies default values for the view, used only if
5994      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5995      *        to not look for defaults.
5996      * @see #View(Context, AttributeSet, int)
5997      */
5998     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5999         this(context);
6000 
6001         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
6002 
6003         final TypedArray a = context.obtainStyledAttributes(
6004                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
6005 
6006         retrieveExplicitStyle(context.getTheme(), attrs);
6007         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
6008                 defStyleAttr, defStyleRes);
6009 
6010         if (sDebugViewAttributes) {
6011             saveAttributeData(attrs, a);
6012         }
6013 
6014         Drawable background = null;
6015 
6016         int leftPadding = -1;
6017         int topPadding = -1;
6018         int rightPadding = -1;
6019         int bottomPadding = -1;
6020         int startPadding = UNDEFINED_PADDING;
6021         int endPadding = UNDEFINED_PADDING;
6022 
6023         int padding = -1;
6024         int paddingHorizontal = -1;
6025         int paddingVertical = -1;
6026 
6027         int viewFlagValues = 0;
6028         int viewFlagMasks = 0;
6029 
6030         boolean setScrollContainer = false;
6031 
6032         int x = 0;
6033         int y = 0;
6034 
6035         float tx = 0;
6036         float ty = 0;
6037         float tz = 0;
6038         float elevation = 0;
6039         float rotation = 0;
6040         float rotationX = 0;
6041         float rotationY = 0;
6042         float sx = 1f;
6043         float sy = 1f;
6044         boolean transformSet = false;
6045 
6046         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
6047         int overScrollMode = mOverScrollMode;
6048         boolean initializeScrollbars = false;
6049         boolean initializeScrollIndicators = false;
6050 
6051         boolean startPaddingDefined = false;
6052         boolean endPaddingDefined = false;
6053         boolean leftPaddingDefined = false;
6054         boolean rightPaddingDefined = false;
6055 
6056         // Set default values.
6057         viewFlagValues |= FOCUSABLE_AUTO;
6058         viewFlagMasks |= FOCUSABLE_AUTO;
6059 
6060         final int N = a.getIndexCount();
6061         for (int i = 0; i < N; i++) {
6062             int attr = a.getIndex(i);
6063             switch (attr) {
6064                 case com.android.internal.R.styleable.View_background:
6065                     background = a.getDrawable(attr);
6066                     break;
6067                 case com.android.internal.R.styleable.View_padding:
6068                     padding = a.getDimensionPixelSize(attr, -1);
6069                     mUserPaddingLeftInitial = padding;
6070                     mUserPaddingRightInitial = padding;
6071                     leftPaddingDefined = true;
6072                     rightPaddingDefined = true;
6073                     break;
6074                 case com.android.internal.R.styleable.View_paddingHorizontal:
6075                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
6076                     mUserPaddingLeftInitial = paddingHorizontal;
6077                     mUserPaddingRightInitial = paddingHorizontal;
6078                     leftPaddingDefined = true;
6079                     rightPaddingDefined = true;
6080                     break;
6081                 case com.android.internal.R.styleable.View_paddingVertical:
6082                     paddingVertical = a.getDimensionPixelSize(attr, -1);
6083                     break;
6084                 case com.android.internal.R.styleable.View_paddingLeft:
6085                     leftPadding = a.getDimensionPixelSize(attr, -1);
6086                     mUserPaddingLeftInitial = leftPadding;
6087                     leftPaddingDefined = true;
6088                     break;
6089                 case com.android.internal.R.styleable.View_paddingTop:
6090                     topPadding = a.getDimensionPixelSize(attr, -1);
6091                     break;
6092                 case com.android.internal.R.styleable.View_paddingRight:
6093                     rightPadding = a.getDimensionPixelSize(attr, -1);
6094                     mUserPaddingRightInitial = rightPadding;
6095                     rightPaddingDefined = true;
6096                     break;
6097                 case com.android.internal.R.styleable.View_paddingBottom:
6098                     bottomPadding = a.getDimensionPixelSize(attr, -1);
6099                     break;
6100                 case com.android.internal.R.styleable.View_paddingStart:
6101                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
6102                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
6103                     break;
6104                 case com.android.internal.R.styleable.View_paddingEnd:
6105                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
6106                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
6107                     break;
6108                 case com.android.internal.R.styleable.View_scrollX:
6109                     x = a.getDimensionPixelOffset(attr, 0);
6110                     break;
6111                 case com.android.internal.R.styleable.View_scrollY:
6112                     y = a.getDimensionPixelOffset(attr, 0);
6113                     break;
6114                 case com.android.internal.R.styleable.View_alpha:
6115                     setAlpha(a.getFloat(attr, 1f));
6116                     break;
6117                 case com.android.internal.R.styleable.View_transformPivotX:
6118                     setPivotX(a.getDimension(attr, 0));
6119                     break;
6120                 case com.android.internal.R.styleable.View_transformPivotY:
6121                     setPivotY(a.getDimension(attr, 0));
6122                     break;
6123                 case com.android.internal.R.styleable.View_translationX:
6124                     tx = a.getDimension(attr, 0);
6125                     transformSet = true;
6126                     break;
6127                 case com.android.internal.R.styleable.View_translationY:
6128                     ty = a.getDimension(attr, 0);
6129                     transformSet = true;
6130                     break;
6131                 case com.android.internal.R.styleable.View_translationZ:
6132                     tz = a.getDimension(attr, 0);
6133                     transformSet = true;
6134                     break;
6135                 case com.android.internal.R.styleable.View_elevation:
6136                     elevation = a.getDimension(attr, 0);
6137                     transformSet = true;
6138                     break;
6139                 case com.android.internal.R.styleable.View_rotation:
6140                     rotation = a.getFloat(attr, 0);
6141                     transformSet = true;
6142                     break;
6143                 case com.android.internal.R.styleable.View_rotationX:
6144                     rotationX = a.getFloat(attr, 0);
6145                     transformSet = true;
6146                     break;
6147                 case com.android.internal.R.styleable.View_rotationY:
6148                     rotationY = a.getFloat(attr, 0);
6149                     transformSet = true;
6150                     break;
6151                 case com.android.internal.R.styleable.View_scaleX:
6152                     sx = a.getFloat(attr, 1f);
6153                     transformSet = true;
6154                     break;
6155                 case com.android.internal.R.styleable.View_scaleY:
6156                     sy = a.getFloat(attr, 1f);
6157                     transformSet = true;
6158                     break;
6159                 case com.android.internal.R.styleable.View_id:
6160                     mID = a.getResourceId(attr, NO_ID);
6161                     break;
6162                 case com.android.internal.R.styleable.View_tag:
6163                     mTag = a.getText(attr);
6164                     break;
6165                 case com.android.internal.R.styleable.View_fitsSystemWindows:
6166                     if (a.getBoolean(attr, false)) {
6167                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
6168                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
6169                     }
6170                     break;
6171                 case com.android.internal.R.styleable.View_focusable:
6172                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
6173                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
6174                         viewFlagMasks |= FOCUSABLE_MASK;
6175                     }
6176                     break;
6177                 case com.android.internal.R.styleable.View_focusableInTouchMode:
6178                     if (a.getBoolean(attr, false)) {
6179                         // unset auto focus since focusableInTouchMode implies explicit focusable
6180                         viewFlagValues &= ~FOCUSABLE_AUTO;
6181                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
6182                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
6183                     }
6184                     break;
6185                 case com.android.internal.R.styleable.View_clickable:
6186                     if (a.getBoolean(attr, false)) {
6187                         viewFlagValues |= CLICKABLE;
6188                         viewFlagMasks |= CLICKABLE;
6189                     }
6190                     break;
6191                 case com.android.internal.R.styleable.View_allowClickWhenDisabled:
6192                     setAllowClickWhenDisabled(a.getBoolean(attr, false));
6193                     break;
6194                 case com.android.internal.R.styleable.View_longClickable:
6195                     if (a.getBoolean(attr, false)) {
6196                         viewFlagValues |= LONG_CLICKABLE;
6197                         viewFlagMasks |= LONG_CLICKABLE;
6198                     }
6199                     break;
6200                 case com.android.internal.R.styleable.View_contextClickable:
6201                     if (a.getBoolean(attr, false)) {
6202                         viewFlagValues |= CONTEXT_CLICKABLE;
6203                         viewFlagMasks |= CONTEXT_CLICKABLE;
6204                     }
6205                     break;
6206                 case com.android.internal.R.styleable.View_saveEnabled:
6207                     if (!a.getBoolean(attr, true)) {
6208                         viewFlagValues |= SAVE_DISABLED;
6209                         viewFlagMasks |= SAVE_DISABLED_MASK;
6210                     }
6211                     break;
6212                 case com.android.internal.R.styleable.View_duplicateParentState:
6213                     if (a.getBoolean(attr, false)) {
6214                         viewFlagValues |= DUPLICATE_PARENT_STATE;
6215                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
6216                     }
6217                     break;
6218                 case com.android.internal.R.styleable.View_visibility:
6219                     final int visibility = a.getInt(attr, 0);
6220                     if (visibility != 0) {
6221                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
6222                         viewFlagMasks |= VISIBILITY_MASK;
6223                     }
6224                     break;
6225                 case com.android.internal.R.styleable.View_layoutDirection:
6226                     // Clear any layout direction flags (included resolved bits) already set
6227                     mPrivateFlags2 &=
6228                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
6229                     // Set the layout direction flags depending on the value of the attribute
6230                     final int layoutDirection = a.getInt(attr, -1);
6231                     final int value = (layoutDirection != -1) ?
6232                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
6233                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
6234                     break;
6235                 case com.android.internal.R.styleable.View_drawingCacheQuality:
6236                     final int cacheQuality = a.getInt(attr, 0);
6237                     if (cacheQuality != 0) {
6238                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
6239                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
6240                     }
6241                     break;
6242                 case com.android.internal.R.styleable.View_contentDescription:
6243                     setContentDescription(a.getString(attr));
6244                     break;
6245                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
6246                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
6247                     break;
6248                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
6249                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
6250                     break;
6251                 case com.android.internal.R.styleable.View_labelFor:
6252                     setLabelFor(a.getResourceId(attr, NO_ID));
6253                     break;
6254                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
6255                     if (!a.getBoolean(attr, true)) {
6256                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
6257                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
6258                     }
6259                     break;
6260                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
6261                     if (!a.getBoolean(attr, true)) {
6262                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
6263                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
6264                     }
6265                     break;
6266                 case R.styleable.View_scrollbars:
6267                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
6268                     if (scrollbars != SCROLLBARS_NONE) {
6269                         viewFlagValues |= scrollbars;
6270                         viewFlagMasks |= SCROLLBARS_MASK;
6271                         initializeScrollbars = true;
6272                     }
6273                     break;
6274                 //noinspection deprecation
6275                 case R.styleable.View_fadingEdge:
6276                     break;
6277                 case R.styleable.View_requiresFadingEdge:
6278                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
6279                     if (fadingEdge != FADING_EDGE_NONE) {
6280                         viewFlagValues |= fadingEdge;
6281                         viewFlagMasks |= FADING_EDGE_MASK;
6282                         initializeFadingEdgeInternal(a);
6283                     }
6284                     break;
6285                 case R.styleable.View_scrollbarStyle:
6286                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
6287                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6288                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
6289                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
6290                     }
6291                     break;
6292                 case R.styleable.View_isScrollContainer:
6293                     setScrollContainer = true;
6294                     if (a.getBoolean(attr, false)) {
6295                         setScrollContainer(true);
6296                     }
6297                     break;
6298                 case com.android.internal.R.styleable.View_keepScreenOn:
6299                     if (a.getBoolean(attr, false)) {
6300                         viewFlagValues |= KEEP_SCREEN_ON;
6301                         viewFlagMasks |= KEEP_SCREEN_ON;
6302                     }
6303                     break;
6304                 case R.styleable.View_filterTouchesWhenObscured:
6305                     if (a.getBoolean(attr, false)) {
6306                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
6307                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
6308                     }
6309                     break;
6310                 case R.styleable.View_nextFocusLeft:
6311                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
6312                     break;
6313                 case R.styleable.View_nextFocusRight:
6314                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
6315                     break;
6316                 case R.styleable.View_nextFocusUp:
6317                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
6318                     break;
6319                 case R.styleable.View_nextFocusDown:
6320                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
6321                     break;
6322                 case R.styleable.View_nextFocusForward:
6323                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
6324                     break;
6325                 case R.styleable.View_nextClusterForward:
6326                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
6327                     break;
6328                 case R.styleable.View_minWidth:
6329                     mMinWidth = a.getDimensionPixelSize(attr, 0);
6330                     break;
6331                 case R.styleable.View_minHeight:
6332                     mMinHeight = a.getDimensionPixelSize(attr, 0);
6333                     break;
6334                 case R.styleable.View_onClick:
6335                     if (context.isRestricted()) {
6336                         throw new IllegalStateException("The android:onClick attribute cannot "
6337                                 + "be used within a restricted context");
6338                     }
6339 
6340                     final String handlerName = a.getString(attr);
6341                     if (handlerName != null) {
6342                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
6343                     }
6344                     break;
6345                 case R.styleable.View_overScrollMode:
6346                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
6347                     break;
6348                 case R.styleable.View_verticalScrollbarPosition:
6349                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
6350                     break;
6351                 case R.styleable.View_layerType:
6352                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
6353                     break;
6354                 case R.styleable.View_textDirection:
6355                     // Clear any text direction flag already set
6356                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
6357                     // Set the text direction flags depending on the value of the attribute
6358                     final int textDirection = a.getInt(attr, -1);
6359                     if (textDirection != -1) {
6360                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
6361                     }
6362                     break;
6363                 case R.styleable.View_textAlignment:
6364                     // Clear any text alignment flag already set
6365                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
6366                     // Set the text alignment flag depending on the value of the attribute
6367                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
6368                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
6369                     break;
6370                 case R.styleable.View_importantForAccessibility:
6371                     setImportantForAccessibility(a.getInt(attr,
6372                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
6373                     break;
6374                 case R.styleable.View_accessibilityDataSensitive:
6375                     setAccessibilityDataSensitive(a.getInt(attr,
6376                             ACCESSIBILITY_DATA_SENSITIVE_AUTO));
6377                     break;
6378                 case R.styleable.View_accessibilityLiveRegion:
6379                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
6380                     break;
6381                 case R.styleable.View_transitionName:
6382                     setTransitionName(a.getString(attr));
6383                     break;
6384                 case R.styleable.View_nestedScrollingEnabled:
6385                     setNestedScrollingEnabled(a.getBoolean(attr, false));
6386                     break;
6387                 case R.styleable.View_stateListAnimator:
6388                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
6389                             a.getResourceId(attr, 0)));
6390                     break;
6391                 case R.styleable.View_backgroundTint:
6392                     // This will get applied later during setBackground().
6393                     if (mBackgroundTint == null) {
6394                         mBackgroundTint = new TintInfo();
6395                     }
6396                     mBackgroundTint.mTintList = a.getColorStateList(
6397                             R.styleable.View_backgroundTint);
6398                     mBackgroundTint.mHasTintList = true;
6399                     break;
6400                 case R.styleable.View_backgroundTintMode:
6401                     // This will get applied later during setBackground().
6402                     if (mBackgroundTint == null) {
6403                         mBackgroundTint = new TintInfo();
6404                     }
6405                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
6406                             R.styleable.View_backgroundTintMode, -1), null);
6407                     mBackgroundTint.mHasTintMode = true;
6408                     break;
6409                 case R.styleable.View_outlineProvider:
6410                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
6411                             PROVIDER_BACKGROUND));
6412                     break;
6413                 case R.styleable.View_foreground:
6414                     setForeground(a.getDrawable(attr));
6415                     break;
6416                 case R.styleable.View_foregroundGravity:
6417                     setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
6418                     break;
6419                 case R.styleable.View_foregroundTintMode:
6420                     setForegroundTintBlendMode(
6421                             Drawable.parseBlendMode(a.getInt(attr, -1),
6422                                     null));
6423                     break;
6424                 case R.styleable.View_foregroundTint:
6425                     setForegroundTintList(a.getColorStateList(attr));
6426                     break;
6427                 case R.styleable.View_foregroundInsidePadding:
6428                     if (mForegroundInfo == null) {
6429                         mForegroundInfo = new ForegroundInfo();
6430                     }
6431                     mForegroundInfo.mInsidePadding = a.getBoolean(attr,
6432                             mForegroundInfo.mInsidePadding);
6433                     break;
6434                 case R.styleable.View_scrollIndicators:
6435                     final int scrollIndicators =
6436                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
6437                                     & SCROLL_INDICATORS_PFLAG3_MASK;
6438                     if (scrollIndicators != 0) {
6439                         mPrivateFlags3 |= scrollIndicators;
6440                         initializeScrollIndicators = true;
6441                     }
6442                     break;
6443                 case R.styleable.View_pointerIcon:
6444                     final int resourceId = a.getResourceId(attr, 0);
6445                     if (resourceId != 0) {
6446                         setPointerIcon(PointerIcon.load(
6447                                 context.getResources(), resourceId));
6448                     } else {
6449                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
6450                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
6451                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
6452                         }
6453                     }
6454                     break;
6455                 case R.styleable.View_forceHasOverlappingRendering:
6456                     if (a.peekValue(attr) != null) {
6457                         forceHasOverlappingRendering(a.getBoolean(attr, true));
6458                     }
6459                     break;
6460                 case R.styleable.View_tooltipText:
6461                     setTooltipText(a.getText(attr));
6462                     break;
6463                 case R.styleable.View_keyboardNavigationCluster:
6464                     if (a.peekValue(attr) != null) {
6465                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
6466                     }
6467                     break;
6468                 case R.styleable.View_focusedByDefault:
6469                     if (a.peekValue(attr) != null) {
6470                         setFocusedByDefault(a.getBoolean(attr, true));
6471                     }
6472                     break;
6473                 case R.styleable.View_autofillHints:
6474                     if (a.peekValue(attr) != null) {
6475                         CharSequence[] rawHints = null;
6476                         String rawString = null;
6477 
6478                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
6479                             int resId = a.getResourceId(attr, 0);
6480 
6481                             try {
6482                                 rawHints = a.getTextArray(attr);
6483                             } catch (Resources.NotFoundException e) {
6484                                 rawString = getResources().getString(resId);
6485                             }
6486                         } else {
6487                             rawString = a.getString(attr);
6488                         }
6489 
6490                         if (rawHints == null) {
6491                             if (rawString == null) {
6492                                 throw new IllegalArgumentException(
6493                                         "Could not resolve autofillHints");
6494                             } else {
6495                                 rawHints = rawString.split(",");
6496                             }
6497                         }
6498 
6499                         String[] hints = new String[rawHints.length];
6500 
6501                         int numHints = rawHints.length;
6502                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
6503                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
6504                         }
6505                         setAutofillHints(hints);
6506                     }
6507                     break;
6508                 case R.styleable.View_importantForAutofill:
6509                     if (a.peekValue(attr) != null) {
6510                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
6511                     }
6512                     break;
6513                 case R.styleable.View_importantForContentCapture:
6514                     if (a.peekValue(attr) != null) {
6515                         setImportantForContentCapture(a.getInt(attr,
6516                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
6517                     }
6518                     break;
6519                 case R.styleable.View_isCredential:
6520                     if (a.peekValue(attr) != null) {
6521                         setIsCredential(a.getBoolean(attr, false));
6522                     }
6523                     break;
6524                 case R.styleable.View_defaultFocusHighlightEnabled:
6525                     if (a.peekValue(attr) != null) {
6526                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
6527                     }
6528                     break;
6529                 case R.styleable.View_screenReaderFocusable:
6530                     if (a.peekValue(attr) != null) {
6531                         setScreenReaderFocusable(a.getBoolean(attr, false));
6532                     }
6533                     break;
6534                 case R.styleable.View_accessibilityPaneTitle:
6535                     if (a.peekValue(attr) != null) {
6536                         setAccessibilityPaneTitle(a.getString(attr));
6537                     }
6538                     break;
6539                 case R.styleable.View_outlineSpotShadowColor:
6540                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6541                     break;
6542                 case R.styleable.View_outlineAmbientShadowColor:
6543                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6544                     break;
6545                 case com.android.internal.R.styleable.View_accessibilityHeading:
6546                     setAccessibilityHeading(a.getBoolean(attr, false));
6547                     break;
6548                 case R.styleable.View_forceDarkAllowed:
6549                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6550                     break;
6551                 case R.styleable.View_scrollCaptureHint:
6552                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6553                     break;
6554                 case R.styleable.View_clipToOutline:
6555                     setClipToOutline(a.getBoolean(attr, false));
6556                     break;
6557                 case R.styleable.View_preferKeepClear:
6558                     setPreferKeepClear(a.getBoolean(attr, false));
6559                     break;
6560                 case R.styleable.View_autoHandwritingEnabled:
6561                     setAutoHandwritingEnabled(a.getBoolean(attr, false));
6562                     break;
6563                 case R.styleable.View_handwritingBoundsOffsetLeft:
6564                     mHandwritingBoundsOffsetLeft = a.getDimension(attr, 0);
6565                     break;
6566                 case R.styleable.View_handwritingBoundsOffsetTop:
6567                     mHandwritingBoundsOffsetTop = a.getDimension(attr, 0);
6568                     break;
6569                 case R.styleable.View_handwritingBoundsOffsetRight:
6570                     mHandwritingBoundsOffsetRight = a.getDimension(attr, 0);
6571                     break;
6572                 case R.styleable.View_handwritingBoundsOffsetBottom:
6573                     mHandwritingBoundsOffsetBottom = a.getDimension(attr, 0);
6574                     break;
6575                 case R.styleable.View_contentSensitivity:
6576                     setContentSensitivity(a.getInt(attr, CONTENT_SENSITIVITY_AUTO));
6577                     break;
6578                 default: {
6579                     if (supplementalDescription()) {
6580                         if (attr == com.android.internal.R.styleable.View_supplementalDescription) {
6581                             setSupplementalDescription(a.getString(attr));
6582                         }
6583                     }
6584                 }
6585             }
6586         }
6587 
6588         setOverScrollMode(overScrollMode);
6589 
6590         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6591         // the resolved layout direction). Those cached values will be used later during padding
6592         // resolution.
6593         mUserPaddingStart = startPadding;
6594         mUserPaddingEnd = endPadding;
6595 
6596         if (background != null) {
6597             setBackground(background);
6598         }
6599 
6600         // setBackground above will record that padding is currently provided by the background.
6601         // If we have padding specified via xml, record that here instead and use it.
6602         mLeftPaddingDefined = leftPaddingDefined;
6603         mRightPaddingDefined = rightPaddingDefined;
6604 
6605         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6606         // bottomPadding, and padding set by background.  Valid padding beats everything.
6607         if (padding >= 0) {
6608             leftPadding = padding;
6609             topPadding = padding;
6610             rightPadding = padding;
6611             bottomPadding = padding;
6612             mUserPaddingLeftInitial = padding;
6613             mUserPaddingRightInitial = padding;
6614         } else {
6615             if (paddingHorizontal >= 0) {
6616                 leftPadding = paddingHorizontal;
6617                 rightPadding = paddingHorizontal;
6618                 mUserPaddingLeftInitial = paddingHorizontal;
6619                 mUserPaddingRightInitial = paddingHorizontal;
6620             }
6621             if (paddingVertical >= 0) {
6622                 topPadding = paddingVertical;
6623                 bottomPadding = paddingVertical;
6624             }
6625         }
6626 
6627         if (isRtlCompatibilityMode()) {
6628             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6629             // left / right padding are used if defined (meaning here nothing to do). If they are not
6630             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6631             // start / end and resolve them as left / right (layout direction is not taken into account).
6632             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6633             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6634             // defined.
6635             if (!mLeftPaddingDefined && startPaddingDefined) {
6636                 leftPadding = startPadding;
6637             }
6638             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6639             if (!mRightPaddingDefined && endPaddingDefined) {
6640                 rightPadding = endPadding;
6641             }
6642             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6643         } else {
6644             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6645             // values defined. Otherwise, left /right values are used.
6646             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6647             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6648             // defined.
6649             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6650 
6651             if (mLeftPaddingDefined && !hasRelativePadding) {
6652                 mUserPaddingLeftInitial = leftPadding;
6653             }
6654             if (mRightPaddingDefined && !hasRelativePadding) {
6655                 mUserPaddingRightInitial = rightPadding;
6656             }
6657         }
6658 
6659         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6660         // them on if topPadding or bottomPadding are not valid.
6661         internalSetPadding(
6662                 mUserPaddingLeftInitial,
6663                 topPadding >= 0 ? topPadding : mPaddingTop,
6664                 mUserPaddingRightInitial,
6665                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6666 
6667         if (viewFlagMasks != 0) {
6668             setFlags(viewFlagValues, viewFlagMasks);
6669         }
6670 
6671         if (initializeScrollbars) {
6672             initializeScrollbarsInternal(a);
6673         }
6674 
6675         if (initializeScrollIndicators) {
6676             initializeScrollIndicatorsInternal();
6677         }
6678 
6679         a.recycle();
6680 
6681         // Needs to be called after mViewFlags is set
6682         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6683             recomputePadding();
6684         }
6685 
6686         if (x != 0 || y != 0) {
6687             scrollTo(x, y);
6688         }
6689 
6690         if (transformSet) {
6691             setTranslationX(tx);
6692             setTranslationY(ty);
6693             setTranslationZ(tz);
6694             setElevation(elevation);
6695             setRotation(rotation);
6696             setRotationX(rotationX);
6697             setRotationY(rotationY);
6698             setScaleX(sx);
6699             setScaleY(sy);
6700         }
6701 
6702         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6703             setScrollContainer(true);
6704         }
6705 
6706         computeOpaqueFlags();
6707     }
6708 
6709     /**
6710      * Returns the ordered list of resource ID that are considered when resolving attribute values
6711      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6712      * XML. It will also include a set of explicit styles if specified in XML using
6713      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6714      *
6715      * <p>
6716      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6717      * is enabled in Android developer options.
6718      *
6719      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6720      * @return ordered list of resource ID that are considered when resolving attribute values for
6721      * this {@link View}.
6722      */
6723     @NonNull
6724     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6725         if (!sDebugViewAttributes
6726                 || mAttributeResolutionStacks == null
6727                 || mAttributeResolutionStacks.get(attribute) == null) {
6728             return new int[0];
6729         }
6730         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6731         int stackSize = attributeResolutionStack.length;
6732         if (mSourceLayoutId != ID_NULL) {
6733             stackSize++;
6734         }
6735 
6736         int currentIndex = 0;
6737         int[] stack = new int[stackSize];
6738 
6739         if (mSourceLayoutId != ID_NULL) {
6740             stack[currentIndex] = mSourceLayoutId;
6741             currentIndex++;
6742         }
6743         for (int i = 0; i < attributeResolutionStack.length; i++) {
6744             stack[currentIndex] = attributeResolutionStack[i];
6745             currentIndex++;
6746         }
6747         return stack;
6748     }
6749 
6750     /**
6751      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6752      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6753      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6754      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6755      *
6756      * <p>
6757      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6758      * is enabled in Android developer options.
6759      *
6760      * @return mapping of attribute resource ID to source resource ID where the attribute value
6761      * was set.
6762      */
6763     @NonNull
6764     @SuppressWarnings("AndroidFrameworkEfficientCollections")
6765     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6766         HashMap<Integer, Integer> map = new HashMap<>();
6767         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6768             return map;
6769         }
6770         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6771             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6772         }
6773         return map;
6774     }
6775 
6776     /**
6777      * Returns the resource ID for the style specified using {@code style="..."} in the
6778      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6779      * specified or otherwise not applicable.
6780      * <p>
6781      * Each {@link View} can have an explicit style specified in the layout file.
6782      * This style is used first during the {@link View} attribute resolution, then if an attribute
6783      * is not defined there the resource system looks at default style and theme as fallbacks.
6784      *
6785      * <p>
6786      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6787      * is enabled in Android developer options.
6788      *
6789      * @return The resource ID for the style specified using {@code style="..."} in the
6790      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6791      *      if not specified or otherwise not applicable.
6792      */
6793     @StyleRes
6794     public int getExplicitStyle() {
6795         if (!sDebugViewAttributes) {
6796             return ID_NULL;
6797         }
6798         return mExplicitStyle;
6799     }
6800 
6801     /**
6802      * An implementation of OnClickListener that attempts to lazily load a
6803      * named click handling method from a parent or ancestor context.
6804      */
6805     private static class DeclaredOnClickListener implements OnClickListener {
6806         private final View mHostView;
6807         private final String mMethodName;
6808 
6809         private Method mResolvedMethod;
6810         private Context mResolvedContext;
6811 
6812         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6813             mHostView = hostView;
6814             mMethodName = methodName;
6815         }
6816 
6817         @Override
6818         public void onClick(@NonNull View v) {
6819             if (mResolvedMethod == null) {
6820                 resolveMethod(mHostView.getContext(), mMethodName);
6821             }
6822 
6823             try {
6824                 mResolvedMethod.invoke(mResolvedContext, v);
6825             } catch (IllegalAccessException e) {
6826                 throw new IllegalStateException(
6827                         "Could not execute non-public method for android:onClick", e);
6828             } catch (InvocationTargetException e) {
6829                 throw new IllegalStateException(
6830                         "Could not execute method for android:onClick", e);
6831             }
6832         }
6833 
6834         @NonNull
6835         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6836             while (context != null) {
6837                 try {
6838                     if (!context.isRestricted()) {
6839                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6840                         if (method != null) {
6841                             mResolvedMethod = method;
6842                             mResolvedContext = context;
6843                             return;
6844                         }
6845                     }
6846                 } catch (NoSuchMethodException e) {
6847                     // Failed to find method, keep searching up the hierarchy.
6848                 }
6849 
6850                 if (context instanceof ContextWrapper) {
6851                     context = ((ContextWrapper) context).getBaseContext();
6852                 } else {
6853                     // Can't search up the hierarchy, null out and fail.
6854                     context = null;
6855                 }
6856             }
6857 
6858             final int id = mHostView.getId();
6859             final String idText = id == NO_ID ? "" : " with id '"
6860                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6861             throw new IllegalStateException("Could not find method " + mMethodName
6862                     + "(View) in a parent or ancestor Context for android:onClick "
6863                     + "attribute defined on view " + mHostView.getClass() + idText);
6864         }
6865     }
6866 
6867     /**
6868      * Non-public constructor for use in testing
6869      */
6870     @UnsupportedAppUsage
6871     View() {
6872         mResources = null;
6873         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6874     }
6875 
6876     /**
6877      * Returns {@code true} when the View is attached and the system developer setting to show
6878      * the layout bounds is enabled or {@code false} otherwise.
6879      */
6880     public final boolean isShowingLayoutBounds() {
6881         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6882     }
6883 
6884     /**
6885      * Used to test isShowingLayoutBounds(). This sets the local value used
6886      * by that function. This method does nothing if the layout isn't attached.
6887      *
6888      * @hide
6889      */
6890     @TestApi
6891     public final void setShowingLayoutBounds(boolean debugLayout) {
6892         if (mAttachInfo != null) {
6893             mAttachInfo.mDebugLayout = debugLayout;
6894         }
6895     }
6896 
6897     private static SparseArray<String> getAttributeMap() {
6898         if (mAttributeMap == null) {
6899             mAttributeMap = new SparseArray<>();
6900         }
6901         return mAttributeMap;
6902     }
6903 
6904     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6905             @Nullable AttributeSet attrs) {
6906         if (!sDebugViewAttributes) {
6907             return;
6908         }
6909         mExplicitStyle = theme.getExplicitStyle(attrs);
6910     }
6911 
6912     /**
6913      * Stores debugging information about attributes. This should be called in a constructor by
6914      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6915      * then the custom attributes used by this view will not be visible in layout inspection tools.
6916      *
6917      *  @param context Context under which this view is created.
6918      * @param styleable A reference to styleable array R.styleable.Foo
6919      * @param attrs AttributeSet used to construct this view.
6920      * @param t Resolved {@link TypedArray} returned by a call to
6921      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6922      * @param defStyleAttr Default style attribute passed into the view constructor.
6923      * @param defStyleRes Default style resource passed into the view constructor.
6924      */
6925     public final void saveAttributeDataForStyleable(@NonNull Context context,
6926             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6927             int defStyleAttr, int defStyleRes) {
6928         if (!sDebugViewAttributes) {
6929             return;
6930         }
6931 
6932         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6933                 defStyleAttr, defStyleRes, mExplicitStyle);
6934 
6935         if (mAttributeResolutionStacks == null) {
6936             mAttributeResolutionStacks = new SparseArray<>();
6937         }
6938 
6939         if (mAttributeSourceResId == null) {
6940             mAttributeSourceResId = new SparseIntArray();
6941         }
6942 
6943         final int indexCount = t.getIndexCount();
6944         for (int j = 0; j < indexCount; ++j) {
6945             final int index = t.getIndex(j);
6946             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6947             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6948         }
6949     }
6950 
6951     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6952         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6953         final int indexCount = t.getIndexCount();
6954         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6955 
6956         int i = 0;
6957 
6958         // Store raw XML attributes.
6959         for (int j = 0; j < attrsCount; ++j) {
6960             attributes[i] = attrs.getAttributeName(j);
6961             attributes[i + 1] = attrs.getAttributeValue(j);
6962             i += 2;
6963         }
6964 
6965         // Store resolved styleable attributes.
6966         final Resources res = t.getResources();
6967         final SparseArray<String> attributeMap = getAttributeMap();
6968         for (int j = 0; j < indexCount; ++j) {
6969             final int index = t.getIndex(j);
6970             if (!t.hasValueOrEmpty(index)) {
6971                 // Value is undefined. Skip it.
6972                 continue;
6973             }
6974 
6975             final int resourceId = t.getResourceId(index, 0);
6976             if (resourceId == 0) {
6977                 // Value is not a reference. Skip it.
6978                 continue;
6979             }
6980 
6981             String resourceName = attributeMap.get(resourceId);
6982             if (resourceName == null) {
6983                 try {
6984                     resourceName = res.getResourceName(resourceId);
6985                 } catch (Resources.NotFoundException e) {
6986                     resourceName = "0x" + Integer.toHexString(resourceId);
6987                 }
6988                 attributeMap.put(resourceId, resourceName);
6989             }
6990 
6991             attributes[i] = resourceName;
6992             attributes[i + 1] = t.getString(index);
6993             i += 2;
6994         }
6995 
6996         // Trim to fit contents.
6997         final String[] trimmed = new String[i];
6998         System.arraycopy(attributes, 0, trimmed, 0, i);
6999         mAttributes = trimmed;
7000     }
7001 
7002     @Override
7003     public String toString() {
7004         StringBuilder out = new StringBuilder(256);
7005         out.append(getClass().getName());
7006         out.append('{');
7007         out.append(Integer.toHexString(System.identityHashCode(this)));
7008         out.append(' ');
7009         switch (mViewFlags&VISIBILITY_MASK) {
7010             case VISIBLE: out.append('V'); break;
7011             case INVISIBLE: out.append('I'); break;
7012             case GONE: out.append('G'); break;
7013             default: out.append('.'); break;
7014         }
7015         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
7016         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
7017         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
7018         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
7019         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
7020         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
7021         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
7022         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
7023         out.append(' ');
7024         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
7025         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
7026         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
7027         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
7028             out.append('p');
7029         } else {
7030             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
7031         }
7032         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
7033         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
7034         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
7035         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
7036         out.append(' ');
7037         out.append(mLeft);
7038         out.append(',');
7039         out.append(mTop);
7040         out.append('-');
7041         out.append(mRight);
7042         out.append(',');
7043         out.append(mBottom);
7044         appendId(out);
7045         if (mAutofillId != null) {
7046             out.append(" aid="); out.append(mAutofillId);
7047         }
7048         out.append("}");
7049         return out.toString();
7050     }
7051 
7052     void appendId(StringBuilder out) {
7053         final int id = getId();
7054         if (id != NO_ID) {
7055             out.append(" #");
7056             out.append(Integer.toHexString(id));
7057             final Resources r = mResources;
7058             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
7059                 try {
7060                     String pkgname;
7061                     switch (id&0xff000000) {
7062                         case 0x7f000000:
7063                             pkgname="app";
7064                             break;
7065                         case 0x01000000:
7066                             pkgname="android";
7067                             break;
7068                         default:
7069                             pkgname = r.getResourcePackageName(id);
7070                             break;
7071                     }
7072                     String typename = r.getResourceTypeName(id);
7073                     String entryname = r.getResourceEntryName(id);
7074                     out.append(" ");
7075                     out.append(pkgname);
7076                     out.append(":");
7077                     out.append(typename);
7078                     out.append("/");
7079                     out.append(entryname);
7080                 } catch (Resources.NotFoundException e) {
7081                 }
7082             }
7083         }
7084     }
7085 
7086     /**
7087      * <p>
7088      * Initializes the fading edges from a given set of styled attributes. This
7089      * method should be called by subclasses that need fading edges and when an
7090      * instance of these subclasses is created programmatically rather than
7091      * being inflated from XML. This method is automatically called when the XML
7092      * is inflated.
7093      * </p>
7094      *
7095      * @param a the styled attributes set to initialize the fading edges from
7096      *
7097      * @removed
7098      */
7099     protected void initializeFadingEdge(TypedArray a) {
7100         // This method probably shouldn't have been included in the SDK to begin with.
7101         // It relies on 'a' having been initialized using an attribute filter array that is
7102         // not publicly available to the SDK. The old method has been renamed
7103         // to initializeFadingEdgeInternal and hidden for framework use only;
7104         // this one initializes using defaults to make it safe to call for apps.
7105 
7106         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
7107 
7108         initializeFadingEdgeInternal(arr);
7109 
7110         arr.recycle();
7111     }
7112 
7113     /**
7114      * <p>
7115      * Initializes the fading edges from a given set of styled attributes. This
7116      * method should be called by subclasses that need fading edges and when an
7117      * instance of these subclasses is created programmatically rather than
7118      * being inflated from XML. This method is automatically called when the XML
7119      * is inflated.
7120      * </p>
7121      *
7122      * @param a the styled attributes set to initialize the fading edges from
7123      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
7124      */
7125     protected void initializeFadingEdgeInternal(TypedArray a) {
7126         initScrollCache();
7127 
7128         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
7129                 R.styleable.View_fadingEdgeLength,
7130                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
7131     }
7132 
7133     /**
7134      * Returns the size of the vertical faded edges used to indicate that more
7135      * content in this view is visible.
7136      *
7137      * @return The size in pixels of the vertical faded edge or 0 if vertical
7138      *         faded edges are not enabled for this view.
7139      * @attr ref android.R.styleable#View_fadingEdgeLength
7140      */
7141     public int getVerticalFadingEdgeLength() {
7142         if (isVerticalFadingEdgeEnabled()) {
7143             ScrollabilityCache cache = mScrollCache;
7144             if (cache != null) {
7145                 return cache.fadingEdgeLength;
7146             }
7147         }
7148         return 0;
7149     }
7150 
7151     /**
7152      * Set the size of the faded edge used to indicate that more content in this
7153      * view is available.  Will not change whether the fading edge is enabled; use
7154      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
7155      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
7156      * for the vertical or horizontal fading edges.
7157      *
7158      * @param length The size in pixels of the faded edge used to indicate that more
7159      *        content in this view is visible.
7160      */
7161     public void setFadingEdgeLength(int length) {
7162         initScrollCache();
7163         mScrollCache.fadingEdgeLength = length;
7164     }
7165 
7166     /**
7167      * Clears the request and callback previously set
7168      * through {@link View#setPendingCredentialRequest}.
7169      * Once this API is invoked, there will be no request fired to {@link CredentialManager}
7170      * on future view focus events.
7171      *
7172      * @see #setPendingCredentialRequest
7173      */
7174     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
7175     public void clearPendingCredentialRequest() {
7176         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
7177             Log.v(AUTOFILL_LOG_TAG, "clearPendingCredentialRequest called");
7178         }
7179         mViewCredentialHandler = null;
7180     }
7181 
7182     /**
7183      * Sets a {@link CredentialManager} request to retrieve credentials, when the user focuses
7184      * on this given view.
7185      *
7186      * When this view is focused, the given {@code request} will be fired to
7187      * {@link CredentialManager}, which will fetch content from all
7188      * {@link android.service.credentials.CredentialProviderService} services on the
7189      * device, and then display credential options to the user on a relevant UI
7190      * (dropdown, keyboard suggestions etc.).
7191      *
7192      * When the user selects a credential, the final {@link GetCredentialResponse} will be
7193      * propagated to the given {@code callback}. Developers are expected to handle the response
7194      * programmatically and perform a relevant action, e.g. signing in the user.
7195      *
7196      * <p> For details on how to  build a Credential Manager request, please see
7197      * {@link GetCredentialRequest}.
7198      *
7199      * <p> This API should be called at any point before the user focuses on the view, e.g. during
7200      * {@code onCreate} of an Activity.
7201      *
7202      * @param request the request to be fired when this view is entered
7203      * @param callback to be invoked when either a response or an exception needs to be
7204      *                 propagated for the given view
7205      */
7206     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
7207     public void setPendingCredentialRequest(@NonNull GetCredentialRequest request,
7208             @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
7209         Preconditions.checkNotNull(request, "request must not be null");
7210         Preconditions.checkNotNull(callback, "callback must not be null");
7211 
7212         for (CredentialOption option : request.getCredentialOptions()) {
7213             ArrayList<AutofillId> ids = option.getCandidateQueryData()
7214                     .getParcelableArrayList(
7215                             CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class);
7216             ids = ids != null ? ids : new ArrayList<>();
7217             if (!ids.contains(getAutofillId())) {
7218                 ids.add(getAutofillId());
7219             }
7220             option.getCandidateQueryData()
7221                     .putParcelableArrayList(CredentialProviderService.EXTRA_AUTOFILL_ID, ids);
7222         }
7223         mViewCredentialHandler = new ViewCredentialHandler(request, callback);
7224     }
7225 
7226     /**
7227      *
7228      * @hide
7229      */
7230     @Nullable
7231     public ViewCredentialHandler getViewCredentialHandler() {
7232         return mViewCredentialHandler;
7233     }
7234 
7235     /**
7236      * Returns the size of the horizontal faded edges used to indicate that more
7237      * content in this view is visible.
7238      *
7239      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
7240      *         faded edges are not enabled for this view.
7241      * @attr ref android.R.styleable#View_fadingEdgeLength
7242      */
7243     public int getHorizontalFadingEdgeLength() {
7244         if (isHorizontalFadingEdgeEnabled()) {
7245             ScrollabilityCache cache = mScrollCache;
7246             if (cache != null) {
7247                 return cache.fadingEdgeLength;
7248             }
7249         }
7250         return 0;
7251     }
7252 
7253     /**
7254      * Returns the width of the vertical scrollbar.
7255      *
7256      * @return The width in pixels of the vertical scrollbar or 0 if there
7257      *         is no vertical scrollbar.
7258      */
7259     public int getVerticalScrollbarWidth() {
7260         ScrollabilityCache cache = mScrollCache;
7261         if (cache != null) {
7262             ScrollBarDrawable scrollBar = cache.scrollBar;
7263             if (scrollBar != null) {
7264                 int size = scrollBar.getSize(true);
7265                 if (size <= 0) {
7266                     size = cache.scrollBarSize;
7267                 }
7268                 return size;
7269             }
7270             return 0;
7271         }
7272         return 0;
7273     }
7274 
7275     /**
7276      * Returns the height of the horizontal scrollbar.
7277      *
7278      * @return The height in pixels of the horizontal scrollbar or 0 if
7279      *         there is no horizontal scrollbar.
7280      */
7281     protected int getHorizontalScrollbarHeight() {
7282         ScrollabilityCache cache = mScrollCache;
7283         if (cache != null) {
7284             ScrollBarDrawable scrollBar = cache.scrollBar;
7285             if (scrollBar != null) {
7286                 int size = scrollBar.getSize(false);
7287                 if (size <= 0) {
7288                     size = cache.scrollBarSize;
7289                 }
7290                 return size;
7291             }
7292             return 0;
7293         }
7294         return 0;
7295     }
7296 
7297     /**
7298      * <p>
7299      * Initializes the scrollbars from a given set of styled attributes. This
7300      * method should be called by subclasses that need scrollbars and when an
7301      * instance of these subclasses is created programmatically rather than
7302      * being inflated from XML. This method is automatically called when the XML
7303      * is inflated.
7304      * </p>
7305      *
7306      * @param a the styled attributes set to initialize the scrollbars from
7307      *
7308      * @removed
7309      */
7310     protected void initializeScrollbars(TypedArray a) {
7311         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
7312         // using the View filter array which is not available to the SDK. As such, internal
7313         // framework usage now uses initializeScrollbarsInternal and we grab a default
7314         // TypedArray with the right filter instead here.
7315         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
7316 
7317         initializeScrollbarsInternal(arr);
7318 
7319         // We ignored the method parameter. Recycle the one we actually did use.
7320         arr.recycle();
7321     }
7322 
7323     private void initializeScrollBarDrawable() {
7324         initScrollCache();
7325 
7326         if (mScrollCache.scrollBar == null) {
7327             mScrollCache.scrollBar = new ScrollBarDrawable();
7328             mScrollCache.scrollBar.setState(getDrawableState());
7329             mScrollCache.scrollBar.setCallback(this);
7330         }
7331     }
7332 
7333     /**
7334      * <p>
7335      * Initializes the scrollbars from a given set of styled attributes. This
7336      * method should be called by subclasses that need scrollbars and when an
7337      * instance of these subclasses is created programmatically rather than
7338      * being inflated from XML. This method is automatically called when the XML
7339      * is inflated.
7340      * </p>
7341      *
7342      * @param a the styled attributes set to initialize the scrollbars from
7343      * @hide
7344      */
7345     @UnsupportedAppUsage
7346     protected void initializeScrollbarsInternal(TypedArray a) {
7347         initScrollCache();
7348 
7349         final ScrollabilityCache scrollabilityCache = mScrollCache;
7350 
7351         if (scrollabilityCache.scrollBar == null) {
7352             scrollabilityCache.scrollBar = new ScrollBarDrawable();
7353             scrollabilityCache.scrollBar.setState(getDrawableState());
7354             scrollabilityCache.scrollBar.setCallback(this);
7355         }
7356 
7357         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
7358 
7359         if (!fadeScrollbars) {
7360             scrollabilityCache.state = ScrollabilityCache.ON;
7361         }
7362         scrollabilityCache.fadeScrollBars = fadeScrollbars;
7363 
7364 
7365         scrollabilityCache.scrollBarFadeDuration = a.getInt(
7366                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
7367                         .getScrollBarFadeDuration());
7368         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
7369                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
7370                 ViewConfiguration.getScrollDefaultDelay());
7371 
7372 
7373         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
7374                 com.android.internal.R.styleable.View_scrollbarSize,
7375                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
7376 
7377         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
7378         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
7379 
7380         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
7381         if (thumb != null) {
7382             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
7383         }
7384 
7385         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
7386                 false);
7387         if (alwaysDraw) {
7388             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
7389         }
7390 
7391         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
7392         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
7393 
7394         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
7395         if (thumb != null) {
7396             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
7397         }
7398 
7399         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
7400                 false);
7401         if (alwaysDraw) {
7402             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
7403         }
7404 
7405         // Apply layout direction to the new Drawables if needed
7406         final int layoutDirection = getLayoutDirection();
7407         if (track != null) {
7408             track.setLayoutDirection(layoutDirection);
7409         }
7410         if (thumb != null) {
7411             thumb.setLayoutDirection(layoutDirection);
7412         }
7413 
7414         // Re-apply user/background padding so that scrollbar(s) get added
7415         resolvePadding();
7416     }
7417 
7418     /**
7419      * Defines the vertical scrollbar thumb drawable
7420      * @attr ref android.R.styleable#View_scrollbarThumbVertical
7421      *
7422      * @see #awakenScrollBars(int)
7423      * @see #isVerticalScrollBarEnabled()
7424      * @see #setVerticalScrollBarEnabled(boolean)
7425      */
7426     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
7427         initializeScrollBarDrawable();
7428         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
7429     }
7430 
7431     /**
7432      * Defines the vertical scrollbar track drawable
7433      * @attr ref android.R.styleable#View_scrollbarTrackVertical
7434      *
7435      * @see #awakenScrollBars(int)
7436      * @see #isVerticalScrollBarEnabled()
7437      * @see #setVerticalScrollBarEnabled(boolean)
7438      */
7439     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
7440         initializeScrollBarDrawable();
7441         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
7442     }
7443 
7444     /**
7445      * Defines the horizontal thumb drawable
7446      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
7447      *
7448      * @see #awakenScrollBars(int)
7449      * @see #isHorizontalScrollBarEnabled()
7450      * @see #setHorizontalScrollBarEnabled(boolean)
7451      */
7452     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
7453         initializeScrollBarDrawable();
7454         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
7455     }
7456 
7457     /**
7458      * Defines the horizontal track drawable
7459      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
7460      *
7461      * @see #awakenScrollBars(int)
7462      * @see #isHorizontalScrollBarEnabled()
7463      * @see #setHorizontalScrollBarEnabled(boolean)
7464      */
7465     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
7466         initializeScrollBarDrawable();
7467         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
7468     }
7469 
7470     /**
7471      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
7472      * exists, null otherwise.
7473      *
7474      * @see #awakenScrollBars(int)
7475      * @see #isVerticalScrollBarEnabled()
7476      * @see #setVerticalScrollBarEnabled(boolean)
7477      */
7478     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
7479         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
7480     }
7481 
7482     /**
7483      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
7484      * exists, null otherwise.
7485      *
7486      * @see #awakenScrollBars(int)
7487      * @see #isVerticalScrollBarEnabled()
7488      * @see #setVerticalScrollBarEnabled(boolean)
7489      */
7490     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
7491         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
7492     }
7493 
7494     /**
7495      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
7496      * exists, null otherwise.
7497      *
7498      * @see #awakenScrollBars(int)
7499      * @see #isHorizontalScrollBarEnabled()
7500      * @see #setHorizontalScrollBarEnabled(boolean)
7501      */
7502     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
7503         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
7504     }
7505 
7506     /**
7507      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
7508      * exists, null otherwise.
7509      *
7510      * @see #awakenScrollBars(int)
7511      * @see #isHorizontalScrollBarEnabled()
7512      * @see #setHorizontalScrollBarEnabled(boolean)
7513      */
7514     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
7515         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
7516     }
7517 
7518     private void initializeScrollIndicatorsInternal() {
7519         // Some day maybe we'll break this into top/left/start/etc. and let the
7520         // client control it. Until then, you can have any scroll indicator you
7521         // want as long as it's a 1dp foreground-colored rectangle.
7522         if (mScrollIndicatorDrawable == null) {
7523             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
7524         }
7525     }
7526 
7527     /**
7528      * <p>
7529      * Initalizes the scrollability cache if necessary.
7530      * </p>
7531      */
7532     private void initScrollCache() {
7533         if (mScrollCache == null) {
7534             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
7535         }
7536     }
7537 
7538     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
7539     private ScrollabilityCache getScrollCache() {
7540         initScrollCache();
7541         return mScrollCache;
7542     }
7543 
7544     /**
7545      * Set the position of the vertical scroll bar. Should be one of
7546      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
7547      * {@link #SCROLLBAR_POSITION_RIGHT}.
7548      *
7549      * @param position Where the vertical scroll bar should be positioned.
7550      */
7551     public void setVerticalScrollbarPosition(int position) {
7552         if (mVerticalScrollbarPosition != position) {
7553             mVerticalScrollbarPosition = position;
7554             computeOpaqueFlags();
7555             resolvePadding();
7556         }
7557     }
7558 
7559     /**
7560      * @return The position where the vertical scroll bar will show, if applicable.
7561      * @see #setVerticalScrollbarPosition(int)
7562      */
7563     public int getVerticalScrollbarPosition() {
7564         return mVerticalScrollbarPosition;
7565     }
7566 
7567     boolean isOnScrollbar(float x, float y) {
7568         if (mScrollCache == null) {
7569             return false;
7570         }
7571         x += getScrollX();
7572         y += getScrollY();
7573         final boolean canScrollVertically =
7574                 computeVerticalScrollRange() > computeVerticalScrollExtent();
7575         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
7576             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7577             getVerticalScrollBarBounds(null, touchBounds);
7578             if (touchBounds.contains((int) x, (int) y)) {
7579                 return true;
7580             }
7581         }
7582         final boolean canScrollHorizontally =
7583                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
7584         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
7585             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7586             getHorizontalScrollBarBounds(null, touchBounds);
7587             if (touchBounds.contains((int) x, (int) y)) {
7588                 return true;
7589             }
7590         }
7591         return false;
7592     }
7593 
7594     @UnsupportedAppUsage
7595     boolean isOnScrollbarThumb(float x, float y) {
7596         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
7597     }
7598 
7599     private boolean isOnVerticalScrollbarThumb(float x, float y) {
7600         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
7601             return false;
7602         }
7603         final int range = computeVerticalScrollRange();
7604         final int extent = computeVerticalScrollExtent();
7605         if (range > extent) {
7606             x += getScrollX();
7607             y += getScrollY();
7608             final Rect bounds = mScrollCache.mScrollBarBounds;
7609             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7610             getVerticalScrollBarBounds(bounds, touchBounds);
7611             final int offset = computeVerticalScrollOffset();
7612             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
7613                     extent, range);
7614             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
7615                     extent, range, offset);
7616             final int thumbTop = bounds.top + thumbOffset;
7617             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7618             if (x >= touchBounds.left && x <= touchBounds.right
7619                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
7620                 return true;
7621             }
7622         }
7623         return false;
7624     }
7625 
7626     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
7627         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
7628             return false;
7629         }
7630         final int range = computeHorizontalScrollRange();
7631         final int extent = computeHorizontalScrollExtent();
7632         if (range > extent) {
7633             x += getScrollX();
7634             y += getScrollY();
7635             final Rect bounds = mScrollCache.mScrollBarBounds;
7636             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7637             getHorizontalScrollBarBounds(bounds, touchBounds);
7638             final int offset = computeHorizontalScrollOffset();
7639 
7640             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
7641                     extent, range);
7642             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7643                     extent, range, offset);
7644             final int thumbLeft = bounds.left + thumbOffset;
7645             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7646             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7647                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7648                 return true;
7649             }
7650         }
7651         return false;
7652     }
7653 
7654     @UnsupportedAppUsage
7655     boolean isDraggingScrollBar() {
7656         return mScrollCache != null
7657                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7658     }
7659 
7660     /**
7661      * Sets the state of all scroll indicators.
7662      * <p>
7663      * See {@link #setScrollIndicators(int, int)} for usage information.
7664      *
7665      * @param indicators a bitmask of indicators that should be enabled, or
7666      *                   {@code 0} to disable all indicators
7667      * @see #setScrollIndicators(int, int)
7668      * @see #getScrollIndicators()
7669      * @attr ref android.R.styleable#View_scrollIndicators
7670      */
7671     @RemotableViewMethod
7672     public void setScrollIndicators(@ScrollIndicators int indicators) {
7673         setScrollIndicators(indicators,
7674                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7675     }
7676 
7677     /**
7678      * Sets the state of the scroll indicators specified by the mask. To change
7679      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7680      * <p>
7681      * When a scroll indicator is enabled, it will be displayed if the view
7682      * can scroll in the direction of the indicator.
7683      * <p>
7684      * Multiple indicator types may be enabled or disabled by passing the
7685      * logical OR of the desired types. If multiple types are specified, they
7686      * will all be set to the same enabled state.
7687      * <p>
7688      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7689      *
7690      * @param indicators the indicator direction, or the logical OR of multiple
7691      *             indicator directions. One or more of:
7692      *             <ul>
7693      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7694      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7695      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7696      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7697      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7698      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7699      *             </ul>
7700      * @see #setScrollIndicators(int)
7701      * @see #getScrollIndicators()
7702      * @attr ref android.R.styleable#View_scrollIndicators
7703      */
7704     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7705         // Shift and sanitize mask.
7706         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7707         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7708 
7709         // Shift and mask indicators.
7710         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7711         indicators &= mask;
7712 
7713         // Merge with non-masked flags.
7714         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7715 
7716         if (mPrivateFlags3 != updatedFlags) {
7717             mPrivateFlags3 = updatedFlags;
7718 
7719             if (indicators != 0) {
7720                 initializeScrollIndicatorsInternal();
7721             }
7722             invalidate();
7723         }
7724     }
7725 
7726     /**
7727      * Returns a bitmask representing the enabled scroll indicators.
7728      * <p>
7729      * For example, if the top and left scroll indicators are enabled and all
7730      * other indicators are disabled, the return value will be
7731      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7732      * <p>
7733      * To check whether the bottom scroll indicator is enabled, use the value
7734      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7735      *
7736      * @return a bitmask representing the enabled scroll indicators
7737      */
7738     @InspectableProperty(flagMapping = {
7739             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7740             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7741             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7742             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7743             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7744             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7745             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7746     })
7747     @ScrollIndicators
7748     public int getScrollIndicators() {
7749         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7750                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7751     }
7752 
7753     @UnsupportedAppUsage
7754     ListenerInfo getListenerInfo() {
7755         if (mListenerInfo != null) {
7756             return mListenerInfo;
7757         }
7758         mListenerInfo = new ListenerInfo();
7759         return mListenerInfo;
7760     }
7761 
7762     /**
7763      * Register a callback to be invoked when the scroll X or Y positions of
7764      * this view change.
7765      * <p>
7766      * <b>Note:</b> Some views handle scrolling independently from View and may
7767      * have their own separate listeners for scroll-type events. For example,
7768      * {@link android.widget.ListView ListView} allows clients to register an
7769      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7770      * to listen for changes in list scroll position.
7771      *
7772      * @param l The listener to notify when the scroll X or Y position changes.
7773      * @see android.view.View#getScrollX()
7774      * @see android.view.View#getScrollY()
7775      */
7776     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7777         getListenerInfo().mOnScrollChangeListener = l;
7778     }
7779 
7780     /**
7781      * Register a callback to be invoked when focus of this view changed.
7782      *
7783      * @param l The callback that will run.
7784      */
7785     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7786         getListenerInfo().mOnFocusChangeListener = l;
7787     }
7788 
7789     /**
7790      * Add a listener that will be called when the bounds of the view change due to
7791      * layout processing.
7792      *
7793      * @param listener The listener that will be called when layout bounds change.
7794      */
7795     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7796         ListenerInfo li = getListenerInfo();
7797         if (li.mOnLayoutChangeListeners == null) {
7798             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7799         }
7800         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7801             li.mOnLayoutChangeListeners.add(listener);
7802         }
7803     }
7804 
7805     /**
7806      * Remove a listener for layout changes.
7807      *
7808      * @param listener The listener for layout bounds change.
7809      */
7810     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7811         ListenerInfo li = mListenerInfo;
7812         if (li == null || li.mOnLayoutChangeListeners == null) {
7813             return;
7814         }
7815         li.mOnLayoutChangeListeners.remove(listener);
7816     }
7817 
7818     /**
7819      * Add a listener for attach state changes.
7820      *
7821      * This listener will be called whenever this view is attached or detached
7822      * from a window. Remove the listener using
7823      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7824      *
7825      * @param listener Listener to attach
7826      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7827      */
7828     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7829         ListenerInfo li = getListenerInfo();
7830         if (li.mOnAttachStateChangeListeners == null) {
7831             li.mOnAttachStateChangeListeners
7832                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7833         }
7834         li.mOnAttachStateChangeListeners.add(listener);
7835     }
7836 
7837     /**
7838      * Remove a listener for attach state changes. The listener will receive no further
7839      * notification of window attach/detach events.
7840      *
7841      * @param listener Listener to remove
7842      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7843      */
7844     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7845         ListenerInfo li = mListenerInfo;
7846         if (li == null || li.mOnAttachStateChangeListeners == null) {
7847             return;
7848         }
7849         li.mOnAttachStateChangeListeners.remove(listener);
7850     }
7851 
7852     /**
7853      * Returns the focus-change callback registered for this view.
7854      *
7855      * @return The callback, or null if one is not registered.
7856      */
7857     public OnFocusChangeListener getOnFocusChangeListener() {
7858         ListenerInfo li = mListenerInfo;
7859         return li != null ? li.mOnFocusChangeListener : null;
7860     }
7861 
7862     /**
7863      * Register a callback to be invoked when this view is clicked. If this view is not
7864      * clickable, it becomes clickable.
7865      *
7866      * @param l The callback that will run
7867      *
7868      * @see #setClickable(boolean)
7869      */
7870     public void setOnClickListener(@Nullable OnClickListener l) {
7871         if (!isClickable()) {
7872             setClickable(true);
7873         }
7874         getListenerInfo().mOnClickListener = l;
7875     }
7876 
7877     /**
7878      * Return whether this view has an attached OnClickListener.  Returns
7879      * true if there is a listener, false if there is none.
7880      */
7881     public boolean hasOnClickListeners() {
7882         ListenerInfo li = mListenerInfo;
7883         return (li != null && li.mOnClickListener != null);
7884     }
7885 
7886     /**
7887      * Register a callback to be invoked when this view is clicked and held. If this view is not
7888      * long clickable, it becomes long clickable.
7889      *
7890      * @param l The callback that will run
7891      *
7892      * @see #setLongClickable(boolean)
7893      */
7894     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7895         if (!isLongClickable()) {
7896             setLongClickable(true);
7897         }
7898         getListenerInfo().mOnLongClickListener = l;
7899     }
7900 
7901     /**
7902      * Return whether this view has an attached OnLongClickListener.  Returns
7903      * true if there is a listener, false if there is none.
7904      */
7905     public boolean hasOnLongClickListeners() {
7906         ListenerInfo li = mListenerInfo;
7907         return (li != null && li.mOnLongClickListener != null);
7908     }
7909 
7910     /**
7911      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7912      * @hide
7913      */
7914     @Nullable
7915     public OnLongClickListener getOnLongClickListener() {
7916         ListenerInfo li = mListenerInfo;
7917         return (li != null) ? li.mOnLongClickListener : null;
7918     }
7919 
7920     /**
7921      * Register a callback to be invoked when this view is context clicked. If the view is not
7922      * context clickable, it becomes context clickable.
7923      *
7924      * @param l The callback that will run
7925      * @see #setContextClickable(boolean)
7926      */
7927     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7928         if (!isContextClickable()) {
7929             setContextClickable(true);
7930         }
7931         getListenerInfo().mOnContextClickListener = l;
7932     }
7933 
7934     /**
7935      * Register a callback to be invoked when the context menu for this view is
7936      * being built. If this view is not long clickable, it becomes long clickable.
7937      *
7938      * @param l The callback that will run
7939      *
7940      */
7941     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7942         if (!isLongClickable()) {
7943             setLongClickable(true);
7944         }
7945         getListenerInfo().mOnCreateContextMenuListener = l;
7946     }
7947 
7948     /**
7949      * Set an observer to collect stats for each frame rendered for this view.
7950      *
7951      * @hide
7952      */
7953     public void addFrameMetricsListener(Window window,
7954             Window.OnFrameMetricsAvailableListener listener,
7955             Handler handler) {
7956         if (mAttachInfo != null) {
7957             if (mAttachInfo.mThreadedRenderer != null) {
7958                 if (mFrameMetricsObservers == null) {
7959                     mFrameMetricsObservers = new ArrayList<>();
7960                 }
7961 
7962                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7963                 mFrameMetricsObservers.add(fmo);
7964                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7965             } else {
7966                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7967             }
7968         } else {
7969             if (mFrameMetricsObservers == null) {
7970                 mFrameMetricsObservers = new ArrayList<>();
7971             }
7972 
7973             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7974             mFrameMetricsObservers.add(fmo);
7975         }
7976     }
7977 
7978     /**
7979      * Remove observer configured to collect frame stats for this view.
7980      *
7981      * @hide
7982      */
7983     public void removeFrameMetricsListener(
7984             Window.OnFrameMetricsAvailableListener listener) {
7985         ThreadedRenderer renderer = getThreadedRenderer();
7986         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7987         if (fmo == null) {
7988             throw new IllegalArgumentException(
7989                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7990         }
7991 
7992         if (mFrameMetricsObservers != null) {
7993             mFrameMetricsObservers.remove(fmo);
7994             if (renderer != null) {
7995                 renderer.removeObserver(fmo.getRendererObserver());
7996             }
7997         }
7998     }
7999 
8000     private void registerPendingFrameMetricsObservers() {
8001         if (mFrameMetricsObservers != null) {
8002             ThreadedRenderer renderer = getThreadedRenderer();
8003             if (renderer != null) {
8004                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
8005                     renderer.addObserver(fmo.getRendererObserver());
8006                 }
8007             } else {
8008                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
8009             }
8010         }
8011     }
8012 
8013     private FrameMetricsObserver findFrameMetricsObserver(
8014             Window.OnFrameMetricsAvailableListener listener) {
8015         if (mFrameMetricsObservers != null) {
8016             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
8017                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
8018                 if (observer.mListener == listener) {
8019                     return observer;
8020                 }
8021             }
8022         }
8023 
8024         return null;
8025     }
8026 
8027     /** @hide */
8028     public void setNotifyAutofillManagerOnClick(boolean notify) {
8029         if (notify) {
8030             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
8031         } else {
8032             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
8033         }
8034     }
8035 
8036     private void notifyAutofillManagerOnClick() {
8037         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
8038             try {
8039                 getAutofillManager().notifyViewClicked(this);
8040             } finally {
8041                 // Set it to already called so it's not called twice when called by
8042                 // performClickInternal()
8043                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
8044             }
8045         }
8046     }
8047 
8048     /**
8049      * Entry point for {@link #performClick()} - other methods on View should call it instead of
8050      * {@code performClick()} directly to make sure the autofill manager is notified when
8051      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
8052      * method).
8053      */
8054     private boolean performClickInternal() {
8055         // Must notify autofill manager before performing the click actions to avoid scenarios where
8056         // the app has a click listener that changes the state of views the autofill service might
8057         // be interested on.
8058         notifyAutofillManagerOnClick();
8059 
8060         return performClick();
8061     }
8062 
8063     /**
8064      * Call this view's OnClickListener, if it is defined.  Performs all normal
8065      * actions associated with clicking: reporting accessibility event, playing
8066      * a sound, etc.
8067      *
8068      * @return True there was an assigned OnClickListener that was called, false
8069      *         otherwise is returned.
8070      */
8071     // NOTE: other methods on View should not call this method directly, but performClickInternal()
8072     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
8073     // could extend this method without calling super.performClick()).
8074     public boolean performClick() {
8075         // We still need to call this method to handle the cases where performClick() was called
8076         // externally, instead of through performClickInternal()
8077         notifyAutofillManagerOnClick();
8078 
8079         final boolean result;
8080         final ListenerInfo li = mListenerInfo;
8081         if (li != null && li.mOnClickListener != null) {
8082             playSoundEffect(SoundEffectConstants.CLICK);
8083             li.mOnClickListener.onClick(this);
8084             result = true;
8085         } else {
8086             result = false;
8087         }
8088 
8089         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
8090 
8091         notifyEnterOrExitForAutoFillIfNeeded(true);
8092 
8093         return result;
8094     }
8095 
8096     /**
8097      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
8098      * this only calls the listener, and does not do any associated clicking
8099      * actions like reporting an accessibility event.
8100      *
8101      * @return True there was an assigned OnClickListener that was called, false
8102      *         otherwise is returned.
8103      */
8104     public boolean callOnClick() {
8105         ListenerInfo li = mListenerInfo;
8106         if (li != null && li.mOnClickListener != null) {
8107             li.mOnClickListener.onClick(this);
8108             return true;
8109         }
8110         return false;
8111     }
8112 
8113     /**
8114      * Calls this view's OnLongClickListener, if it is defined. Invokes the
8115      * context menu if the OnLongClickListener did not consume the event.
8116      *
8117      * @return {@code true} if one of the above receivers consumed the event,
8118      *         {@code false} otherwise
8119      */
8120     public boolean performLongClick() {
8121         return performLongClickInternal(mLongClickX, mLongClickY);
8122     }
8123 
8124     /**
8125      * Calls this view's OnLongClickListener, if it is defined. Invokes the
8126      * context menu if the OnLongClickListener did not consume the event,
8127      * anchoring it to an (x,y) coordinate.
8128      *
8129      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
8130      *          to disable anchoring
8131      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
8132      *          to disable anchoring
8133      * @return {@code true} if one of the above receivers consumed the event,
8134      *         {@code false} otherwise
8135      */
8136     public boolean performLongClick(float x, float y) {
8137         mLongClickX = x;
8138         mLongClickY = y;
8139         final boolean handled = performLongClick();
8140         mLongClickX = Float.NaN;
8141         mLongClickY = Float.NaN;
8142         return handled;
8143     }
8144 
8145     /**
8146      * Calls this view's OnLongClickListener, if it is defined. Invokes the
8147      * context menu if the OnLongClickListener did not consume the event,
8148      * optionally anchoring it to an (x,y) coordinate.
8149      *
8150      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
8151      *          to disable anchoring
8152      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
8153      *          to disable anchoring
8154      * @return {@code true} if one of the above receivers consumed the event,
8155      *         {@code false} otherwise
8156      */
8157     private boolean performLongClickInternal(float x, float y) {
8158         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
8159 
8160         boolean handled = false;
8161         final OnLongClickListener listener =
8162                 mListenerInfo == null ? null : mListenerInfo.mOnLongClickListener;
8163         boolean shouldPerformHapticFeedback = true;
8164         if (listener != null) {
8165             handled = listener.onLongClick(View.this);
8166             if (handled) {
8167                 shouldPerformHapticFeedback = listener.onLongClickUseDefaultHapticFeedback(
8168                         View.this);
8169             }
8170         }
8171         if (!handled) {
8172             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
8173             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
8174         }
8175         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
8176             if (!handled) {
8177                 handled = showLongClickTooltip((int) x, (int) y);
8178             }
8179         }
8180         if (handled && shouldPerformHapticFeedback) {
8181             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
8182         }
8183         return handled;
8184     }
8185 
8186     /**
8187      * Call this view's OnContextClickListener, if it is defined.
8188      *
8189      * @param x the x coordinate of the context click
8190      * @param y the y coordinate of the context click
8191      * @return True if there was an assigned OnContextClickListener that consumed the event, false
8192      *         otherwise.
8193      */
8194     public boolean performContextClick(float x, float y) {
8195         return performContextClick();
8196     }
8197 
8198     /**
8199      * Call this view's OnContextClickListener, if it is defined.
8200      *
8201      * @return True if there was an assigned OnContextClickListener that consumed the event, false
8202      *         otherwise.
8203      */
8204     public boolean performContextClick() {
8205         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
8206 
8207         boolean handled = false;
8208         ListenerInfo li = mListenerInfo;
8209         if (li != null && li.mOnContextClickListener != null) {
8210             handled = li.mOnContextClickListener.onContextClick(View.this);
8211         }
8212         if (handled) {
8213             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
8214         }
8215         return handled;
8216     }
8217 
8218     /**
8219      * Performs button-related actions during a touch down event.
8220      *
8221      * @param event The event.
8222      * @return True if the down was consumed.
8223      *
8224      * @hide
8225      */
8226     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
8227         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
8228             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
8229             showContextMenu(event.getX(), event.getY());
8230             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8231             return true;
8232         }
8233         return false;
8234     }
8235 
8236     /**
8237      * Shows the context menu for this view.
8238      *
8239      * @return {@code true} if the context menu was shown, {@code false}
8240      *         otherwise
8241      * @see #showContextMenu(float, float)
8242      */
8243     public boolean showContextMenu() {
8244         return getParent().showContextMenuForChild(this);
8245     }
8246 
8247     /**
8248      * Shows the context menu for this view anchored to the specified
8249      * view-relative coordinate.
8250      *
8251      * @param x the X coordinate in pixels relative to the view to which the
8252      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
8253      * @param y the Y coordinate in pixels relative to the view to which the
8254      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
8255      * @return {@code true} if the context menu was shown, {@code false}
8256      *         otherwise
8257      */
8258     public boolean showContextMenu(float x, float y) {
8259         return getParent().showContextMenuForChild(this, x, y);
8260     }
8261 
8262     /**
8263      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
8264      *
8265      * @param callback Callback that will control the lifecycle of the action mode
8266      * @return The new action mode if it is started, null otherwise
8267      *
8268      * @see ActionMode
8269      * @see #startActionMode(android.view.ActionMode.Callback, int)
8270      */
8271     public ActionMode startActionMode(ActionMode.Callback callback) {
8272         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
8273     }
8274 
8275     /**
8276      * Start an action mode with the given type.
8277      *
8278      * @param callback Callback that will control the lifecycle of the action mode
8279      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
8280      * @return The new action mode if it is started, null otherwise
8281      *
8282      * @see ActionMode
8283      */
8284     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
8285         ViewParent parent = getParent();
8286         if (parent == null) return null;
8287         try {
8288             return parent.startActionModeForChild(this, callback, type);
8289         } catch (AbstractMethodError ame) {
8290             // Older implementations of custom views might not implement this.
8291             return parent.startActionModeForChild(this, callback);
8292         }
8293     }
8294 
8295     /**
8296      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
8297      * Context, creating a unique View identifier to retrieve the result.
8298      *
8299      * @param intent The Intent to be started.
8300      * @param requestCode The request code to use.
8301      * @hide
8302      */
8303     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
8304     public void startActivityForResult(Intent intent, int requestCode) {
8305         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
8306         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
8307     }
8308 
8309     /**
8310      * If this View corresponds to the calling who, dispatches the activity result.
8311      * @param who The identifier for the targeted View to receive the result.
8312      * @param requestCode The integer request code originally supplied to
8313      *                    startActivityForResult(), allowing you to identify who this
8314      *                    result came from.
8315      * @param resultCode The integer result code returned by the child activity
8316      *                   through its setResult().
8317      * @param data An Intent, which can return result data to the caller
8318      *               (various data can be attached to Intent "extras").
8319      * @return {@code true} if the activity result was dispatched.
8320      * @hide
8321      */
8322     public boolean dispatchActivityResult(
8323             String who, int requestCode, int resultCode, Intent data) {
8324         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
8325             onActivityResult(requestCode, resultCode, data);
8326             mStartActivityRequestWho = null;
8327             return true;
8328         }
8329         return false;
8330     }
8331 
8332     /**
8333      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
8334      *
8335      * @param requestCode The integer request code originally supplied to
8336      *                    startActivityForResult(), allowing you to identify who this
8337      *                    result came from.
8338      * @param resultCode The integer result code returned by the child activity
8339      *                   through its setResult().
8340      * @param data An Intent, which can return result data to the caller
8341      *               (various data can be attached to Intent "extras").
8342      * @hide
8343      */
8344     public void onActivityResult(int requestCode, int resultCode, Intent data) {
8345         // Do nothing.
8346     }
8347 
8348     /**
8349      * Register a callback to be invoked when a hardware key is pressed in this view.
8350      * Key presses in software input methods will generally not trigger the methods of
8351      * this listener.
8352      * @param l the key listener to attach to this view
8353      */
8354     public void setOnKeyListener(OnKeyListener l) {
8355         getListenerInfo().mOnKeyListener = l;
8356     }
8357 
8358     /**
8359      * Register a callback to be invoked when a touch event is sent to this view.
8360      * @param l the touch listener to attach to this view
8361      */
8362     public void setOnTouchListener(OnTouchListener l) {
8363         getListenerInfo().mOnTouchListener = l;
8364     }
8365 
8366     /**
8367      * Register a callback to be invoked when a generic motion event is sent to this view.
8368      * @param l the generic motion listener to attach to this view
8369      */
8370     public void setOnGenericMotionListener(OnGenericMotionListener l) {
8371         getListenerInfo().mOnGenericMotionListener = l;
8372     }
8373 
8374     /**
8375      * Register a callback to be invoked when a hover event is sent to this view.
8376      * @param l the hover listener to attach to this view
8377      */
8378     public void setOnHoverListener(OnHoverListener l) {
8379         getListenerInfo().mOnHoverListener = l;
8380     }
8381 
8382     /**
8383      * Register a drag event listener callback object for this View. The parameter is
8384      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
8385      * View, the system calls the
8386      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
8387      * @param l An implementation of {@link android.view.View.OnDragListener}.
8388      */
8389     public void setOnDragListener(OnDragListener l) {
8390         getListenerInfo().mOnDragListener = l;
8391     }
8392 
8393     /**
8394      * Give this view focus. This will cause
8395      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
8396      *
8397      * Note: this does not check whether this {@link View} should get focus, it just
8398      * gives it focus no matter what.  It should only be called internally by framework
8399      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
8400      *
8401      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
8402      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
8403      *        focus moved when requestFocus() is called. It may not always
8404      *        apply, in which case use the default View.FOCUS_DOWN.
8405      * @param previouslyFocusedRect The rectangle of the view that had focus
8406      *        prior in this View's coordinate system.
8407      */
8408     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
8409         if (DBG) {
8410             System.out.println(this + " requestFocus()");
8411         }
8412 
8413         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
8414             mPrivateFlags |= PFLAG_FOCUSED;
8415 
8416             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
8417 
8418             if (mParent != null) {
8419                 mParent.requestChildFocus(this, this);
8420                 updateFocusedInCluster(oldFocus, direction);
8421             }
8422 
8423             if (mAttachInfo != null) {
8424                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
8425             }
8426 
8427             onFocusChanged(true, direction, previouslyFocusedRect);
8428             refreshDrawableState();
8429         }
8430     }
8431 
8432     /**
8433      * Sets this view's preference for reveal behavior when it gains focus.
8434      *
8435      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
8436      * this view would prefer to be brought fully into view when it gains focus.
8437      * For example, a text field that a user is meant to type into. Other views such
8438      * as scrolling containers may prefer to opt-out of this behavior.</p>
8439      *
8440      * <p>The default value for views is true, though subclasses may change this
8441      * based on their preferred behavior.</p>
8442      *
8443      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
8444      *
8445      * @see #getRevealOnFocusHint()
8446      */
8447     public final void setRevealOnFocusHint(boolean revealOnFocus) {
8448         if (revealOnFocus) {
8449             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
8450         } else {
8451             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
8452         }
8453     }
8454 
8455     /**
8456      * Returns this view's preference for reveal behavior when it gains focus.
8457      *
8458      * <p>When this method returns true for a child view requesting focus, ancestor
8459      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
8460      * should make a best effort to make the newly focused child fully visible to the user.
8461      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
8462      * other properties affecting visibility to the user as part of the focus change.</p>
8463      *
8464      * @return true if this view would prefer to become fully visible when it gains focus,
8465      *         false if it would prefer not to disrupt scroll positioning
8466      *
8467      * @see #setRevealOnFocusHint(boolean)
8468      */
8469     public final boolean getRevealOnFocusHint() {
8470         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
8471     }
8472 
8473     /**
8474      * Populates <code>outRect</code> with the hotspot bounds. By default,
8475      * the hotspot bounds are identical to the screen bounds.
8476      *
8477      * @param outRect rect to populate with hotspot bounds
8478      * @hide Only for internal use by views and widgets.
8479      */
8480     public void getHotspotBounds(Rect outRect) {
8481         final Drawable background = getBackground();
8482         if (background != null) {
8483             background.getHotspotBounds(outRect);
8484         } else {
8485             getBoundsOnScreen(outRect);
8486         }
8487     }
8488 
8489     /**
8490      * Request that a rectangle of this view be visible on the screen,
8491      * scrolling if necessary just enough.
8492      *
8493      * <p>A View should call this if it maintains some notion of which part
8494      * of its content is interesting.  For example, a text editing view
8495      * should call this when its cursor moves.
8496      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
8497      * It should not be affected by which part of the View is currently visible or its scroll
8498      * position.
8499      *
8500      * @param rectangle The rectangle in the View's content coordinate space
8501      * @return Whether any parent scrolled.
8502      * @see AccessibilityAction#ACTION_SHOW_ON_SCREEN
8503      */
8504     public boolean requestRectangleOnScreen(Rect rectangle) {
8505         return requestRectangleOnScreen(rectangle, false);
8506     }
8507 
8508     /**
8509      * Request that a rectangle of this view be visible on the screen,
8510      * scrolling if necessary just enough.
8511      *
8512      * <p>A View should call this if it maintains some notion of which part
8513      * of its content is interesting.  For example, a text editing view
8514      * should call this when its cursor moves.
8515      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
8516      * It should not be affected by which part of the View is currently visible or its scroll
8517      * position.
8518      * <p>When <code>immediate</code> is set to true, scrolling will not be
8519      * animated.
8520      *
8521      * @param rectangle The rectangle in the View's content coordinate space
8522      * @param immediate True to forbid animated scrolling, false otherwise
8523      * @return Whether any parent scrolled.
8524      */
8525     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
8526         if (mParent == null) {
8527             return false;
8528         }
8529 
8530         View child = this;
8531 
8532         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
8533         position.set(rectangle);
8534 
8535         ViewParent parent = mParent;
8536         boolean scrolled = false;
8537         while (parent != null) {
8538             rectangle.set((int) position.left, (int) position.top,
8539                     (int) position.right, (int) position.bottom);
8540 
8541             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
8542 
8543             if (!(parent instanceof View)) {
8544                 break;
8545             }
8546 
8547             // move it from child's content coordinate space to parent's content coordinate space
8548             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
8549 
8550             child = (View) parent;
8551             parent = child.getParent();
8552         }
8553 
8554         return scrolled;
8555     }
8556 
8557     /**
8558      * Called when this view wants to give up focus. If focus is cleared
8559      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
8560      * <p>
8561      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
8562      * to the first focusable View from the top after focus is cleared. Hence, if this
8563      * View is the first from the top that can take focus, then all callbacks
8564      * related to clearing focus will be invoked after which the framework will
8565      * give focus to this view.
8566      * </p>
8567      */
8568     public void clearFocus() {
8569         if (DBG) {
8570             System.out.println(this + " clearFocus()");
8571         }
8572 
8573         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
8574         clearFocusInternal(null, true, refocus);
8575     }
8576 
8577     /**
8578      * Clears focus from the view, optionally propagating the change up through
8579      * the parent hierarchy and requesting that the root view place new focus.
8580      *
8581      * @param propagate whether to propagate the change up through the parent
8582      *            hierarchy
8583      * @param refocus when propagate is true, specifies whether to request the
8584      *            root view place new focus
8585      * @hide
8586      */
8587     public void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
8588         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
8589             mPrivateFlags &= ~PFLAG_FOCUSED;
8590             clearParentsWantFocus();
8591 
8592             if (propagate && mParent != null) {
8593                 mParent.clearChildFocus(this);
8594             }
8595 
8596             onFocusChanged(false, 0, null);
8597             refreshDrawableState();
8598 
8599             if (propagate && (!refocus || !rootViewRequestFocus())) {
8600                 notifyGlobalFocusCleared(this);
8601             }
8602         }
8603     }
8604 
8605     void notifyGlobalFocusCleared(View oldFocus) {
8606         if (oldFocus != null && mAttachInfo != null) {
8607             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
8608         }
8609     }
8610 
8611     boolean rootViewRequestFocus() {
8612         final View root = getRootView();
8613         return root != null && root.requestFocus();
8614     }
8615 
8616     /**
8617      * Called internally by the view system when a new view is getting focus.
8618      * This is what clears the old focus.
8619      * <p>
8620      * <b>NOTE:</b> The parent view's focused child must be updated manually
8621      * after calling this method. Otherwise, the view hierarchy may be left in
8622      * an inconstent state.
8623      */
8624     void unFocus(View focused) {
8625         if (DBG) {
8626             System.out.println(this + " unFocus()");
8627         }
8628 
8629         clearFocusInternal(focused, false, false);
8630     }
8631 
8632     /**
8633      * Returns true if this view has focus itself, or is the ancestor of the
8634      * view that has focus.
8635      *
8636      * @return True if this view has or contains focus, false otherwise.
8637      */
8638     @ViewDebug.ExportedProperty(category = "focus")
8639     public boolean hasFocus() {
8640         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8641     }
8642 
8643     /**
8644      * Returns true if this view is focusable or if it contains a reachable View
8645      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
8646      * is a view whose parents do not block descendants focus.
8647      * Only {@link #VISIBLE} views are considered focusable.
8648      *
8649      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8650      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8651      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8652      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8653      * {@code false} for views not explicitly marked as focusable.
8654      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8655      * behavior.</p>
8656      *
8657      * @return {@code true} if the view is focusable or if the view contains a focusable
8658      *         view, {@code false} otherwise
8659      *
8660      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8661      * @see ViewGroup#getTouchscreenBlocksFocus()
8662      * @see #hasExplicitFocusable()
8663      */
8664     public boolean hasFocusable() {
8665         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8666     }
8667 
8668     /**
8669      * Returns true if this view is focusable or if it contains a reachable View
8670      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8671      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8672      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8673      * {@link #FOCUSABLE} are considered focusable.
8674      *
8675      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8676      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8677      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8678      * to focusable will not.</p>
8679      *
8680      * @return {@code true} if the view is focusable or if the view contains a focusable
8681      *         view, {@code false} otherwise
8682      *
8683      * @see #hasFocusable()
8684      */
8685     public boolean hasExplicitFocusable() {
8686         return hasFocusable(false, true);
8687     }
8688 
8689     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8690         if (!isFocusableInTouchMode()) {
8691             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8692                 final ViewGroup g = (ViewGroup) p;
8693                 if (g.shouldBlockFocusForTouchscreen()) {
8694                     return false;
8695                 }
8696             }
8697         }
8698 
8699         // Invisible, gone, or disabled views are never focusable.
8700         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8701                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8702             return false;
8703         }
8704 
8705         // Only use effective focusable value when allowed.
8706         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8707             return true;
8708         }
8709 
8710         return false;
8711     }
8712 
8713     /**
8714      * Called by the view system when the focus state of this view changes.
8715      * When the focus change event is caused by directional navigation, direction
8716      * and previouslyFocusedRect provide insight into where the focus is coming from.
8717      * When overriding, be sure to call up through to the super class so that
8718      * the standard focus handling will occur.
8719      *
8720      * @param gainFocus True if the View has focus; false otherwise.
8721      * @param direction The direction focus has moved when requestFocus()
8722      *                  is called to give this view focus. Values are
8723      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8724      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8725      *                  It may not always apply, in which case use the default.
8726      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8727      *        system, of the previously focused view.  If applicable, this will be
8728      *        passed in as finer grained information about where the focus is coming
8729      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8730      */
8731     @CallSuper
8732     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8733             @Nullable Rect previouslyFocusedRect) {
8734         if (DBG) {
8735             Log.d(VIEW_LOG_TAG, "onFocusChanged() entered. gainFocus: "
8736                     + gainFocus);
8737         }
8738         if (gainFocus) {
8739             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8740         } else {
8741             notifyViewAccessibilityStateChangedIfNeeded(
8742                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8743         }
8744 
8745         // Here we check whether we still need the default focus highlight, and switch it on/off.
8746         switchDefaultFocusHighlight();
8747 
8748         if (!gainFocus) {
8749             if (isPressed()) {
8750                 setPressed(false);
8751             }
8752             if (hasWindowFocus()) {
8753                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8754             }
8755             onFocusLost();
8756         } else if (hasWindowFocus()) {
8757             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8758             ViewRootImpl viewRoot = getViewRootImpl();
8759             if (viewRoot != null) {
8760                 if (mIsHandwritingDelegate) {
8761                     viewRoot.getHandwritingInitiator().onDelegateViewFocused(this);
8762                 } else if (initiationWithoutInputConnection() && onCheckIsTextEditor()) {
8763                     viewRoot.getHandwritingInitiator().onEditorFocused(this);
8764                 }
8765             }
8766         }
8767 
8768         invalidate(true);
8769         ListenerInfo li = mListenerInfo;
8770         if (li != null && li.mOnFocusChangeListener != null) {
8771             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8772         }
8773 
8774         if (mAttachInfo != null) {
8775             mAttachInfo.mKeyDispatchState.reset(this);
8776         }
8777 
8778         if (mParent != null) {
8779             mParent.onDescendantUnbufferedRequested();
8780         }
8781 
8782         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8783         updatePreferKeepClearForFocus();
8784     }
8785 
8786     /**
8787      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8788      *
8789      * @param hasFocus {@code true} when the {@link View} is being focused.
8790      */
8791     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8792         if (mAttachInfo == null) {
8793             return;
8794         }
8795         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8796     }
8797 
8798     /** @hide */
8799     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8800         if (canNotifyAutofillEnterExitEvent()) {
8801             AutofillManager afm = getAutofillManager();
8802             if (afm != null) {
8803                 if (DBG) {
8804                     Log.d(VIEW_LOG_TAG, this + " afm is not null");
8805                 }
8806                 if (enter) {
8807                     // We have not been laid out yet, hence cannot evaluate
8808                     // whether this view is visible to the user, we will do
8809                     // the evaluation once layout is complete.
8810                     // Sometimes, views are already laid out, but it's still
8811                     // not visible to the user, we also do the evaluation once
8812                     // the view is visible. ex: There is a fade-in animation
8813                     // for the activity, the view will be laid out when the
8814                     // animation beginning. On the time, the view is not visible
8815                     // to the user. And then as the animation progresses, the view
8816                     // becomes visible to the user.
8817                     if (DBG) {
8818                         Log.d(VIEW_LOG_TAG,
8819                                 "notifyEnterOrExitForAutoFillIfNeeded:"
8820                                 + " isLaidOut(): " + isLaidOut()
8821                                 + " isVisibleToUser(): " + isVisibleToUser()
8822                                 + " isFocused(): " + isFocused());
8823                     }
8824                     if (!isLaidOut() || !isVisibleToUser()) {
8825                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8826                     } else if (isVisibleToUser()) {
8827                         if (isFocused()) {
8828                             // TODO This is a potential problem that View gets focus before it's
8829                             // visible to User. Ideally View should handle the event when
8830                             // isVisibleToUser() becomes true where it should issue
8831                             // notifyViewEntered().
8832                             afm.notifyViewEntered(this);
8833                         } else {
8834                             afm.notifyViewEnteredForFillDialog(this);
8835                         }
8836                     }
8837                 } else if (!isFocused()) {
8838                     afm.notifyViewExited(this);
8839                 }
8840             }
8841         }
8842     }
8843 
8844     /**
8845      * Visually distinct portion of a window with window-like semantics are considered panes for
8846      * accessibility purposes. One example is the content view of a large fragment that is replaced.
8847      * In order for accessibility services to understand a pane's window-like behavior, panes
8848      * should have descriptive titles. Views with pane titles produce
8849      * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}s when they appear, disappear, or change
8850      * title.
8851      *
8852      * <p>
8853      * When transitioning from one Activity to another, instead of using
8854      * {@code setAccessibilityPaneTitle()}, set a descriptive title for its window by using
8855      * {@code android:label}
8856      * for the matching Activity entry in your application's manifest or updating the title at
8857      * runtime with {@link android.app.Activity#setTitle(CharSequence)}.
8858      *
8859      * <p>
8860      * <aside>
8861      * <b>Note:</b> Use
8862      * {@link androidx.core.view.ViewCompat#setAccessibilityPaneTitle(View, CharSequence)}
8863      * for backwards-compatibility.
8864      * </aside>
8865      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8866      *                               View is not a pane.
8867      *
8868      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8869      *
8870      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8871      */
8872     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8873         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8874             boolean currentPaneTitleEmpty = mAccessibilityPaneTitle == null;
8875             boolean newPaneTitleEmpty =  accessibilityPaneTitle == null;
8876             mAccessibilityPaneTitle = accessibilityPaneTitle;
8877             // Make explicitly important as nulled titles need to be important for DISAPPEARED
8878             // events.
8879             if (mAccessibilityPaneTitle != null
8880                     && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8881                 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8882             }
8883             if (currentPaneTitleEmpty) {
8884                 notifyViewAccessibilityStateChangedIfNeeded(
8885                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED);
8886             } else if (newPaneTitleEmpty) {
8887                 notifyViewAccessibilityStateChangedIfNeeded(
8888                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
8889             } else {
8890                 notifyViewAccessibilityStateChangedIfNeeded(
8891                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8892             }
8893         }
8894     }
8895 
8896     /**
8897      * Get the title of the pane for purposes of accessibility.
8898      *
8899      * @return The current pane title.
8900      *
8901      * {@see #setAccessibilityPaneTitle}.
8902      *
8903      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8904      */
8905     @InspectableProperty
8906     @Nullable
8907     public CharSequence getAccessibilityPaneTitle() {
8908         return mAccessibilityPaneTitle;
8909     }
8910 
8911     private boolean isAccessibilityPane() {
8912         return mAccessibilityPaneTitle != null;
8913     }
8914 
8915     /**
8916      * Sends an accessibility event of the given type. If accessibility is
8917      * not enabled this method has no effect. The default implementation calls
8918      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8919      * to populate information about the event source (this View), then calls
8920      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8921      * populate the text content of the event source including its descendants,
8922      * then for events type {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
8923      * and {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} with
8924      * subtype {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION},
8925      * throttle the events, and last calls
8926      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8927      * on its parent to request sending of the event to interested parties.
8928      * <p>
8929      * If an {@link AccessibilityDelegate} has been specified via calling
8930      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8931      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8932      * responsible for handling this call.
8933      * </p>
8934      * <p>
8935      * If this view uses {@link AccessibilityNodeProvider} to provide virtual view hierarchy rooted
8936      * at this view, this method should not be called to send events from virtual children because
8937      * it will populate the events with wrong information and the events should be throttled per
8938      * child instead at the virtual root level. To send events from virtual children, call
8939      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} on the view's
8940      * parent to request sending of the event to interested parties.
8941      * </p>
8942      *
8943      * @param eventType The type of the event to send, as defined by several types from
8944      * {@link AccessibilityEvent}, such as
8945      * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} or
8946      * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8947      *
8948      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8949      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8950      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8951      * @see AccessibilityDelegate
8952      */
8953     public void sendAccessibilityEvent(int eventType) {
8954         if (mAccessibilityDelegate != null) {
8955             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8956         } else {
8957             sendAccessibilityEventInternal(eventType);
8958         }
8959     }
8960 
8961     /**
8962      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} {@link
8963      * AccessibilityEvent} to suggest that an accessibility service announce the specified text to
8964      * its users.
8965      *
8966      * <p>Note: The event generated with this API carries no semantic meaning, and accessibility
8967      * services may choose to ignore it. Apps that accurately supply accessibility with the
8968      * semantics of their UI should not need to specify what exactly is announced.
8969      *
8970      * <p>In general, do not attempt to generate announcements as confirmation message for simple
8971      * actions like a button press. Label your controls concisely and precisely instead.
8972      *
8973      * <p>To convey significant UI changes like window changes, use {@link
8974      * android.app.Activity#setTitle(CharSequence)} and {@link
8975      * #setAccessibilityPaneTitle(CharSequence)}.
8976      *
8977      * <p>Use {@link #setAccessibilityLiveRegion(int)} to inform the user of changes to critical
8978      * views within the user interface. These should still be used sparingly as they may generate
8979      * announcements every time a View is updated.
8980      *
8981      * <p>Use {@link #setStateDescription(CharSequence)} to convey state changes to views within the
8982      * user interface. While a live region may send different types of events generated by the view,
8983      * state description will send {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events of
8984      * type {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION}.
8985      *
8986      * <p>For notifying users about errors, such as in a login screen with text that displays an
8987      * "incorrect password" notification, set {@link AccessibilityNodeInfo#setError(CharSequence)}
8988      * and dispatch an {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event with a change
8989      * type of {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR}, instead. Some widgets may
8990      * expose methods that convey error states to accessibility automatically, such as {@link
8991      * android.widget.TextView#setError(CharSequence)}, which manages these accessibility semantics
8992      * and event dispatch for callers.
8993      *
8994      * @deprecated Use one of the methods described in the documentation above to semantically
8995      *     describe UI instead of using an announcement, as accessibility services may choose to
8996      *     ignore events dispatched with this method.
8997      * @param text The announcement text.
8998      */
8999     @FlaggedApi(FLAG_DEPRECATE_ACCESSIBILITY_ANNOUNCEMENT_APIS)
9000     @Deprecated
9001     public void announceForAccessibility(CharSequence text) {
9002         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
9003             AccessibilityEvent event = AccessibilityEvent.obtain(
9004                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
9005             onInitializeAccessibilityEvent(event);
9006             event.getText().add(text);
9007             event.setContentDescription(null);
9008             mParent.requestSendAccessibilityEvent(this, event);
9009         }
9010     }
9011 
9012     /**
9013      * @see #sendAccessibilityEvent(int)
9014      *
9015      * Note: Called from the default {@link AccessibilityDelegate}.
9016      *
9017      * @hide
9018      */
9019     public void sendAccessibilityEventInternal(int eventType) {
9020         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9021             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
9022         }
9023     }
9024 
9025     /**
9026      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
9027      * takes as an argument an empty {@link AccessibilityEvent} and does not
9028      * perform a check whether accessibility is enabled.
9029      * <p>
9030      * If an {@link AccessibilityDelegate} has been specified via calling
9031      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9032      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
9033      * is responsible for handling this call.
9034      * </p>
9035      *
9036      * @param event The event to send.
9037      *
9038      * @see #sendAccessibilityEvent(int)
9039      */
9040     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
9041         if (mAccessibilityDelegate != null) {
9042             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9043         } else {
9044             sendAccessibilityEventUncheckedInternal(event);
9045         }
9046     }
9047 
9048     /**
9049      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
9050      *
9051      * Note: Called from the default {@link AccessibilityDelegate}.
9052      *
9053      * @hide
9054      */
9055     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
9056         // Panes disappearing are relevant even if though the view is no longer visible.
9057         boolean isWindowStateChanged =
9058                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
9059         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
9060                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
9061         boolean detached = detached();
9062         if (!isShown() && !isWindowDisappearedEvent && !detached) {
9063             return;
9064         }
9065         onInitializeAccessibilityEvent(event);
9066         // Only a subset of accessibility events populates text content.
9067         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
9068             dispatchPopulateAccessibilityEvent(event);
9069         }
9070         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
9071         if (throttle != null) {
9072             throttle.post(event);
9073         } else if (!isWindowDisappearedEvent && detached) {
9074             // Views could be attached soon later. Accessibility events during this temporarily
9075             // detached period should be sent too.
9076             postDelayed(() -> {
9077                 if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
9078                     requestParentSendAccessibilityEvent(event);
9079                 }
9080             }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
9081         } else {
9082             requestParentSendAccessibilityEvent(event);
9083         }
9084     }
9085 
9086     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
9087         ViewParent parent = getParent();
9088         if (parent != null) {
9089             getParent().requestSendAccessibilityEvent(this, event);
9090         }
9091     }
9092 
9093     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
9094             AccessibilityEvent event) {
9095         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
9096             if (mSendViewScrolledAccessibilityEvent == null) {
9097                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
9098             }
9099             return mSendViewScrolledAccessibilityEvent;
9100         }
9101         boolean isStateContentChanged = (event.getContentChangeTypes()
9102                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
9103         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
9104                 && isStateContentChanged) {
9105             if (mSendStateChangedAccessibilityEvent == null) {
9106                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
9107             }
9108             return mSendStateChangedAccessibilityEvent;
9109         }
9110         return null;
9111     }
9112 
9113     private void clearAccessibilityThrottles() {
9114         cancel(mSendViewScrolledAccessibilityEvent);
9115         cancel(mSendStateChangedAccessibilityEvent);
9116     }
9117 
9118     /**
9119      * Dispatches an {@link AccessibilityEvent} to the {@link View} to add the text content of the
9120      * view and its children.
9121      * <p>
9122      * <b>Note:</b> This method should only be used with event.setText().
9123      * Avoid mutating other event state in this method. In general, put UI metadata in the node for
9124      * services to easily query.
9125      * <ul>
9126      *     <li> If you are modifying other event properties, you may be eliminating semantics
9127      *     accessibility services may want. Instead, send a separate event using
9128      *     {@link #sendAccessibilityEvent(int)} and override
9129      *     {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
9130      *     </li>
9131      *     <li>If you are checking for type {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
9132      *     to generate window/title announcements, you may be causing disruptive announcements
9133      *     (or making no announcements at all). Instead, follow the practices described in
9134      *     {@link View#announceForAccessibility(CharSequence)}. <b>Note:</b> this does not suggest
9135      *     calling announceForAccessibility(), but using the suggestions listed in its
9136      *     documentation.
9137      *     </li>
9138      *     <li>If you are making changes based on the state of accessibility, such as checking for
9139      *     an event type to trigger a UI update, while well-intentioned, you are creating brittle,
9140      *     less well-maintained code that works for some users but not others. Instead, leverage
9141      *     existing code for equitable experiences and less technical debt. See
9142      *     {@link AccessibilityManager#isEnabled()} for an example.
9143      *     </li>
9144      * </ul>
9145      * <p>
9146      * Note that the event text is populated in a separate dispatch path
9147      * ({@link #onPopulateAccessibilityEvent(AccessibilityEvent)}) since we add to the
9148      * event not only the text of the source but also the text of all its descendants.
9149      * <p>
9150      * A typical implementation will call
9151      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on this view
9152      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
9153      * on each child or the first child that is visible. Override this method if custom population
9154      * of the event text content is required.
9155      *
9156      * <p>
9157      * If an {@link AccessibilityDelegate} has been specified via calling
9158      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9159      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
9160      * is responsible for handling this call.
9161      * </p>
9162      * <p>
9163      * If this view sets {@link #isAccessibilityDataSensitive()} then this view should only append
9164      * sensitive information to an event that also sets
9165      * {@link AccessibilityEvent#isAccessibilityDataSensitive()}.
9166      * </p>
9167      * <p>
9168      * <em>Note:</em> Accessibility events of certain types are not dispatched for
9169      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
9170      * </p>
9171      *
9172      * @param event The event.
9173      *
9174      * @return True if the event population was completed.
9175      */
9176     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
9177         if (mAccessibilityDelegate != null) {
9178             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
9179         } else {
9180             return dispatchPopulateAccessibilityEventInternal(event);
9181         }
9182     }
9183 
9184     /**
9185      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
9186      *
9187      * Note: Called from the default {@link AccessibilityDelegate}.
9188      *
9189      * @hide
9190      */
9191     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
9192         onPopulateAccessibilityEvent(event);
9193         return false;
9194     }
9195 
9196     /**
9197      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
9198      * giving a chance to this View to populate the accessibility event with its
9199      * text content.
9200      * <p>
9201      * <b>Note:</b> This method should only be used with event.setText().
9202      * Avoid mutating other event state in this method. Instead, follow the practices described in
9203      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}. In general, put UI
9204      * metadata in the node for services to easily query, than in transient events.
9205      * <p>
9206      * Example: Adding formatted date string to an accessibility event in addition
9207      *          to the text added by the super implementation:
9208      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
9209      *     super.onPopulateAccessibilityEvent(event);
9210      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
9211      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
9212      *         mCurrentDate.getTimeInMillis(), flags);
9213      *     event.getText().add(selectedDateUtterance);
9214      * }</pre>
9215      * <p>
9216      * If an {@link AccessibilityDelegate} has been specified via calling
9217      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9218      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
9219      * is responsible for handling this call.
9220      * </p>
9221      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
9222      * information to the event, in case the default implementation has basic information to add.
9223      * </p>
9224      *
9225      * @param event The accessibility event which to populate.
9226      *
9227      * @see #sendAccessibilityEvent(int)
9228      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
9229      */
9230     @CallSuper
9231     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
9232         if (mAccessibilityDelegate != null) {
9233             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
9234         } else {
9235             onPopulateAccessibilityEventInternal(event);
9236         }
9237     }
9238 
9239     /**
9240      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
9241      *
9242      * Note: Called from the default {@link AccessibilityDelegate}.
9243      *
9244      * @hide
9245      */
9246     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
9247         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
9248                 && isAccessibilityPane()) {
9249             event.getText().add(getAccessibilityPaneTitle());
9250         }
9251     }
9252 
9253     /**
9254      * Initializes an {@link AccessibilityEvent} with information about
9255      * this View which is the event source. In other words, the source of
9256      * an accessibility event is the view whose state change triggered firing
9257      * the event.
9258      * <p>
9259      * Example: Setting the password property of an event in addition
9260      *          to properties set by the super implementation:
9261      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
9262      *     super.onInitializeAccessibilityEvent(event);
9263      *     event.setPassword(true);
9264      * }</pre>
9265      * <p>
9266      * If an {@link AccessibilityDelegate} has been specified via calling
9267      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9268      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
9269      * is responsible for handling this call.
9270      * </p>
9271      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
9272      * information to the event, in case the default implementation has basic information to add.
9273      * </p>
9274      * @param event The event to initialize.
9275      *
9276      * @see #sendAccessibilityEvent(int)
9277      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
9278      */
9279     @CallSuper
9280     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
9281         if (mAccessibilityDelegate != null) {
9282             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
9283         } else {
9284             onInitializeAccessibilityEventInternal(event);
9285         }
9286     }
9287 
9288     /**
9289      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
9290      *
9291      * Note: Called from the default {@link AccessibilityDelegate}.
9292      *
9293      * @hide
9294      */
9295     @UnsupportedAppUsage
9296     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
9297         event.setSource(this);
9298         event.setClassName(getAccessibilityClassName());
9299         event.setPackageName(getContext().getPackageName());
9300         event.setEnabled(isEnabled());
9301         event.setContentDescription(mContentDescription);
9302         event.setScrollX(getScrollX());
9303         event.setScrollY(getScrollY());
9304 
9305         switch (event.getEventType()) {
9306             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
9307                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
9308                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
9309                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
9310                 event.setItemCount(focusablesTempList.size());
9311                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
9312                 if (mAttachInfo != null) {
9313                     focusablesTempList.clear();
9314                 }
9315             } break;
9316             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
9317                 CharSequence text = getIterableTextForAccessibility();
9318                 if (text != null && text.length() > 0) {
9319                     event.setFromIndex(getAccessibilitySelectionStart());
9320                     event.setToIndex(getAccessibilitySelectionEnd());
9321                     event.setItemCount(text.length());
9322                 }
9323             } break;
9324         }
9325     }
9326 
9327     /**
9328      * Returns an {@link AccessibilityNodeInfo} representing this view from the
9329      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
9330      * This method is responsible for obtaining an accessibility node info from a
9331      * pool of reusable instances and calling
9332      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
9333      * initialize the former.
9334      * <p>
9335      * Note: The client is responsible for recycling the obtained instance by calling
9336      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
9337      * </p>
9338      *
9339      * @return A populated {@link AccessibilityNodeInfo}.
9340      *
9341      * @see AccessibilityNodeInfo
9342      */
9343     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
9344         if (mAccessibilityDelegate != null) {
9345             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
9346         } else {
9347             return createAccessibilityNodeInfoInternal();
9348         }
9349     }
9350 
9351     /**
9352      * @see #createAccessibilityNodeInfo()
9353      *
9354      * @hide
9355      */
9356     public @Nullable AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
9357         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9358         if (provider != null) {
9359             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
9360         } else {
9361             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
9362             onInitializeAccessibilityNodeInfo(info);
9363             return info;
9364         }
9365     }
9366 
9367     /**
9368      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
9369      * The base implementation sets:
9370      * <ul>
9371      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
9372      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
9373      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
9374      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
9375      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
9376      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
9377      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
9378      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
9379      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
9380      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
9381      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
9382      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
9383      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
9384      * </ul>
9385      * <p>
9386      * Subclasses should override this method, call the super implementation,
9387      * and set additional attributes.
9388      * </p>
9389      * <p>
9390      * If an {@link AccessibilityDelegate} has been specified via calling
9391      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9392      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
9393      * is responsible for handling this call.
9394      * </p>
9395      *
9396      * @param info The instance to initialize.
9397      */
9398     @CallSuper
9399     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
9400         if (mAccessibilityDelegate != null) {
9401             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
9402         } else {
9403             onInitializeAccessibilityNodeInfoInternal(info);
9404         }
9405     }
9406 
9407     /**
9408      * Gets the location of this view in screen coordinates.
9409      *
9410      * @param outRect The output location
9411      * @hide
9412      */
9413     @UnsupportedAppUsage
9414     public void getBoundsOnScreen(Rect outRect) {
9415         getBoundsOnScreen(outRect, false);
9416     }
9417 
9418     /**
9419      * Gets the location of this view in screen coordinates.
9420      *
9421      * @param outRect The output location
9422      * @param clipToParent Whether to clip child bounds to the parent ones.
9423      * @hide
9424      */
9425     @UnsupportedAppUsage
9426     @TestApi
9427     public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
9428         if (mAttachInfo == null) {
9429             return;
9430         }
9431         RectF position = mAttachInfo.mTmpTransformRect;
9432         getBoundsToScreenInternal(position, clipToParent);
9433         outRect.set(Math.round(position.left), Math.round(position.top),
9434                 Math.round(position.right), Math.round(position.bottom));
9435         // If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
9436         // will sandbox outRect within window bounds.
9437         mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
9438     }
9439 
9440     /**
9441      * Gets the location of this view in screen coordinates.
9442      *
9443      * @param outRect The output location
9444      * @param clipToParent Whether to clip child bounds to the parent ones.
9445      * @hide
9446      */
9447     public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
9448         if (mAttachInfo == null) {
9449             return;
9450         }
9451         RectF position = mAttachInfo.mTmpTransformRect;
9452         getBoundsToScreenInternal(position, clipToParent);
9453         outRect.set(position.left, position.top, position.right, position.bottom);
9454     }
9455 
9456     /**
9457      * Gets the location of this view in window coordinates.
9458      *
9459      * @param outRect The output location
9460      * @param clipToParent Whether to clip child bounds to the parent ones.
9461      * @hide
9462      */
9463     public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
9464         if (mAttachInfo == null) {
9465             return;
9466         }
9467         RectF position = mAttachInfo.mTmpTransformRect;
9468         getBoundsToWindowInternal(position, clipToParent);
9469         outRect.set(Math.round(position.left), Math.round(position.top),
9470                 Math.round(position.right), Math.round(position.bottom));
9471     }
9472 
9473     private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
9474         position.set(0, 0, mRight - mLeft, mBottom - mTop);
9475         mapRectFromViewToScreenCoords(position, clipToParent);
9476     }
9477 
9478     private void getBoundsToWindowInternal(RectF position, boolean clipToParent) {
9479         position.set(0, 0, mRight - mLeft, mBottom - mTop);
9480         mapRectFromViewToWindowCoords(position, clipToParent);
9481     }
9482 
9483     /**
9484      * Map a rectangle from view-relative coordinates to screen-relative coordinates
9485      *
9486      * @param rect The rectangle to be mapped
9487      * @param clipToParent Whether to clip child bounds to the parent ones.
9488      * @hide
9489      */
9490     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
9491         mapRectFromViewToWindowCoords(rect, clipToParent);
9492         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
9493     }
9494 
9495     /**
9496      * Map a rectangle from view-relative coordinates to window-relative coordinates
9497      *
9498      * @param rect The rectangle to be mapped
9499      * @param clipToParent Whether to clip child bounds to the parent ones.
9500      * @hide
9501      */
9502     public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
9503         if (!hasIdentityMatrix()) {
9504             getMatrix().mapRect(rect);
9505         }
9506 
9507         rect.offset(mLeft, mTop);
9508 
9509         ViewParent parent = mParent;
9510         while (parent instanceof View) {
9511             View parentView = (View) parent;
9512 
9513             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
9514 
9515             if (clipToParent) {
9516                 rect.left = Math.max(rect.left, 0);
9517                 rect.top = Math.max(rect.top, 0);
9518                 rect.right = Math.min(rect.right, parentView.getWidth());
9519                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
9520             }
9521 
9522             if (!parentView.hasIdentityMatrix()) {
9523                 parentView.getMatrix().mapRect(rect);
9524             }
9525 
9526             rect.offset(parentView.mLeft, parentView.mTop);
9527 
9528             parent = parentView.mParent;
9529         }
9530 
9531         if (parent instanceof ViewRootImpl) {
9532             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
9533             rect.offset(0, -viewRootImpl.mCurScrollY);
9534         }
9535     }
9536 
9537     /**
9538      * Return the class name of this object to be used for accessibility purposes.
9539      * Subclasses should only override this if they are implementing something that
9540      * should be seen as a completely new class of view when used by accessibility,
9541      * unrelated to the class it is deriving from.  This is used to fill in
9542      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
9543      */
9544     public CharSequence getAccessibilityClassName() {
9545         return View.class.getName();
9546     }
9547 
9548     /**
9549      * Called when assist structure is being retrieved from a view as part of
9550      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
9551      * @param structure Fill in with structured view data.  The default implementation
9552      * fills in all data that can be inferred from the view itself.
9553      */
9554     public void onProvideStructure(ViewStructure structure) {
9555         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
9556     }
9557 
9558     /**
9559      * Populates a {@link ViewStructure} to fullfil an autofill request.
9560      *
9561      * <p>The structure should contain at least the following properties:
9562      * <ul>
9563      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
9564      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
9565      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
9566      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
9567      * </ul>
9568      *
9569      * <p>It's also recommended to set the following properties - the more properties the structure
9570      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
9571      * using the structure:
9572      *
9573      * <ul>
9574      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
9575      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
9576      *       view can only be filled with predefined values (typically used when the autofill type
9577      *       is {@link #AUTOFILL_TYPE_LIST}).
9578      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
9579      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
9580      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
9581      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
9582      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
9583      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
9584      *   <li>For views representing text fields, text properties such as the text itself
9585      *       ({@link ViewStructure#setText(CharSequence)}), text hints
9586      *       ({@link ViewStructure#setHint(CharSequence)}, input type
9587      *       ({@link ViewStructure#setInputType(int)}),
9588      *   <li>For views representing HTML nodes, its web domain
9589      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
9590      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
9591      * </ul>
9592      *
9593      * <p>The default implementation of this method already sets most of these properties based on
9594      * related {@link View} methods (for example, the autofill id is set using
9595      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
9596      * and views in the standard Android widgets library also override it to set their
9597      * relevant properties (for example, {@link android.widget.TextView} already sets the text
9598      * properties), so it's recommended to only override this method
9599      * (and call {@code super.onProvideAutofillStructure()}) when:
9600      *
9601      * <ul>
9602      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
9603      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
9604      *   <li>The view can only be autofilled with predefined options, so it can call
9605      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
9606      * </ul>
9607      *
9608      * <p><b>Note:</b> The {@code left} and {@code top} values set in
9609      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
9610      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
9611      *
9612      * <p>Views support the Autofill Framework mainly by:
9613      * <ul>
9614      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9615      *   <li>Notifying the Android System when the view value changed by calling
9616      *       {@link AutofillManager#notifyValueChanged(View)}.
9617      *   <li>Implementing the methods that autofill the view.
9618      * </ul>
9619      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
9620      * for the latter.
9621      *
9622      * @param structure fill in with structured view data for autofill purposes.
9623      * @param flags optional flags.
9624      *
9625      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9626      */
9627     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
9628         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
9629     }
9630 
9631     /**
9632      * Populates a {@link ViewStructure} for content capture.
9633      *
9634      * <p>This method is called after a view that is eligible for content capture
9635      * (for example, if it {@link #isImportantForContentCapture()}, an intelligence service is
9636      * enabled for the user, and the activity rendering the view is enabled for content capture)
9637      * is laid out and is visible. The populated structure is then passed to the service through
9638      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
9639      *
9640      * <p>The default implementation of this method sets the most relevant properties based on
9641      * related {@link View} methods, and views in the standard Android widgets library also
9642      * override it to set their relevant properties. Therefore, if overriding this method, it
9643      * is recommended to call {@code super.onProvideContentCaptureStructure()}.
9644      *
9645      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
9646      * the node representing this view and return right away, then asynchronously report (not
9647      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
9648      * changed by calling
9649      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
9650      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
9651      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
9652      * respectively. The structure for a child must be created using
9653      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
9654      * {@code autofillId} for a child can be obtained either through
9655      * {@code childStructure.getAutofillId()} or
9656      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
9657      *
9658      * <p>When the virtual view hierarchy represents a web page, you should also:
9659      *
9660      * <ul>
9661      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
9662      *   capture events should be generate for that URL.
9663      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
9664      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
9665      *   that subtree.
9666      * </ul>
9667      *
9668      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
9669      * <ul>
9670      *   <li>{@link ViewStructure#setChildCount(int)}
9671      *   <li>{@link ViewStructure#addChildCount(int)}
9672      *   <li>{@link ViewStructure#getChildCount()}
9673      *   <li>{@link ViewStructure#newChild(int)}
9674      *   <li>{@link ViewStructure#asyncNewChild(int)}
9675      *   <li>{@link ViewStructure#asyncCommit()}
9676      *   <li>{@link ViewStructure#setWebDomain(String)}
9677      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
9678      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
9679      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
9680      *   <li>{@link ViewStructure#setAlpha(float)}
9681      *   <li>{@link ViewStructure#setElevation(float)}
9682      *   <li>{@link ViewStructure#setTransformation(Matrix)}
9683      *
9684      * </ul>
9685      */
9686     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
9687         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
9688     }
9689 
9690     /** @hide */
9691     protected void onProvideStructure(@NonNull ViewStructure structure,
9692             @ViewStructureType int viewFor, int flags) {
9693         final int id = mID;
9694         if (id != NO_ID && !isViewIdGenerated(id)) {
9695             String pkg, type, entry;
9696             try {
9697                 final Resources res = getResources();
9698                 entry = res.getResourceEntryName(id);
9699                 type = res.getResourceTypeName(id);
9700                 pkg = res.getResourcePackageName(id);
9701             } catch (Resources.NotFoundException e) {
9702                 entry = type = pkg = null;
9703             }
9704             structure.setId(id, pkg, type, entry);
9705         } else {
9706             structure.setId(id, null, null, null);
9707         }
9708 
9709         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9710                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
9711             final @AutofillType int autofillType = getAutofillType();
9712             // Don't need to fill autofill info if view does not support it.
9713             // For example, only TextViews that are editable support autofill
9714             if (autofillType != AUTOFILL_TYPE_NONE) {
9715                 structure.setAutofillType(autofillType);
9716                 structure.setAutofillHints(getAutofillHints());
9717                 structure.setAutofillValue(getAutofillValue());
9718                 structure.setIsCredential(isCredential());
9719             }
9720             if (getViewCredentialHandler() != null) {
9721                 structure.setPendingCredentialRequest(
9722                         getViewCredentialHandler().getRequest(),
9723                         getViewCredentialHandler().getCallback());
9724             }
9725             structure.setImportantForAutofill(getImportantForAutofill());
9726             structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
9727         }
9728 
9729         int ignoredParentLeft = 0;
9730         int ignoredParentTop = 0;
9731         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9732                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
9733             View parentGroup = null;
9734 
9735             ViewParent viewParent = getParent();
9736             if (viewParent instanceof View) {
9737                 parentGroup = (View) viewParent;
9738             }
9739 
9740             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
9741                 ignoredParentLeft += parentGroup.mLeft - parentGroup.mScrollX;
9742                 ignoredParentTop += parentGroup.mTop - parentGroup.mScrollY;
9743 
9744                 viewParent = parentGroup.getParent();
9745                 if (viewParent instanceof View) {
9746                     parentGroup = (View) viewParent;
9747                 } else {
9748                     break;
9749                 }
9750             }
9751         }
9752 
9753         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
9754                 mRight - mLeft, mBottom - mTop);
9755         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
9756             if (!hasIdentityMatrix()) {
9757                 structure.setTransformation(getMatrix());
9758             }
9759             structure.setElevation(getZ());
9760         }
9761         structure.setVisibility(getVisibility());
9762         structure.setEnabled(isEnabled());
9763         if (isClickable()) {
9764             structure.setClickable(true);
9765         }
9766         if (isFocusable()) {
9767             structure.setFocusable(true);
9768         }
9769         if (isFocused()) {
9770             structure.setFocused(true);
9771         }
9772         if (isAccessibilityFocused()) {
9773             structure.setAccessibilityFocused(true);
9774         }
9775         if (isSelected()) {
9776             structure.setSelected(true);
9777         }
9778         if (isActivated()) {
9779             structure.setActivated(true);
9780         }
9781         if (isLongClickable()) {
9782             structure.setLongClickable(true);
9783         }
9784         if (this instanceof Checkable) {
9785             structure.setCheckable(true);
9786             if (((Checkable)this).isChecked()) {
9787                 structure.setChecked(true);
9788             }
9789         }
9790         if (isOpaque()) {
9791             structure.setOpaque(true);
9792         }
9793         if (isContextClickable()) {
9794             structure.setContextClickable(true);
9795         }
9796         structure.setClassName(getAccessibilityClassName().toString());
9797         structure.setContentDescription(getContentDescription());
9798     }
9799 
9800     /**
9801      * Called when assist structure is being retrieved from a view as part of
9802      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
9803      * generate additional virtual structure under this view.  The default implementation
9804      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
9805      * view's virtual accessibility nodes, if any.  You can override this for a more
9806      * optimal implementation providing this data.
9807      */
9808     public void onProvideVirtualStructure(ViewStructure structure) {
9809         onProvideVirtualStructureCompat(structure, false);
9810     }
9811 
9812     /**
9813      * Fallback implementation to populate a ViewStructure from accessibility state.
9814      *
9815      * @param structure The structure to populate.
9816      * @param forAutofill Whether the structure is needed for autofill.
9817      */
9818     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
9819         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9820         if (provider != null) {
9821             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9822                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
9823             }
9824             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
9825             structure.setChildCount(1);
9826             final ViewStructure root = structure.newChild(0);
9827             if (info != null) {
9828                 populateVirtualStructure(root, provider, info, null, forAutofill);
9829                 info.recycle();
9830             } else {
9831                 Log.w(AUTOFILL_LOG_TAG, "AccessibilityNodeInfo is null.");
9832             }
9833         }
9834     }
9835 
9836     /**
9837      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
9838      * request.
9839      *
9840      * <p>This method should be used when the view manages a virtual structure under this view. For
9841      * example, a view that draws input fields using {@link #draw(Canvas)}.
9842      *
9843      * <p>When implementing this method, subclasses must follow the rules below:
9844      *
9845      * <ul>
9846      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
9847      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
9848      *       identifying the children in the virtual structure.
9849      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
9850      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
9851      *       autofill performance.
9852      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
9853      *       children.
9854      *   <li>Set the autofill properties of the child structure as defined by
9855      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
9856      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
9857      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
9858      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
9859      *       when the focused virtual child changed.
9860      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9861      *       whether a given virtual view is visible to the user in order to support triggering
9862      *       save when all views of interest go away.
9863      *   <li>Call
9864      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9865      *       when the value of a virtual child changed.
9866      *   <li>Call {@link
9867      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9868      *       when the visibility of a virtual child changed.
9869      *   <li>Call
9870      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9871      *       child is clicked.
9872      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9873      *       changed and the current context should be committed (for example, when the user tapped
9874      *       a {@code SUBMIT} button in an HTML page).
9875      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9876      *       changed and the current context should be canceled (for example, when the user tapped
9877      *       a {@code CANCEL} button in an HTML page).
9878      *   <li>Provide ways for users to manually request autofill by calling
9879      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9880      *   <li>The {@code left} and {@code top} values set in
9881      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9882      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9883      *       structure.
9884      * </ul>
9885      *
9886      * <p>Views with virtual children support the Autofill Framework mainly by:
9887      * <ul>
9888      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9889      *       autofilled.
9890      *   <li>Implementing the methods that autofill the virtual children.
9891      * </ul>
9892      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9893      * for the latter.
9894      *
9895      * @param structure fill in with virtual children data for autofill purposes.
9896      * @param flags optional flags.
9897      *
9898      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9899      */
9900     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9901         if (mContext.isAutofillCompatibilityEnabled()) {
9902             onProvideVirtualStructureCompat(structure, true);
9903         }
9904     }
9905 
9906     /**
9907      * Sets the listener to be {@link #performReceiveContent used} to handle insertion of
9908      * content into this view.
9909      *
9910      * <p>Depending on the type of view, this listener may be invoked for different scenarios. For
9911      * example, for an editable {@link android.widget.TextView}, this listener will be invoked for
9912      * the following scenarios:
9913      * <ol>
9914      *     <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
9915      *     insertion/selection menu)
9916      *     <li>Content insertion from the keyboard (from {@link InputConnection#commitContent})
9917      *     <li>Drag and drop (drop events from {@link #onDragEvent})
9918      *     <li>Autofill
9919      *     <li>Selection replacement via {@link Intent#ACTION_PROCESS_TEXT}
9920      * </ol>
9921      *
9922      * <p>When setting a listener, clients must also declare the accepted MIME types.
9923      * The listener will still be invoked even if the MIME type of the content is not one of the
9924      * declared MIME types (e.g. if the user pastes content whose type is not one of the declared
9925      * MIME types).
9926      * In that case, the listener may reject the content (defer to the default platform behavior)
9927      * or execute some other fallback logic (e.g. show an appropriate message to the user).
9928      * The declared MIME types serve as a hint to allow different features to optionally alter
9929      * their behavior. For example, a soft keyboard may optionally choose to hide its UI for
9930      * inserting GIFs for a particular input field if the MIME types set here for that field
9931      * don't include "image/gif" or "image/*".
9932      *
9933      * <p>Note: MIME type matching in the Android framework is case-sensitive, unlike formal RFC
9934      * MIME types. As a result, you should always write your MIME types with lowercase letters,
9935      * or use {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9936      * lowercase.
9937      *
9938      * @param mimeTypes The MIME types accepted by the given listener. These may use patterns
9939      *                  such as "image/*", but may not start with a wildcard. This argument must
9940      *                  not be null or empty if a non-null listener is passed in.
9941      * @param listener The listener to use. This can be null to reset to the default behavior.
9942      */
9943     public void setOnReceiveContentListener(
9944             @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
9945             @Nullable OnReceiveContentListener listener) {
9946         if (listener != null) {
9947             Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
9948                     "When the listener is set, MIME types must also be set");
9949         }
9950         if (mimeTypes != null) {
9951             Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
9952                     "A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
9953         }
9954         mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
9955         getListenerInfo().mOnReceiveContentListener = listener;
9956     }
9957 
9958     /**
9959      * Receives the given content. If no listener is set, invokes {@link #onReceiveContent}. If a
9960      * listener is {@link #setOnReceiveContentListener set}, invokes the listener instead; if the
9961      * listener returns a non-null result, invokes {@link #onReceiveContent} to handle it.
9962      *
9963      * @param payload The content to insert and related metadata.
9964      *
9965      * @return The portion of the passed-in content that was not accepted (may be all, some, or none
9966      * of the passed-in content).
9967      */
9968     @Nullable
9969     public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
9970         final OnReceiveContentListener listener = (mListenerInfo == null) ? null
9971                 : getListenerInfo().mOnReceiveContentListener;
9972         if (listener != null) {
9973             final ContentInfo remaining = listener.onReceiveContent(this, payload);
9974             return (remaining == null) ? null : onReceiveContent(remaining);
9975         }
9976         return onReceiveContent(payload);
9977     }
9978 
9979     /**
9980      * Implements the default behavior for receiving content for this type of view. The default
9981      * view implementation is a no-op (returns the passed-in content without acting on it).
9982      *
9983      * <p>Widgets should override this method to define their default behavior for receiving
9984      * content. Apps should {@link #setOnReceiveContentListener set a listener} to provide
9985      * app-specific handling for receiving content.
9986      *
9987      * <p>See {@link #setOnReceiveContentListener} and {@link #performReceiveContent} for more info.
9988      *
9989      * @param payload The content to insert and related metadata.
9990      *
9991      * @return The portion of the passed-in content that was not handled (may be all, some, or none
9992      * of the passed-in content).
9993      */
9994     @Nullable
9995     public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
9996         return payload;
9997     }
9998 
9999     /**
10000      * Returns the MIME types accepted by {@link #performReceiveContent} for this view, as
10001      * configured via {@link #setOnReceiveContentListener}. By default returns null.
10002      *
10003      * <p>Different features (e.g. pasting from the clipboard, inserting stickers from the soft
10004      * keyboard, etc) may optionally use this metadata to conditionally alter their behavior. For
10005      * example, a soft keyboard may choose to hide its UI for inserting GIFs for a particular
10006      * input field if the MIME types returned here for that field don't include "image/gif" or
10007      * "image/*".
10008      *
10009      * <p>Note: Comparisons of MIME types should be performed using utilities such as
10010      * {@link ClipDescription#compareMimeTypes} rather than simple string equality, in order to
10011      * correctly handle patterns such as "text/*", "image/*", etc. Note that MIME type matching
10012      * in the Android framework is case-sensitive, unlike formal RFC MIME types. As a result,
10013      * you should always write your MIME types with lowercase letters, or use
10014      * {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
10015      * lowercase.
10016      *
10017      * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
10018      * include patterns such as "image/*").
10019      */
10020     @SuppressLint("NullableCollection")
10021     @Nullable
10022     public String[] getReceiveContentMimeTypes() {
10023         return mReceiveContentMimeTypes;
10024     }
10025 
10026     /**
10027      * Automatically fills the content of this view with the {@code value}.
10028      *
10029      * <p>Views support the Autofill Framework mainly by:
10030      * <ul>
10031      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
10032      *   <li>Implementing the methods that autofill the view.
10033      * </ul>
10034      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
10035      * this method is responsible for latter.
10036      *
10037      * <p>This method does nothing by default, but when overridden it typically:
10038      * <ol>
10039      *   <li>Checks if the provided value matches the expected type (which is defined by
10040      *       {@link #getAutofillType()}).
10041      *   <li>Checks if the view is editable - if it isn't, it should return right away.
10042      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
10043      *   <li>Pass the actual value to the equivalent setter in the view.
10044      * </ol>
10045      *
10046      * <p>For example, a text-field view could implement the method this way:
10047      *
10048      * <pre class="prettyprint">
10049      * &#64;Override
10050      * public void autofill(AutofillValue value) {
10051      *   if (!value.isText() || !this.isEditable()) {
10052      *      return;
10053      *   }
10054      *   CharSequence text = value.getTextValue();
10055      *   if (text != null) {
10056      *     this.setText(text);
10057      *   }
10058      * }
10059      * </pre>
10060      *
10061      * <p>If the value is updated asynchronously, the next call to
10062      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
10063      * changed to the autofilled value. If not, the view will not be considered autofilled.
10064      *
10065      * <p><b>Note:</b> After this method is called, the value returned by
10066      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
10067      * view will not be highlighted as autofilled.
10068      *
10069      * @param value value to be autofilled.
10070      */
10071     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
10072     }
10073 
10074     /**
10075      * Automatically fills the content of the virtual children within this view.
10076      *
10077      * <p>Views with virtual children support the Autofill Framework mainly by:
10078      * <ul>
10079      *   <li>Providing the metadata defining what the virtual children mean and how they can be
10080      *       autofilled.
10081      *   <li>Implementing the methods that autofill the virtual children.
10082      * </ul>
10083      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
10084      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
10085      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
10086      *
10087      * <p>If a child value is updated asynchronously, the next call to
10088      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
10089      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
10090      * considered autofilled.
10091      *
10092      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
10093      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
10094      * changes.
10095      *
10096      * @param values map of values to be autofilled, keyed by virtual child id.
10097      *
10098      * @attr ref android.R.styleable#Theme_autofilledHighlight
10099      */
10100     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
10101         if (!mContext.isAutofillCompatibilityEnabled()) {
10102             return;
10103         }
10104         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10105         if (provider == null) {
10106             return;
10107         }
10108         final int valueCount = values.size();
10109         for (int i = 0; i < valueCount; i++) {
10110             final AutofillValue value = values.valueAt(i);
10111             if (value.isText()) {
10112                 final int virtualId = values.keyAt(i);
10113                 final CharSequence text = value.getTextValue();
10114                 final Bundle arguments = new Bundle();
10115                 arguments.putCharSequence(
10116                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
10117                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
10118             }
10119         }
10120     }
10121 
10122     /**
10123      * @hide
10124      */
10125     public void onGetCredentialResponse(GetCredentialResponse response) {
10126         if (getPendingCredentialCallback() == null) {
10127             Log.w(AUTOFILL_LOG_TAG, "onGetCredentialResponse called but no callback found");
10128             return;
10129         }
10130         getPendingCredentialCallback().onResult(response);
10131     }
10132 
10133     /**
10134      * @hide
10135      */
10136     public void onGetCredentialException(String errorType, String errorMsg) {
10137         if (getPendingCredentialCallback() == null) {
10138             Log.w(AUTOFILL_LOG_TAG, "onGetCredentialException called but no callback found");
10139             return;
10140         }
10141         getPendingCredentialCallback().onError(new GetCredentialException(errorType, errorMsg));
10142     }
10143 
10144     /**
10145      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
10146      *
10147      * <p>The autofill id is created on demand, unless it is explicitly set by
10148      * {@link #setAutofillId(AutofillId)}.
10149      *
10150      * <p>See {@link #setAutofillId(AutofillId)} for more info.
10151      *
10152      * @return The View's autofill id.
10153      */
10154     public final AutofillId getAutofillId() {
10155         if (mAutofillId == null) {
10156             // The autofill id needs to be unique, but its value doesn't matter,
10157             // so it's better to reuse the accessibility id to save space.
10158             mAutofillId = new AutofillId(getAutofillViewId());
10159         }
10160         return mAutofillId;
10161     }
10162 
10163     /**
10164      * Returns the {@link GetCredentialRequest} associated with the view.
10165      * If the return value is null, that means no request has been set
10166      * on the view and no {@link CredentialManager} flow will be invoked
10167      * when this view is focused. Traditioanl autofill flows will still
10168      * work, autofilling content if applicable, from
10169      * the active {@link android.service.autofill.AutofillService} on
10170      * the device.
10171      *
10172      * <p>See {@link #setPendingCredentialRequest} for more info.
10173      *
10174      * @return The credential request associated with this View.
10175      */
10176     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
10177     @Nullable
10178     public final GetCredentialRequest getPendingCredentialRequest() {
10179         if (mViewCredentialHandler == null) {
10180             return null;
10181         }
10182         return mViewCredentialHandler.getRequest();
10183     }
10184 
10185 
10186     /**
10187      * Returns the callback that has previously been set up on this view through
10188      * the {@link #setPendingCredentialRequest} API.
10189      * If the return value is null, that means no callback, or request, has been set
10190      * on the view and no {@link CredentialManager} flow will be invoked
10191      * when this view is focused. Traditioanl autofill flows will still
10192      * work, and autofillable content will still be returned through the
10193      * {@link #autofill(AutofillValue)} )} API.
10194      *
10195      * <p>See {@link #setPendingCredentialRequest} for more info.
10196      *
10197      * @return The callback associated with this view that will be invoked on a response from
10198      * {@link CredentialManager} .
10199      */
10200     @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION)
10201     @Nullable
10202     public final OutcomeReceiver<GetCredentialResponse,
10203             GetCredentialException> getPendingCredentialCallback() {
10204         if (mViewCredentialHandler == null) {
10205             return null;
10206         }
10207         return mViewCredentialHandler.getCallback();
10208     }
10209 
10210     /**
10211      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
10212      *
10213      * <p>The autofill id is created on demand, and this method should only be called when a view is
10214      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
10215      * that method creates a snapshot of the view that is passed along to the autofill service.
10216      *
10217      * <p>This method is typically used when view subtrees are recycled to represent different
10218      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
10219      * out, and restored later when it's swapped back in. For example:
10220      *
10221      * <pre>
10222      * EditText reusableView = ...;
10223      * ViewGroup parentView = ...;
10224      * AutofillManager afm = ...;
10225      *
10226      * // Swap out the view and change its contents
10227      * AutofillId oldId = reusableView.getAutofillId();
10228      * CharSequence oldText = reusableView.getText();
10229      * parentView.removeView(reusableView);
10230      * AutofillId newId = afm.getNextAutofillId();
10231      * reusableView.setText("New I am");
10232      * reusableView.setAutofillId(newId);
10233      * parentView.addView(reusableView);
10234      *
10235      * // Later, swap the old content back in
10236      * parentView.removeView(reusableView);
10237      * reusableView.setAutofillId(oldId);
10238      * reusableView.setText(oldText);
10239      * parentView.addView(reusableView);
10240      * </pre>
10241      *
10242      * <p>NOTE: If this view is a descendant of an {@link android.widget.AdapterView}, the system
10243      * may reset its autofill id when this view is recycled. If the autofill ids need to be stable,
10244      * they should be set again in
10245      * {@link android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
10246      *
10247      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
10248      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
10249      * obtained through {@link #getAutofillId()}), or a new value obtained through
10250      * {@link AutofillManager#getNextAutofillId()}.
10251      *
10252      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
10253      * a window}.
10254      *
10255      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
10256      */
10257     public void setAutofillId(@Nullable AutofillId id) {
10258         // TODO(b/37566627): add unit / CTS test for all possible combinations below
10259         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10260             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
10261         }
10262         if (isAttachedToWindow()) {
10263             throw new IllegalStateException("Cannot set autofill id when view is attached");
10264         }
10265         if (id != null && !id.isNonVirtual()) {
10266             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
10267         }
10268         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
10269             // Ignore reset because it was never explicitly set before.
10270             return;
10271         }
10272         mAutofillId = id;
10273         if (id != null) {
10274             mAutofillViewId = id.getViewId();
10275             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
10276         } else {
10277             mAutofillViewId = NO_ID;
10278             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
10279         }
10280     }
10281 
10282     /**
10283      * Forces a reset of the autofill ids of the subtree rooted at this view. Like calling
10284      * {@link #setAutofillId(AutofillId) setAutofillId(null)} for each view, but works even if the
10285      * views are attached to a window.
10286      *
10287      * <p>This is useful if the views are being recycled, since an autofill id should uniquely
10288      * identify a particular piece of content.
10289      *
10290      * @hide
10291      */
10292     public void resetSubtreeAutofillIds() {
10293         if (mAutofillViewId == NO_ID) {
10294             return;
10295         }
10296         if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10297             Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
10298         } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10299             Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
10300         }
10301         mAutofillId = null;
10302         mAutofillViewId = NO_ID;
10303         mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
10304     }
10305 
10306     /**
10307      * Describes the autofill type of this view, so an
10308      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
10309      * when autofilling the view.
10310      *
10311      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
10312      * support the Autofill Framework.
10313      *
10314      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
10315      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
10316      *
10317      * @see #onProvideAutofillStructure(ViewStructure, int)
10318      * @see #autofill(AutofillValue)
10319      */
10320     public @AutofillType int getAutofillType() {
10321         return AUTOFILL_TYPE_NONE;
10322     }
10323 
10324     /**
10325      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
10326      * to autofill the view with the user's data.
10327      *
10328      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
10329      *
10330      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
10331      * {@code null} if no hints were set.
10332      *
10333      * @attr ref android.R.styleable#View_autofillHints
10334      */
10335     @ViewDebug.ExportedProperty()
10336     @InspectableProperty
10337     @Nullable public String[] getAutofillHints() {
10338         return mAutofillHints;
10339     }
10340 
10341     /**
10342      * @hide
10343      */
10344     @TestApi
10345     public boolean isAutofilled() {
10346         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
10347     }
10348 
10349     /**
10350      * @hide
10351      */
10352     public boolean hideAutofillHighlight() {
10353         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
10354     }
10355 
10356     /**
10357      * Gets the {@link View}'s current autofill value.
10358      *
10359      * <p>By default returns {@code null}, but subclasses should override it and return an
10360      * appropriate value to properly support the Autofill Framework.
10361      *
10362      * @see #onProvideAutofillStructure(ViewStructure, int)
10363      * @see #autofill(AutofillValue)
10364      */
10365     @Nullable
10366     public AutofillValue getAutofillValue() {
10367         return null;
10368     }
10369 
10370     /**
10371      * Gets the mode for determining whether this view is important for autofill.
10372      *
10373      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
10374      * info about this mode.
10375      *
10376      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
10377      * {@link #setImportantForAutofill(int)}.
10378      *
10379      * @attr ref android.R.styleable#View_importantForAutofill
10380      */
10381     @ViewDebug.ExportedProperty(mapping = {
10382             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
10383             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
10384             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
10385             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
10386                 to = "yesExcludeDescendants"),
10387             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
10388                 to = "noExcludeDescendants")})
10389     @InspectableProperty(enumMapping = {
10390             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
10391             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
10392             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
10393             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
10394                     name = "yesExcludeDescendants"),
10395             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
10396                     name = "noExcludeDescendants"),
10397     })
10398     public @AutofillImportance int getImportantForAutofill() {
10399         return (mPrivateFlags3
10400                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
10401     }
10402 
10403     /**
10404      * Sets the mode for determining whether this view is considered important for autofill.
10405      *
10406      * <p>The platform determines the importance for autofill automatically but you
10407      * can use this method to customize the behavior. For example:
10408      *
10409      * <ol>
10410      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
10411      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
10412      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
10413      *       view of an activity containing a spreadhseet editor), it should be
10414      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
10415      *   <li>When the view content is relevant for autofill but its children aren't (for example,
10416      *       a credit card expiration date represented by a custom view that overrides the proper
10417      *       autofill methods and has 2 children representing the month and year), it should
10418      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
10419      * </ol>
10420      *
10421      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
10422      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
10423      * children) will not be used for autofill purpose; for example, when the user explicitly
10424      * makes an autofill request, all views are included in the ViewStructure, and starting in
10425      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} the system uses other factors along
10426      * with importance to determine the autofill behavior. See {@link #isImportantForAutofill()}
10427      * for more details about how the View's importance for autofill is used.
10428      *
10429      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
10430      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
10431      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
10432      *
10433      * @attr ref android.R.styleable#View_importantForAutofill
10434      */
10435     public void setImportantForAutofill(@AutofillImportance int mode) {
10436         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
10437         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
10438                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
10439     }
10440 
10441     /**
10442      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
10443      * associated with this view is considered important for autofill purposes.
10444      *
10445      * <p>Generally speaking, a view is important for autofill if:
10446      * <ol>
10447      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
10448      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
10449      *     determine how other views can be autofilled.
10450      * <ol>
10451      *
10452      * <p>For example, view containers should typically return {@code false} for performance reasons
10453      * (since the important info is provided by their children), but if its properties have relevant
10454      * information (for example, a resource id called {@code credentials}, it should return
10455      * {@code true}. On the other hand, views representing labels or editable fields should
10456      * typically return {@code true}, but in some cases they could return {@code false}
10457      * (for example, if they're part of a "Captcha" mechanism).
10458      *
10459      * <p>The value returned by this method depends on the value returned by
10460      * {@link #getImportantForAutofill()}:
10461      *
10462      * <ol>
10463      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
10464      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
10465      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
10466      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
10467      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
10468      *       that can return {@code true} in some cases (like a container with a resource id),
10469      *       but {@code false} in most.
10470      *   <li>otherwise, it returns {@code false}.
10471      * </ol>
10472      *
10473      * <p> The behavior of importances depends on Android version:
10474      * <ol>
10475      *   <li>For {@link android.os.Build.VERSION_CODES#TIRAMISU} and below:
10476      *     <ol>
10477      *       <li>When a view is considered important for autofill:
10478      *          <ol>
10479      *            <li>The view might automatically trigger an autofill request when focused on.
10480      *            <li>The contents of the view are included in the {@link ViewStructure} used in an
10481      *                autofill request.
10482      *          </ol>
10483      *        <li>On the other hand, when a view is considered not important for autofill:
10484      *          <ol>
10485      *            <li>The view never automatically triggers autofill requests, but it can trigger a
10486      *                manual request through {@link AutofillManager#requestAutofill(View)}.
10487      *            <li>The contents of the view are not included in the {@link ViewStructure} used in
10488      *                an autofill request, unless the request has the
10489      *                {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
10490      *          </ol>
10491      *      </ol>
10492      *  <li>For {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above:
10493      *    <ol>
10494      *      <li>The system uses importance, along with other view properties and other optimization
10495      *          factors, to determine if a view should trigger autofill on focus.
10496      *      <li>The contents of {@link #IMPORTANT_FOR_AUTOFILL_AUTO},
10497      *        {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@link #IMPORTANT_FOR_AUTOFILL_NO},
10498      *        {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, and
10499      *        {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} views will be included in the
10500      *        {@link ViewStructure} used in an autofill request.
10501      *    </ol>
10502      * </ol>
10503      *
10504      * @return whether the view is considered important for autofill.
10505      *
10506      * @see #setImportantForAutofill(int)
10507      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
10508      * @see #IMPORTANT_FOR_AUTOFILL_YES
10509      * @see #IMPORTANT_FOR_AUTOFILL_NO
10510      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
10511      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
10512      * @see AutofillManager#requestAutofill(View)
10513      */
10514     public final boolean isImportantForAutofill() {
10515         // Check parent mode to ensure we're not hidden.
10516         ViewParent parent = mParent;
10517         while (parent instanceof View) {
10518             final int parentImportance = ((View) parent).getImportantForAutofill();
10519             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
10520                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
10521                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10522                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
10523                             + "because parent " + parent + "'s importance is " + parentImportance);
10524                 }
10525                 return false;
10526             }
10527             parent = parent.getParent();
10528         }
10529 
10530         final int importance = getImportantForAutofill();
10531 
10532         // First, check the explicit states.
10533         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
10534                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
10535             return true;
10536         }
10537         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
10538                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
10539             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
10540                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
10541                         + "because its importance is " + importance);
10542             }
10543             return false;
10544         }
10545 
10546         // Then use some heuristics to handle AUTO.
10547         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
10548             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
10549                     + this);
10550             return false;
10551         }
10552 
10553         // Always include views that have an explicit resource id.
10554         final int id = mID;
10555         if (id != NO_ID && !isViewIdGenerated(id)) {
10556             final Resources res = getResources();
10557             String entry = null;
10558             String pkg = null;
10559             try {
10560                 entry = res.getResourceEntryName(id);
10561                 pkg = res.getResourcePackageName(id);
10562             } catch (Resources.NotFoundException e) {
10563                 // ignore
10564             }
10565             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
10566                 return true;
10567             }
10568         }
10569 
10570         // If the app developer explicitly set hints for it, it's important.
10571         if (getAutofillHints() != null) {
10572             return true;
10573         }
10574 
10575         // Otherwise, assume it's not important...
10576         return false;
10577     }
10578 
10579     /**
10580      * Sets content sensitivity mode to determine whether this view displays sensitive content
10581      * (e.g. username, password etc.). The system will improve user privacy i.e. hide content
10582      * drawn by a sensitive view from screen sharing and recording.
10583      *
10584      * <p> The window hosting a sensitive view will be marked as secure during an active media
10585      * projection session. This would be equivalent to applying
10586      * {@link android.view.WindowManager.LayoutParams#FLAG_SECURE} to the window.
10587      *
10588      * @param mode {@link #CONTENT_SENSITIVITY_AUTO}, {@link #CONTENT_SENSITIVITY_NOT_SENSITIVE}
10589      *                                            or {@link #CONTENT_SENSITIVITY_SENSITIVE}
10590      */
10591     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
10592     public final void setContentSensitivity(@ContentSensitivity int mode)  {
10593         mPrivateFlags4 &= ~PFLAG4_CONTENT_SENSITIVITY_MASK;
10594         mPrivateFlags4 |= ((mode << PFLAG4_CONTENT_SENSITIVITY_SHIFT)
10595                 & PFLAG4_CONTENT_SENSITIVITY_MASK);
10596         if (sensitiveContentAppProtection()) {
10597             updateSensitiveViewsCountIfNeeded(isAggregatedVisible());
10598         }
10599     }
10600 
10601     /**
10602      * Gets content sensitivity mode to determine whether this view displays sensitive content.
10603      *
10604      * <p>See {@link #setContentSensitivity(int)} and
10605      * {@link #isContentSensitive()} for more info about this mode.
10606      *
10607      * @return {@link #CONTENT_SENSITIVITY_AUTO} by default, or value passed to
10608      * {@link #setContentSensitivity(int)}.
10609      */
10610     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
10611     public @ContentSensitivity final int getContentSensitivity() {
10612         return (mPrivateFlags4 & PFLAG4_CONTENT_SENSITIVITY_MASK)
10613                 >> PFLAG4_CONTENT_SENSITIVITY_SHIFT;
10614     }
10615 
10616     /**
10617      * Returns whether this view displays sensitive content, based
10618      * on the value explicitly set by {@link #setContentSensitivity(int)}.
10619      *
10620      * @return whether the view displays sensitive content.
10621      *
10622      * @see #setContentSensitivity(int)
10623      * @see #CONTENT_SENSITIVITY_AUTO
10624      * @see #CONTENT_SENSITIVITY_SENSITIVE
10625      * @see #CONTENT_SENSITIVITY_NOT_SENSITIVE
10626      */
10627     @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API)
10628     public final boolean isContentSensitive() {
10629         final int contentSensitivity = getContentSensitivity();
10630         if (contentSensitivity == CONTENT_SENSITIVITY_SENSITIVE) {
10631             return true;
10632         } else if (contentSensitivity == CONTENT_SENSITIVITY_NOT_SENSITIVE) {
10633             return false;
10634         } else if (sensitiveContentAppProtection()) {
10635             return SensitiveAutofillHintsHelper
10636                     .containsSensitiveAutofillHint(getAutofillHints());
10637         }
10638         return false;
10639     }
10640 
10641     /**
10642      * Helper used to track sensitive views when they are added or removed from the window
10643      * based on whether it's laid out and visible.
10644      *
10645      * <p>This method is called from many places (visibility changed, view laid out, view attached
10646      * or detached to/from window, etc...)
10647      */
10648     private void updateSensitiveViewsCountIfNeeded(boolean appeared) {
10649         if (!sensitiveContentAppProtection() || mAttachInfo == null) {
10650             return;
10651         }
10652 
10653         if (appeared && isContentSensitive()) {
10654             if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) == 0) {
10655                 mPrivateFlags4 |= PFLAG4_IS_COUNTED_AS_SENSITIVE;
10656                 mAttachInfo.increaseSensitiveViewsCount();
10657             }
10658         } else {
10659             if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) != 0) {
10660                 mPrivateFlags4 &= ~PFLAG4_IS_COUNTED_AS_SENSITIVE;
10661                 mAttachInfo.decreaseSensitiveViewsCount();
10662             }
10663         }
10664     }
10665 
10666     /**
10667      * Gets the mode for determining whether this view is important for content capture.
10668      *
10669      * <p>See {@link #setImportantForContentCapture(int)} and
10670      * {@link #isImportantForContentCapture()} for more info about this mode.
10671      *
10672      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
10673      * {@link #setImportantForContentCapture(int)}.
10674      *
10675      * @attr ref android.R.styleable#View_importantForContentCapture
10676      */
10677     @ViewDebug.ExportedProperty(mapping = {
10678             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
10679             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
10680             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
10681             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
10682                 to = "yesExcludeDescendants"),
10683             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
10684                 to = "noExcludeDescendants")})
10685     @InspectableProperty(enumMapping = {
10686             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
10687             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
10688             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
10689             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
10690                     name = "yesExcludeDescendants"),
10691             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
10692                     name = "noExcludeDescendants"),
10693     })
10694     public @ContentCaptureImportance int getImportantForContentCapture() {
10695         // NOTE: the important for content capture values were the first flags added and are set in
10696         // the rightmost position, so we don't need to shift them
10697         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
10698     }
10699 
10700     /**
10701      * Sets the mode for determining whether this view is considered important for content capture.
10702      *
10703      * <p>The platform determines the importance for autofill automatically but you
10704      * can use this method to customize the behavior. Typically, a view that provides text should
10705      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
10706      *
10707      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
10708      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
10709      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
10710      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
10711      *
10712      * @attr ref android.R.styleable#View_importantForContentCapture
10713      */
10714     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
10715         // Reset first
10716         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
10717         // Then set again
10718         // NOTE: the important for content capture values were the first flags added and are set in
10719         // the rightmost position, so we don't need to shift them
10720         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
10721     }
10722 
10723     /**
10724      * Hints the Android System whether this view is considered important for content capture, based
10725      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
10726      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
10727      *
10728      * <p>See {@link ContentCaptureManager} for more info about content capture.
10729      *
10730      * @return whether the view is considered important for content capture.
10731      *
10732      * @see #setImportantForContentCapture(int)
10733      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
10734      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
10735      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
10736      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
10737      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10738      */
10739     public final boolean isImportantForContentCapture() {
10740         boolean isImportant;
10741         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
10742             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
10743             return isImportant;
10744         }
10745 
10746         isImportant = calculateIsImportantForContentCapture();
10747 
10748         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
10749         if (isImportant) {
10750             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
10751         }
10752         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
10753         return isImportant;
10754     }
10755 
10756     /**
10757      * Calculates whether the flag is important for content capture so it can be used by
10758      * {@link #isImportantForContentCapture()} while the tree is traversed.
10759      */
10760     private boolean calculateIsImportantForContentCapture() {
10761         // Check parent mode to ensure we're important
10762         ViewParent parent = mParent;
10763         while (parent instanceof View) {
10764             final int parentImportance = ((View) parent).getImportantForContentCapture();
10765             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10766                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
10767                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10768                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
10769                             + "content capture because parent " + parent + "'s importance is "
10770                             + parentImportance);
10771                 }
10772                 return false;
10773             }
10774             parent = parent.getParent();
10775         }
10776 
10777         final int importance = getImportantForContentCapture();
10778 
10779         // First, check the explicit states.
10780         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
10781                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
10782             return true;
10783         }
10784         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10785                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
10786             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10787                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
10788                         + "capture because its importance is " + importance);
10789             }
10790             return false;
10791         }
10792 
10793         // Then use some heuristics to handle AUTO.
10794         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
10795             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
10796                     + " on view " + this);
10797             return false;
10798         }
10799 
10800         // View group is important if at least one children also is
10801         if (this instanceof ViewGroup) {
10802             final ViewGroup group = (ViewGroup) this;
10803             for (int i = 0; i < group.getChildCount(); i++) {
10804                 final View child = group.getChildAt(i);
10805                 if (child.isImportantForContentCapture()) {
10806                     return true;
10807                 }
10808             }
10809         }
10810 
10811         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
10812         if (getAutofillHints() != null) {
10813             return true;
10814         }
10815 
10816         // Otherwise, assume it's not important...
10817         return false;
10818     }
10819 
10820     /**
10821      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
10822      * added, based on whether it's laid out and visible, and without knowing if the parent removed
10823      * it from the view hierarchy.
10824      *
10825      * <p>This method is called from many places (visibility changed, view laid out, view attached
10826      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
10827      * described below:
10828      *
10829      * <ol>
10830      *   <li>It should only be called when content capture is enabled for the view.
10831      *   <li>It must call viewAppeared() before viewDisappeared()
10832      *   <li>viewAppeared() can only be called when the view is visible and laid out
10833      *   <li>It should not call the same event twice.
10834      * </ol>
10835      */
10836     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
10837         AttachInfo ai = mAttachInfo;
10838         // Skip it while the view is being laid out for the first time
10839         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
10840 
10841         // First check if context has client, so it saves a service lookup when it doesn't
10842         if (mContext.getContentCaptureOptions() == null) return;
10843 
10844         if (appeared) {
10845             // The appeared event stops sending to AiAi.
10846             // 1. The view is hidden.
10847             // 2. The same event was sent.
10848             // 3. The view is not laid out, and it will be laid out in the future.
10849             //    Some recycled views cached its layout and a relayout is unnecessary. In this case,
10850             // system still needs to notify content capture the view appeared. When a view is
10851             // recycled, it will set the flag PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED.
10852             final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
10853                     && getVisibility() == VISIBLE
10854                     && !isLayoutRequested();
10855             if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
10856                     || !(isLaidOut() || isRecycledWithoutRelayout)) {
10857                 if (DEBUG_CONTENT_CAPTURE) {
10858                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
10859                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10860                             + ", visible=" + (getVisibility() == VISIBLE)
10861                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10862                             + ", alreadyNotifiedDisappeared="
10863                             + getNotifiedContentCaptureDisappeared());
10864                 }
10865                 return;
10866             }
10867         } else {
10868             if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
10869                 if (DEBUG_CONTENT_CAPTURE) {
10870                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
10871                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10872                             + ", visible=" + (getVisibility() == VISIBLE)
10873                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10874                             + ", alreadyNotifiedDisappeared="
10875                             + getNotifiedContentCaptureDisappeared());
10876                 }
10877                 return;
10878             }
10879         }
10880 
10881         ContentCaptureSession session = getContentCaptureSession();
10882         if (session == null) return;
10883 
10884         // ... and finally at the view level
10885         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
10886         if (!isImportantForContentCapture()) return;
10887 
10888         if (appeared) {
10889             setNotifiedContentCaptureAppeared();
10890 
10891             if (ai != null) {
10892                 makeParentImportantAndNotifyAppearedEventIfNeed();
10893                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10894             } else {
10895                 if (DEBUG_CONTENT_CAPTURE) {
10896                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
10897                 }
10898             }
10899         } else {
10900             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10901             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10902 
10903             if (ai != null) {
10904                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10905             } else {
10906                 if (DEBUG_CONTENT_CAPTURE) {
10907                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
10908                 }
10909             }
10910 
10911             // We reset any translation state as views may be re-used (e.g., as in ListView and
10912             // RecyclerView). We only need to do this for views important for content capture since
10913             // views unimportant for content capture won't be translated anyway.
10914             if (!isTemporarilyDetached()) {
10915                 clearTranslationState();
10916             }
10917         }
10918     }
10919 
10920     private void makeParentImportantAndNotifyAppearedEventIfNeed() {
10921         // If view sent the appeared event to Content Capture, Content Capture also
10922         // would like to receive its parents' appeared events. So checks its parents
10923         // whether the appeared event is sent or not. If not, send the appeared event.
10924         final ViewParent parent = getParent();
10925         if (parent instanceof View) {
10926             View p = ((View) parent);
10927             if (p.getNotifiedContentCaptureAppeared()) {
10928                 return;
10929             }
10930             // Set important for content capture in the cache.
10931             p.mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
10932             p.notifyAppearedOrDisappearedForContentCaptureIfNeeded(/* appeared */ true);
10933         }
10934     }
10935 
10936     private void setNotifiedContentCaptureAppeared() {
10937         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10938         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10939     }
10940 
10941     /** @hide */
10942     protected boolean getNotifiedContentCaptureAppeared() {
10943         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
10944     }
10945 
10946 
10947     private boolean getNotifiedContentCaptureDisappeared() {
10948         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
10949     }
10950 
10951     /**
10952      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
10953      *
10954      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
10955      * the content capture events associated with this view or its view hierarchy (if it's a
10956      * {@link ViewGroup}).
10957      *
10958      * <p>For example, if your activity is associated with a web domain, first you would need to
10959      * set the context for the main DOM:
10960      *
10961      * <pre>
10962      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
10963      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
10964      * </pre>
10965      *
10966      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
10967      *
10968      * <pre>
10969      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
10970      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
10971      *   iframeView.setContentCaptureSession(iframeSession);
10972      * </pre>
10973      *
10974      * @param contentCaptureSession a session created by
10975      * {@link ContentCaptureSession#createContentCaptureSession(
10976      *        android.view.contentcapture.ContentCaptureContext)}.
10977      */
10978     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
10979         mContentCaptureSession = contentCaptureSession;
10980     }
10981 
10982     /**
10983      * Gets the session used to notify content capture events.
10984      *
10985      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
10986      * inherited by ancestors, default session or {@code null} if content capture is disabled for
10987      * this view.
10988      */
10989     @Nullable
10990     public final ContentCaptureSession getContentCaptureSession() {
10991         if (mContentCaptureSessionCached) {
10992             return mContentCaptureSession;
10993         }
10994 
10995         mContentCaptureSession = getAndCacheContentCaptureSession();
10996         mContentCaptureSessionCached = true;
10997         return mContentCaptureSession;
10998     }
10999 
11000     @Nullable
11001     private ContentCaptureSession getAndCacheContentCaptureSession() {
11002         // First try the session explicitly set by setContentCaptureSession()
11003         if (mContentCaptureSession != null) {
11004             return mContentCaptureSession;
11005         }
11006 
11007         // Then the session explicitly set in an ancestor
11008         ContentCaptureSession session = null;
11009         if (mParent instanceof View) {
11010             session = ((View) mParent).getContentCaptureSession();
11011         }
11012 
11013         // Finally, if no session was explicitly set, use the context's default session.
11014         if (session == null) {
11015             final ContentCaptureManager ccm = mContext
11016                     .getSystemService(ContentCaptureManager.class);
11017             return ccm == null ? null : ccm.getMainContentCaptureSession();
11018         }
11019         return session;
11020     }
11021 
11022     @Nullable
11023     private AutofillManager getAutofillManager() {
11024         return mContext.getSystemService(AutofillManager.class);
11025     }
11026 
11027     /**
11028      * Check whether current activity / package is in autofill denylist.
11029      *
11030      * Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
11031      * assist structure
11032      */
11033     final boolean isActivityDeniedForAutofillForUnimportantView() {
11034         final AutofillManager afm = getAutofillManager();
11035         if (afm == null) return false;
11036         return afm.isActivityDeniedForAutofill();
11037     }
11038 
11039     /**
11040      * Check whether current view matches autofillable heuristics
11041      *
11042      * Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
11043      * assist structure
11044      */
11045     final boolean isMatchingAutofillableHeuristics() {
11046         final AutofillManager afm = getAutofillManager();
11047         if (afm == null) return false;
11048         // check the flag to see if trigger fill request on not important views is enabled
11049         return afm.isTriggerFillRequestOnUnimportantViewEnabled()
11050             ? afm.isAutofillable(this) : false;
11051     }
11052 
11053     /**
11054      * Returns whether the view is autofillable.
11055      *
11056      * @return whether the view is autofillable, and should send out autofill request to provider.
11057      */
11058     private boolean isAutofillable() {
11059         if (DBG) {
11060             Log.d(VIEW_LOG_TAG, "isAutofillable() entered.");
11061         }
11062         if (getAutofillType() == AUTOFILL_TYPE_NONE) {
11063             if (DBG) {
11064                 Log.d(VIEW_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
11065             }
11066             return false;
11067         }
11068 
11069         final AutofillManager afm = getAutofillManager();
11070         if (afm == null) {
11071             if (DBG) {
11072                 Log.d(VIEW_LOG_TAG, "AutofillManager is null");
11073             }
11074             return false;
11075         }
11076 
11077         // Check whether view is not part of an activity. If it's not, return false.
11078         if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
11079             if (DBG) {
11080                 Log.d(VIEW_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
11081             }
11082             return false;
11083         }
11084 
11085         // If view is important and filter important view flag is turned on, or view is not
11086         // important and trigger fill request on not important view flag is turned on, then use
11087         // AutofillManager.isAutofillable() to decide whether view is autofillable instead.
11088         if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
11089                 || (!isImportantForAutofill()
11090                     && afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
11091             if (DBG) {
11092                 Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill()
11093                         + "afm.isAutofillable(): " + afm.isAutofillable(this));
11094             }
11095             return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
11096         }
11097 
11098         // If the previous condition is not met, fall back to the previous way to trigger fill
11099         // request based on autofill importance instead.
11100         if (DBG) {
11101             Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
11102         }
11103         return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
11104     }
11105 
11106     private boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
11107         final AutofillOptions options = mContext.getAutofillOptions();
11108         if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
11109             return false;
11110         }
11111         afm.notifyViewEnteredForAugmentedAutofill(this);
11112         return true;
11113     }
11114 
11115     /** @hide */
11116     public boolean canNotifyAutofillEnterExitEvent() {
11117         if (DBG) {
11118             Log.d(VIEW_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
11119                     + " isAutofillable(): " + isAutofillable()
11120                     + " isAttachedToWindow(): " + isAttachedToWindow());
11121         }
11122         return isAutofillable() && isAttachedToWindow();
11123     }
11124 
11125     private void populateVirtualStructure(ViewStructure structure,
11126             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
11127             @Nullable AccessibilityNodeInfo parentInfo, boolean forAutofill) {
11128         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
11129                 null, null, info.getViewIdResourceName());
11130         Rect rect = structure.getTempRect();
11131         // The bounds in parent for Jetpack Compose views aren't set as setBoundsInParent is
11132         // deprecated, and only setBoundsInScreen is called.
11133         // The bounds in parent can be calculated by diff'ing the child view's bounds in screen with
11134         // the parent's.
11135         if (sCalculateBoundsInParentFromBoundsInScreenFlagValue) {
11136             getBoundsInParent(info, parentInfo, rect);
11137         } else {
11138             info.getBoundsInParent(rect);
11139         }
11140         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
11141         structure.setVisibility(VISIBLE);
11142         structure.setEnabled(info.isEnabled());
11143         if (info.isClickable()) {
11144             structure.setClickable(true);
11145         }
11146         if (info.isFocusable()) {
11147             structure.setFocusable(true);
11148         }
11149         if (info.isFocused()) {
11150             structure.setFocused(true);
11151         }
11152         if (info.isAccessibilityFocused()) {
11153             structure.setAccessibilityFocused(true);
11154         }
11155         if (info.isSelected()) {
11156             structure.setSelected(true);
11157         }
11158         if (info.isLongClickable()) {
11159             structure.setLongClickable(true);
11160         }
11161         if (info.isCheckable()) {
11162             structure.setCheckable(true);
11163             if (info.isChecked()) {
11164                 structure.setChecked(true);
11165             }
11166         }
11167         if (info.isContextClickable()) {
11168             structure.setContextClickable(true);
11169         }
11170         if (forAutofill) {
11171             structure.setAutofillId(new AutofillId(getAutofillId(),
11172                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
11173         }
11174         if (getViewCredentialHandler() != null) {
11175             structure.setPendingCredentialRequest(
11176                     getViewCredentialHandler().getRequest(),
11177                     getViewCredentialHandler().getCallback());
11178         }
11179         CharSequence cname = info.getClassName();
11180         structure.setClassName(cname != null ? cname.toString() : null);
11181         structure.setContentDescription(info.getContentDescription());
11182         if (forAutofill) {
11183             final int maxTextLength = info.getMaxTextLength();
11184             if (maxTextLength != -1) {
11185                 structure.setMaxTextLength(maxTextLength);
11186             }
11187             structure.setHint(info.getHintText());
11188         }
11189         CharSequence text = info.getText();
11190         boolean hasText = text != null || info.getError() != null;
11191         if (hasText) {
11192             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
11193         }
11194         if (forAutofill) {
11195             if (info.isEditable()) {
11196                 structure.setDataIsSensitive(true);
11197                 if (hasText) {
11198                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
11199                     structure.setAutofillValue(AutofillValue.forText(text));
11200                 }
11201                 int inputType = info.getInputType();
11202                 if (inputType == 0 && info.isPassword()) {
11203                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
11204                 }
11205                 structure.setInputType(inputType);
11206             } else {
11207                 structure.setDataIsSensitive(false);
11208             }
11209         }
11210         final int NCHILDREN = info.getChildCount();
11211         if (NCHILDREN > 0) {
11212             structure.setChildCount(NCHILDREN);
11213             for (int i=0; i<NCHILDREN; i++) {
11214                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
11215                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
11216                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
11217                     continue;
11218                 }
11219                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
11220                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
11221                 if (cinfo != null) {
11222                     ViewStructure child = structure.newChild(i);
11223                     populateVirtualStructure(child, provider, cinfo, info, forAutofill);
11224                     cinfo.recycle();
11225                 }
11226             }
11227         }
11228     }
11229 
11230     private void getBoundsInParent(@NonNull AccessibilityNodeInfo info,
11231             @Nullable AccessibilityNodeInfo parentInfo, @NonNull Rect rect) {
11232         info.getBoundsInParent(rect);
11233         // Fallback to calculate bounds in parent by diffing the bounds in
11234         // screen if it's all 0.
11235         if ((rect.left | rect.top | rect.right | rect.bottom) == 0) {
11236             if (parentInfo != null) {
11237                 Rect parentBoundsInScreen = parentInfo.getBoundsInScreen();
11238                 Rect boundsInScreen = info.getBoundsInScreen();
11239                 rect.set(boundsInScreen.left - parentBoundsInScreen.left,
11240                         boundsInScreen.top - parentBoundsInScreen.top,
11241                         boundsInScreen.right - parentBoundsInScreen.left,
11242                         boundsInScreen.bottom - parentBoundsInScreen.top);
11243             } else {
11244                 info.getBoundsInScreen(rect);
11245             }
11246         }
11247     }
11248 
11249     /**
11250      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
11251      * implementation calls {@link #onProvideStructure} and
11252      * {@link #onProvideVirtualStructure}.
11253      */
11254     public void dispatchProvideStructure(ViewStructure structure) {
11255         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
11256     }
11257 
11258     /**
11259      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
11260      * when an Assist structure is being created as part of an autofill request.
11261      *
11262      * <p>The default implementation does the following:
11263      * <ul>
11264      *   <li>Sets the {@link AutofillId} in the structure.
11265      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
11266      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
11267      * </ul>
11268      *
11269      * <p>Typically, this method should only be overridden by subclasses that provide a view
11270      * hierarchy (such as {@link ViewGroup}) - other classes should override
11271      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
11272      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
11273      *
11274      * <p>When overridden, it must:
11275      *
11276      * <ul>
11277      *   <li>Either call
11278      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
11279      *       set the {@link AutofillId} in the structure (for example, by calling
11280      *       {@code structure.setAutofillId(getAutofillId())}).
11281      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
11282      *       set, all views in the structure should be considered important for autofill,
11283      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
11284      *       respect this flag to provide a better user experience - this flag is typically used
11285      *       when an user explicitly requested autofill. If the flag is not set,
11286      *       then only views marked as important for autofill should be included in the
11287      *       structure - skipping non-important views optimizes the overall autofill performance.
11288      * </ul>
11289      *
11290      * @param structure fill in with structured view data for autofill purposes.
11291      * @param flags optional flags.
11292      *
11293      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
11294      */
11295     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
11296             @AutofillFlags int flags) {
11297         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
11298     }
11299 
11300     private void dispatchProvideStructure(@NonNull ViewStructure structure,
11301             @ViewStructureType int viewFor, @AutofillFlags int flags) {
11302         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
11303             structure.setAutofillId(getAutofillId());
11304             onProvideAutofillStructure(structure, flags);
11305             onProvideAutofillVirtualStructure(structure, flags);
11306         } else if (!isAssistBlocked()) {
11307             onProvideStructure(structure);
11308             onProvideVirtualStructure(structure);
11309         } else {
11310             structure.setClassName(getAccessibilityClassName().toString());
11311             structure.setAssistBlocked(true);
11312         }
11313     }
11314 
11315     /**
11316      * Dispatches the initial content capture events for a view structure.
11317      *
11318      * @hide
11319      */
11320     public void dispatchInitialProvideContentCaptureStructure() {
11321         AttachInfo ai = mAttachInfo;
11322         if (ai == null) {
11323             Log.w(CONTENT_CAPTURE_LOG_TAG,
11324                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
11325             return;
11326         }
11327         ContentCaptureManager ccm = ai.mContentCaptureManager;
11328         if (ccm == null) {
11329             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
11330                     + "no ContentCaptureManager for " + this);
11331             return;
11332         }
11333 
11334         // We must set it before checkign if the view itself is important, because it might
11335         // initially not be (for example, if it's empty), although that might change later (for
11336         // example, if important views are added)
11337         ai.mReadyForContentCaptureUpdates = true;
11338 
11339         if (!isImportantForContentCapture()) {
11340             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
11341                 Log.d(CONTENT_CAPTURE_LOG_TAG,
11342                         "dispatchProvideContentCaptureStructure(): decorView is not important");
11343             }
11344             return;
11345         }
11346 
11347         ai.mContentCaptureManager = ccm;
11348 
11349         ContentCaptureSession session = getContentCaptureSession();
11350         if (session == null) {
11351             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
11352                 Log.d(CONTENT_CAPTURE_LOG_TAG,
11353                         "dispatchProvideContentCaptureStructure(): no session for " + this);
11354             }
11355             return;
11356         }
11357 
11358         session.notifyViewTreeEvent(/* started= */ true);
11359         try {
11360             dispatchProvideContentCaptureStructure();
11361         } finally {
11362             session.notifyViewTreeEvent(/* started= */ false);
11363         }
11364     }
11365 
11366     /** @hide */
11367     void dispatchProvideContentCaptureStructure() {
11368         ContentCaptureSession session = getContentCaptureSession();
11369         if (session != null) {
11370             ViewStructure structure = session.newViewStructure(this);
11371             onProvideContentCaptureStructure(structure, /* flags= */ 0);
11372             setNotifiedContentCaptureAppeared();
11373             session.notifyViewAppeared(structure);
11374         }
11375     }
11376 
11377     /**
11378      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
11379      *
11380      * Note: Called from the default {@link AccessibilityDelegate}.
11381      *
11382      * @hide
11383      */
11384     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
11385         if (mAttachInfo == null) {
11386             return;
11387         }
11388 
11389         Rect bounds = mAttachInfo.mTmpInvalRect;
11390 
11391         getDrawingRect(bounds);
11392         info.setBoundsInParent(bounds);
11393 
11394         getBoundsOnScreen(bounds, true);
11395         info.setBoundsInScreen(bounds);
11396         getBoundsInWindow(bounds, true);
11397         info.setBoundsInWindow(bounds);
11398 
11399         ViewParent parent = getParentForAccessibility();
11400         if (parent instanceof View) {
11401             info.setParent((View) parent);
11402         }
11403 
11404         if (mID != View.NO_ID) {
11405             View rootView = getRootView();
11406             if (rootView == null) {
11407                 rootView = this;
11408             }
11409 
11410             View label = rootView.findLabelForView(this, mID);
11411             if (label != null) {
11412                 if (supportMultipleLabeledby()) {
11413                     info.addLabeledBy(label);
11414                 } else {
11415                     info.setLabeledBy(label);
11416                 }
11417             }
11418 
11419             if ((mAttachInfo.mAccessibilityFetchFlags
11420                     & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS) != 0
11421                     && Resources.resourceHasPackage(mID)) {
11422                 try {
11423                     String viewId = getResources().getResourceName(mID);
11424                     info.setViewIdResourceName(viewId);
11425                 } catch (Resources.NotFoundException nfe) {
11426                     /* ignore */
11427                 }
11428             }
11429         }
11430 
11431         if (mLabelForId != View.NO_ID) {
11432             View rootView = getRootView();
11433             if (rootView == null) {
11434                 rootView = this;
11435             }
11436             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
11437             if (labeled != null) {
11438                 info.setLabelFor(labeled);
11439             }
11440         }
11441 
11442         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
11443             View rootView = getRootView();
11444             if (rootView == null) {
11445                 rootView = this;
11446             }
11447             View next = rootView.findViewInsideOutShouldExist(this,
11448                     mAccessibilityTraversalBeforeId);
11449             if (next != null && next.includeForAccessibility()) {
11450                 info.setTraversalBefore(next);
11451             }
11452         }
11453 
11454         if (mAccessibilityTraversalAfterId != View.NO_ID) {
11455             View rootView = getRootView();
11456             if (rootView == null) {
11457                 rootView = this;
11458             }
11459             View next = rootView.findViewInsideOutShouldExist(this,
11460                     mAccessibilityTraversalAfterId);
11461             if (next != null && next.includeForAccessibility()) {
11462                 info.setTraversalAfter(next);
11463             }
11464         }
11465 
11466         info.setVisibleToUser(isVisibleToUser());
11467 
11468         info.setImportantForAccessibility(isImportantForAccessibility());
11469         info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
11470         info.setPackageName(mContext.getPackageName());
11471         info.setClassName(getAccessibilityClassName());
11472         info.setStateDescription(getStateDescription());
11473         info.setContentDescription(getContentDescription());
11474 
11475         info.setEnabled(isEnabled());
11476         info.setClickable(isClickable());
11477         info.setFocusable(isFocusable());
11478         info.setScreenReaderFocusable(isScreenReaderFocusable());
11479         info.setFocused(isFocused());
11480         info.setAccessibilityFocused(isAccessibilityFocused());
11481         info.setSelected(isSelected());
11482         info.setLongClickable(isLongClickable());
11483         info.setContextClickable(isContextClickable());
11484         info.setLiveRegion(getAccessibilityLiveRegion());
11485         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
11486             info.setTooltipText(mTooltipInfo.mTooltipText);
11487             info.addAction((mTooltipInfo.mTooltipPopup == null)
11488                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
11489                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
11490         }
11491 
11492         // TODO: These make sense only if we are in an AdapterView but all
11493         // views can be selected. Maybe from accessibility perspective
11494         // we should report as selectable view in an AdapterView.
11495         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
11496         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
11497 
11498         if (isFocusable()) {
11499             if (isFocused()) {
11500                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
11501             } else {
11502                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
11503             }
11504         }
11505 
11506         if (!isAccessibilityFocused()) {
11507             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
11508         } else {
11509             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
11510         }
11511 
11512         if (isClickable() && isEnabled()) {
11513             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
11514         }
11515 
11516         if (isLongClickable() && isEnabled()) {
11517             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
11518         }
11519 
11520         if (isContextClickable() && isEnabled()) {
11521             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
11522         }
11523 
11524         CharSequence text = getIterableTextForAccessibility();
11525         if (text != null && text.length() > 0) {
11526             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
11527 
11528             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
11529             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
11530             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
11531             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
11532                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
11533                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
11534         }
11535 
11536         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
11537         populateAccessibilityNodeInfoDrawingOrderInParent(info);
11538         info.setPaneTitle(mAccessibilityPaneTitle);
11539         info.setHeading(isAccessibilityHeading());
11540 
11541         if (mTouchDelegate != null) {
11542             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
11543         }
11544 
11545         if (startedSystemDragForAccessibility()) {
11546             info.addAction(AccessibilityAction.ACTION_DRAG_CANCEL);
11547         }
11548 
11549         if (canAcceptAccessibilityDrop()) {
11550             info.addAction(AccessibilityAction.ACTION_DRAG_DROP);
11551         }
11552     }
11553 
11554 
11555     /**
11556      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
11557      * additional data.
11558      * <p>
11559      * This method only needs overloading if the node is marked as having extra data available.
11560      * </p>
11561      *
11562      * @param info The info to which to add the extra data. Never {@code null}.
11563      * @param extraDataKey A key specifying the type of extra data to add to the info. The
11564      *                     extra data should be added to the {@link Bundle} returned by
11565      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
11566      *                     {@code null}.
11567      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
11568      *                  {@code null} if the service provided no arguments.
11569      *
11570      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
11571      */
11572     public void addExtraDataToAccessibilityNodeInfo(
11573             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
11574             @Nullable Bundle arguments) {
11575     }
11576 
11577     /**
11578      * Determine the order in which this view will be drawn relative to its siblings for a11y
11579      *
11580      * @param info The info whose drawing order should be populated
11581      */
11582     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
11583         /*
11584          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
11585          * drawing order may not be well-defined, and some Views with custom drawing order may
11586          * not be initialized sufficiently to respond properly getChildDrawingOrder.
11587          */
11588         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
11589             info.setDrawingOrder(0);
11590             return;
11591         }
11592         int drawingOrderInParent = 1;
11593         // Iterate up the hierarchy if parents are not important for a11y
11594         View viewAtDrawingLevel = this;
11595         final ViewParent parent = getParentForAccessibility();
11596         while (viewAtDrawingLevel != parent) {
11597             final ViewParent currentParent = viewAtDrawingLevel.getParent();
11598             if (!(currentParent instanceof ViewGroup)) {
11599                 // Should only happen for the Decor
11600                 drawingOrderInParent = 0;
11601                 break;
11602             } else {
11603                 final ViewGroup parentGroup = (ViewGroup) currentParent;
11604                 final int childCount = parentGroup.getChildCount();
11605                 if (childCount > 1) {
11606                     List<View> preorderedList = parentGroup.buildOrderedChildList();
11607                     if (preorderedList != null) {
11608                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
11609                         for (int i = 0; i < childDrawIndex; i++) {
11610                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
11611                         }
11612                         preorderedList.clear();
11613                     } else {
11614                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
11615                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
11616                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
11617                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
11618                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
11619                         if (childDrawIndex != 0) {
11620                             for (int i = 0; i < numChildrenToIterate; i++) {
11621                                 final int otherDrawIndex = (customOrder ?
11622                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
11623                                 if (otherDrawIndex < childDrawIndex) {
11624                                     drawingOrderInParent +=
11625                                             numViewsForAccessibility(parentGroup.getChildAt(i));
11626                                 }
11627                             }
11628                         }
11629                     }
11630                 }
11631             }
11632             viewAtDrawingLevel = (View) currentParent;
11633         }
11634         info.setDrawingOrder(drawingOrderInParent);
11635     }
11636 
11637     private static int numViewsForAccessibility(View view) {
11638         if (view != null) {
11639             if (view.includeForAccessibility()) {
11640                 return 1;
11641             } else if (view instanceof ViewGroup) {
11642                 return ((ViewGroup) view).getNumChildrenForAccessibility();
11643             }
11644         }
11645         return 0;
11646     }
11647 
11648     private View findLabelForView(View view, int labeledId) {
11649         if (mMatchLabelForPredicate == null) {
11650             mMatchLabelForPredicate = new MatchLabelForPredicate();
11651         }
11652         mMatchLabelForPredicate.mLabeledId = labeledId;
11653         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
11654     }
11655 
11656     /**
11657      * Computes whether this virtual autofill view is visible to the user.
11658      *
11659      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
11660      * view must override it.
11661      *
11662      * @return Whether the view is visible on the screen.
11663      */
11664     public boolean isVisibleToUserForAutofill(int virtualId) {
11665         if (mContext.isAutofillCompatibilityEnabled()) {
11666             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
11667             if (provider != null) {
11668                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
11669                 if (node != null) {
11670                     return node.isVisibleToUser();
11671                 }
11672                 // if node is null, assume it's not visible anymore
11673             } else {
11674                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
11675             }
11676             return false;
11677         }
11678         return true;
11679     }
11680 
11681     /**
11682      * Computes whether this view is visible to the user. Such a view is
11683      * attached, visible, all its predecessors are visible, it is not clipped
11684      * entirely by its predecessors, and has an alpha greater than zero.
11685      *
11686      * @return Whether the view is visible on the screen.
11687      *
11688      * @hide
11689      */
11690     @UnsupportedAppUsage
11691     public boolean isVisibleToUser() {
11692         return isVisibleToUser(null);
11693     }
11694 
11695     /**
11696      * Computes whether the given portion of this view is visible to the user.
11697      * Such a view is attached, visible, all its predecessors are visible,
11698      * has an alpha greater than zero, and the specified portion is not
11699      * clipped entirely by its predecessors.
11700      *
11701      * @param boundInView the portion of the view to test; coordinates should be relative; may be
11702      *                    <code>null</code>, and the entire view will be tested in this case.
11703      *                    When <code>true</code> is returned by the function, the actual visible
11704      *                    region will be stored in this parameter; that is, if boundInView is fully
11705      *                    contained within the view, no modification will be made, otherwise regions
11706      *                    outside of the visible area of the view will be clipped.
11707      *
11708      * @return Whether the specified portion of the view is visible on the screen.
11709      *
11710      * @hide
11711      */
11712     @UnsupportedAppUsage(trackingBug = 171933273)
11713     protected boolean isVisibleToUser(Rect boundInView) {
11714         if (mAttachInfo != null) {
11715             // Attached to invisible window means this view is not visible.
11716             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
11717                 return false;
11718             }
11719             // An invisible predecessor or one with alpha zero means
11720             // that this view is not visible to the user.
11721             Object current = this;
11722             while (current instanceof View) {
11723                 View view = (View) current;
11724                 // We have attach info so this view is attached and there is no
11725                 // need to check whether we reach to ViewRootImpl on the way up.
11726                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
11727                         view.getVisibility() != VISIBLE) {
11728                     return false;
11729                 }
11730                 current = view.mParent;
11731             }
11732             // Check if the view is entirely covered by its predecessors.
11733             Rect visibleRect = mAttachInfo.mTmpInvalRect;
11734             Point offset = mAttachInfo.mPoint;
11735             if (!getGlobalVisibleRect(visibleRect, offset)) {
11736                 return false;
11737             }
11738             // Check if the visible portion intersects the rectangle of interest.
11739             if (boundInView != null) {
11740                 visibleRect.offset(-offset.x, -offset.y);
11741                 return boundInView.intersect(visibleRect);
11742             }
11743             return true;
11744         }
11745         return false;
11746     }
11747 
11748     /**
11749      * Returns the delegate for implementing accessibility support via
11750      * composition. For more details see {@link AccessibilityDelegate}.
11751      *
11752      * @return The delegate, or null if none set.
11753      */
11754     public AccessibilityDelegate getAccessibilityDelegate() {
11755         return mAccessibilityDelegate;
11756     }
11757 
11758     /**
11759      * Sets a delegate for implementing accessibility support via composition
11760      * (as opposed to inheritance). For more details, see
11761      * {@link AccessibilityDelegate}.
11762      * <p>
11763      * <strong>Note:</strong> On platform versions prior to
11764      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
11765      * views in the {@code android.widget.*} package are called <i>before</i>
11766      * host methods. This prevents certain properties such as class name from
11767      * being modified by overriding
11768      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
11769      * as any changes will be overwritten by the host class.
11770      * <p>
11771      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
11772      * methods are called <i>after</i> host methods, which all properties to be
11773      * modified without being overwritten by the host class.
11774      *
11775      * @param delegate the object to which accessibility method calls should be
11776      *                 delegated
11777      * @see AccessibilityDelegate
11778      */
11779     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
11780         mAccessibilityDelegate = delegate;
11781     }
11782 
11783     /**
11784      * Gets the provider for managing a virtual view hierarchy rooted at this View
11785      * and reported to {@link android.accessibilityservice.AccessibilityService}s
11786      * that explore the window content.
11787      * <p>
11788      * If this method returns an instance, this instance is responsible for managing
11789      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
11790      * View including the one representing the View itself. Similarly the returned
11791      * instance is responsible for performing accessibility actions on any virtual
11792      * view or the root view itself.
11793      * </p>
11794      * <p>
11795      * If an {@link AccessibilityDelegate} has been specified via calling
11796      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11797      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
11798      * is responsible for handling this call.
11799      * </p>
11800      *
11801      * @return The provider.
11802      *
11803      * @see AccessibilityNodeProvider
11804      */
11805     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
11806         if (mAccessibilityDelegate != null) {
11807             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
11808         } else {
11809             return null;
11810         }
11811     }
11812 
11813     /**
11814      * Gets the unique identifier of this view on the screen for accessibility purposes.
11815      *
11816      * @return The view accessibility id.
11817      *
11818      * @hide
11819      */
11820     @UnsupportedAppUsage
11821     public int getAccessibilityViewId() {
11822         if (mAccessibilityViewId == NO_ID) {
11823             mAccessibilityViewId = sNextAccessibilityViewId++;
11824         }
11825         return mAccessibilityViewId;
11826     }
11827 
11828     /**
11829      * Gets the unique identifier of this view on the screen for autofill purposes.
11830      *
11831      * @return The view autofill id.
11832      *
11833      * @hide
11834      */
11835     public int getAutofillViewId() {
11836         if (mAutofillViewId == NO_ID) {
11837             mAutofillViewId = mContext.getNextAutofillId();
11838         }
11839         return mAutofillViewId;
11840     }
11841 
11842     /**
11843      * Gets the unique identifier of the window in which this View resides.
11844      *
11845      * @return The window accessibility id.
11846      *
11847      * @hide
11848      */
11849     public int getAccessibilityWindowId() {
11850         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
11851                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
11852     }
11853 
11854     /**
11855      * Returns the {@link View}'s state description.
11856      * <p>
11857      * <strong>Note:</strong> Do not override this method, as it will have no
11858      * effect on the state description presented to accessibility services.
11859      * You must call {@link #setStateDescription(CharSequence)} to modify the
11860      * state description.
11861      *
11862      * @return the state description
11863      * @see #setStateDescription(CharSequence)
11864      */
11865     @ViewDebug.ExportedProperty(category = "accessibility")
11866     public final @Nullable CharSequence getStateDescription() {
11867         return mStateDescription;
11868     }
11869 
11870     /**
11871      * Returns the {@link View}'s content description.
11872      * <p>
11873      * <strong>Note:</strong> Do not override this method, as it will have no
11874      * effect on the content description presented to accessibility services.
11875      * You must call {@link #setContentDescription(CharSequence)} to modify the
11876      * content description.
11877      *
11878      * @return the content description
11879      * @see #setContentDescription(CharSequence)
11880      * @attr ref android.R.styleable#View_contentDescription
11881      */
11882     @ViewDebug.ExportedProperty(category = "accessibility")
11883     @InspectableProperty
11884     public CharSequence getContentDescription() {
11885         return mContentDescription;
11886     }
11887 
11888     /**
11889      * Returns the {@link View}'s supplemental description.
11890      * <p>
11891      * A supplemental description provides
11892      * brief supplemental information for this node, such as the purpose of the node when
11893      * that purpose is not conveyed within its textual representation. For example, if a
11894      * dropdown select has a purpose of setting font family, the supplemental description
11895      * could be "font family". If this node has children, its supplemental description serves
11896      * as additional information and is not intended to replace any existing information
11897      * in the subtree. This is different from the {@link #getContentDescription()} in that
11898      * this description is purely supplemental while a content description may be used
11899      * to replace a description for a node or its subtree that an assistive technology
11900      * would otherwise compute based on other properties of the node and its descendants.
11901      *
11902      * <p>
11903      * <strong>Note:</strong> Do not override this method, as it will have no
11904      * effect on the supplemental description presented to accessibility services.
11905      * You must call {@link #setSupplementalDescription(CharSequence)} to modify the
11906      * supplemental description.
11907      *
11908      * @return the supplemental description
11909      * @see #setSupplementalDescription(CharSequence)
11910      * @see #getContentDescription()
11911      * @attr ref android.R.styleable#View_supplementalDescription
11912      */
11913     @FlaggedApi(FLAG_SUPPLEMENTAL_DESCRIPTION)
11914     @ViewDebug.ExportedProperty(category = "accessibility")
11915     @InspectableProperty
11916     @Nullable
11917     public CharSequence getSupplementalDescription() {
11918         return mSupplementalDescription;
11919     }
11920 
11921     /**
11922      * Sets the {@link View}'s state description.
11923      * <p>
11924      * A state description briefly describes the states of the view and is primarily used
11925      * for accessibility support to determine how the states of a view should be presented to
11926      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
11927      * it is used for customized state description (for example, "wifi, connected, three bars").
11928      * State description changes frequently while content description should change less often.
11929      * State description should be localized. For android widgets which have default state
11930      * descriptions, app developers can call this method to override the state descriptions.
11931      * Setting state description to null restores the default behavior.
11932      *
11933      * @param stateDescription The state description.
11934      * @see #getStateDescription()
11935      * @see #setContentDescription(CharSequence) for the difference between content and
11936      * state descriptions.
11937      */
11938     @RemotableViewMethod
11939     public void setStateDescription(@Nullable CharSequence stateDescription) {
11940         if (mStateDescription == null) {
11941             if (stateDescription == null) {
11942                 return;
11943             }
11944         } else if (mStateDescription.equals(stateDescription)) {
11945             return;
11946         }
11947         mStateDescription = stateDescription;
11948         if (!TextUtils.isEmpty(stateDescription)
11949                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
11950             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
11951         }
11952         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11953             AccessibilityEvent event = AccessibilityEvent.obtain();
11954             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11955             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
11956             sendAccessibilityEventUnchecked(event);
11957         }
11958     }
11959 
11960     /**
11961      * Sets the {@link View}'s content description.
11962      * <p>
11963      * A content description briefly describes the view and is primarily used
11964      * for accessibility support to determine how a view should be presented to
11965      * the user. In the case of a view with no textual representation, such as
11966      * {@link android.widget.ImageButton}, a useful content description
11967      * explains what the view does. For example, an image button with a phone
11968      * icon that is used to place a call may use "Call" as its content
11969      * description. An image of a floppy disk that is used to save a file may
11970      * use "Save".
11971      *
11972      * <p>
11973      * This should omit role or state. Role refers to the kind of user-interface element the View
11974      * is, such as a Button or Checkbox. State refers to a frequently changing property of the View,
11975      * such as an On/Off state of a button or the audio level of a volume slider.
11976      *
11977      * <p>
11978      * Content description updates are not frequent, and are used when the semantic content - not
11979      * the state - of the element changes. For example, a Play button might change to a Pause
11980      * button during music playback.
11981      *
11982      * @param contentDescription The content description.
11983      * @see #getContentDescription()
11984      * @see #setStateDescription(CharSequence)} for state changes.
11985      * @attr ref android.R.styleable#View_contentDescription
11986      */
11987     @RemotableViewMethod
11988     public void setContentDescription(CharSequence contentDescription) {
11989         if (mContentDescription == null) {
11990             if (contentDescription == null) {
11991                 return;
11992             }
11993         } else if (mContentDescription.equals(contentDescription)) {
11994             return;
11995         }
11996         mContentDescription = contentDescription;
11997         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
11998         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
11999             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
12000             notifySubtreeAccessibilityStateChangedIfNeeded();
12001         } else {
12002             notifyViewAccessibilityStateChangedIfNeeded(
12003                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
12004         }
12005     }
12006 
12007     /**
12008      * Sets the {@link View}'s supplemental description.
12009      * <p>
12010      * A supplemental description provides
12011      * brief supplemental information for this node, such as the purpose of the node when
12012      * that purpose is not conveyed within its textual representation. For example, if a
12013      * dropdown select has a purpose of setting font family, the supplemental description
12014      * could be "font family". If this node has children, its supplemental description serves
12015      * as additional information and is not intended to replace any existing information
12016      * in the subtree. This is different from the {@link #setContentDescription(CharSequence)}
12017      * in that this description is purely supplemental while a content description may be used
12018      * to replace a description for a node or its subtree that an assistive technology
12019      * would otherwise compute based on other properties of the node and its descendants.
12020      *
12021      * <p>
12022      * This should omit role or state. Role refers to the kind of user-interface element the View
12023      * is, such as a Button or Checkbox. State refers to a frequently changing property of the View,
12024      * such as an On/Off state of a button or the audio level of a volume slider.
12025      *
12026      * @param supplementalDescription The supplemental description.
12027      * @see #getSupplementalDescription()
12028      * @see #setContentDescription(CharSequence)
12029      * @see #setStateDescription(CharSequence) for state changes.
12030      * @attr ref android.R.styleable#View_supplementalDescription
12031      */
12032     @FlaggedApi(FLAG_SUPPLEMENTAL_DESCRIPTION)
12033     @RemotableViewMethod
12034     public void setSupplementalDescription(@Nullable CharSequence supplementalDescription) {
12035         if (mSupplementalDescription == null) {
12036             if (supplementalDescription == null) {
12037                 return;
12038             }
12039         } else if (mSupplementalDescription.equals(supplementalDescription)) {
12040             return;
12041         }
12042         mSupplementalDescription = supplementalDescription;
12043         final boolean nonEmptyDesc = supplementalDescription != null
12044                 && !supplementalDescription.isEmpty();
12045         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
12046             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
12047             notifySubtreeAccessibilityStateChangedIfNeeded();
12048         } else {
12049             notifyViewAccessibilityStateChangedIfNeeded(
12050                     AccessibilityEvent.CONTENT_CHANGE_TYPE_SUPPLEMENTAL_DESCRIPTION);
12051         }
12052     }
12053 
12054     /**
12055      * Sets the id of a view that screen readers are requested to visit after this view.
12056      *
12057      * <p>
12058      *
12059      * For example, if view B should be visited before view A, with
12060      * B.setAccessibilityTraversalBefore(A), this requests that screen readers visit and traverse
12061      * view B before visiting view A.
12062      *
12063      * <p>
12064      * <b>Note:</b> Views are visited in the order determined by the screen reader. Avoid
12065      * explicitly manipulating focus order, as this may result in inconsistent user
12066      * experiences between apps. Instead, use other semantics, such as restructuring the view
12067      * hierarchy layout, to communicate order.
12068      *
12069      * <p>
12070      * Setting this view to be after a view that is not important for accessibility,
12071      * or if this view is not important for accessibility, means this method will have no effect if
12072      * the service is not aware of unimportant views.
12073      *
12074      * <p>
12075      * To avoid a risk of loops, set clear relationships between views. For example, if focus order
12076      * should be B -> A, and B.setAccessibilityTraversalBefore(A), then also call
12077      * A.setAccessibilityTraversalAfter(B).
12078      *
12079      * @param beforeId The id of a view this one precedes in accessibility traversal.
12080      *
12081      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
12082      *
12083      * @see #setImportantForAccessibility(int)
12084      * @see #setAccessibilityTraversalAfter(int)
12085      */
12086     @RemotableViewMethod
12087     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
12088         if (mAccessibilityTraversalBeforeId == beforeId) {
12089             return;
12090         }
12091         mAccessibilityTraversalBeforeId = beforeId;
12092         notifyViewAccessibilityStateChangedIfNeeded(
12093                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12094     }
12095 
12096     /**
12097      * Gets the id of a view before which this one is visited in accessibility traversal.
12098      *
12099      * @return The id of a view this one precedes in accessibility traversal if
12100      *         specified, otherwise {@link #NO_ID}.
12101      *
12102      * @see #setAccessibilityTraversalBefore(int)
12103      */
12104     @IdRes
12105     @InspectableProperty
12106     public int getAccessibilityTraversalBefore() {
12107         return mAccessibilityTraversalBeforeId;
12108     }
12109 
12110     /**
12111      * Sets the id of a view that screen readers are requested to visit before this view.
12112      *
12113      * <p>
12114      * For example, if view B should be visited after A, with B.setAccessibilityTraversalAfter(A),
12115      * then this requests that screen readers visit and traverse view A before visiting view B.
12116      *
12117      * <p>
12118      * <b>Note:</b> Views are visited in the order determined by the screen reader. Avoid
12119      * explicitly manipulating focus order, as this may result in inconsistent user
12120      * experiences between apps. Instead, use other semantics, such as restructuring the view
12121      * hierarchy layout, to communicate order.
12122      *
12123      * <p>
12124      * Setting this view to be after a view that is not important for accessibility,
12125      * or if this view is not important for accessibility, means this method will have no effect if
12126      * the service is not aware of unimportant views.
12127      *
12128      * <p>
12129      * To avoid a risk of loops, set clear relationships between views. For example, if focus order
12130      * should be B -> A, and B.setAccessibilityTraversalBefore(A), then also call
12131      * A.setAccessibilityTraversalAfter(B).
12132      *
12133      * @param afterId The id of a view this one succeeds in accessibility traversal.
12134      *
12135      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
12136      *
12137      * @see #setImportantForAccessibility(int)
12138      * @see #setAccessibilityTraversalBefore(int)
12139      */
12140     @RemotableViewMethod
12141     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
12142         if (mAccessibilityTraversalAfterId == afterId) {
12143             return;
12144         }
12145         mAccessibilityTraversalAfterId = afterId;
12146         notifyViewAccessibilityStateChangedIfNeeded(
12147                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12148     }
12149 
12150     /**
12151      * Gets the id of a view after which this one is visited in accessibility traversal.
12152      *
12153      * @return The id of a view this one succeedes in accessibility traversal if
12154      *         specified, otherwise {@link #NO_ID}.
12155      *
12156      * @see #setAccessibilityTraversalAfter(int)
12157      */
12158     @IdRes
12159     @InspectableProperty
12160     public int getAccessibilityTraversalAfter() {
12161         return mAccessibilityTraversalAfterId;
12162     }
12163 
12164     /**
12165      * Gets the id of a view for which this view serves as a label for
12166      * accessibility purposes.
12167      *
12168      * @return The labeled view id.
12169      */
12170     @IdRes
12171     @ViewDebug.ExportedProperty(category = "accessibility")
12172     @InspectableProperty
12173     public int getLabelFor() {
12174         return mLabelForId;
12175     }
12176 
12177     /**
12178      * Sets the id of a view for which this view serves as a label for
12179      * accessibility purposes.
12180      *
12181      * @param id The labeled view id.
12182      */
12183     @RemotableViewMethod
12184     public void setLabelFor(@IdRes int id) {
12185         if (mLabelForId == id) {
12186             return;
12187         }
12188         mLabelForId = id;
12189         if (mLabelForId != View.NO_ID
12190                 && mID == View.NO_ID) {
12191             mID = generateViewId();
12192         }
12193         notifyViewAccessibilityStateChangedIfNeeded(
12194                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12195     }
12196 
12197     /**
12198      * Invoked whenever this view loses focus, either by losing window focus or by losing
12199      * focus within its window. This method can be used to clear any state tied to the
12200      * focus. For instance, if a button is held pressed with the trackball and the window
12201      * loses focus, this method can be used to cancel the press.
12202      *
12203      * Subclasses of View overriding this method should always call super.onFocusLost().
12204      *
12205      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
12206      * @see #onWindowFocusChanged(boolean)
12207      *
12208      * @hide pending API council approval
12209      */
12210     @CallSuper
12211     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
12212     protected void onFocusLost() {
12213         resetPressedState();
12214     }
12215 
12216     private void resetPressedState() {
12217         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12218             return;
12219         }
12220 
12221         if (isPressed()) {
12222             setPressed(false);
12223 
12224             if (!mHasPerformedLongPress) {
12225                 removeLongPressCallback();
12226             }
12227         }
12228     }
12229 
12230     /**
12231      * Returns true if this view has focus
12232      *
12233      * @return True if this view has focus, false otherwise.
12234      */
12235     @ViewDebug.ExportedProperty(category = "focus")
12236     @InspectableProperty(hasAttributeId = false)
12237     public boolean isFocused() {
12238         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
12239     }
12240 
12241     /**
12242      * Find the view in the hierarchy rooted at this view that currently has
12243      * focus.
12244      *
12245      * @return The view that currently has focus, or null if no focused view can
12246      *         be found.
12247      */
12248     public View findFocus() {
12249         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
12250     }
12251 
12252     /**
12253      * Indicates whether this view is one of the set of scrollable containers in
12254      * its window.
12255      *
12256      * @return whether this view is one of the set of scrollable containers in
12257      * its window
12258      *
12259      * @attr ref android.R.styleable#View_isScrollContainer
12260      */
12261     @InspectableProperty(name = "isScrollContainer")
12262     public boolean isScrollContainer() {
12263         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
12264     }
12265 
12266     /**
12267      * Change whether this view is one of the set of scrollable containers in
12268      * its window.  This will be used to determine whether the window can
12269      * resize or must pan when a soft input area is open -- scrollable
12270      * containers allow the window to use resize mode since the container
12271      * will appropriately shrink.
12272      *
12273      * @attr ref android.R.styleable#View_isScrollContainer
12274      */
12275     public void setScrollContainer(boolean isScrollContainer) {
12276         if (isScrollContainer) {
12277             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
12278                 mAttachInfo.mScrollContainers.add(this);
12279                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
12280             }
12281             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
12282         } else {
12283             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
12284                 mAttachInfo.mScrollContainers.remove(this);
12285             }
12286             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
12287         }
12288     }
12289 
12290     /**
12291      * Returns the quality of the drawing cache.
12292      *
12293      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
12294      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
12295      *
12296      * @see #setDrawingCacheQuality(int)
12297      * @see #setDrawingCacheEnabled(boolean)
12298      * @see #isDrawingCacheEnabled()
12299      *
12300      * @attr ref android.R.styleable#View_drawingCacheQuality
12301      *
12302      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12303      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12304      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12305      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12306      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12307      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12308      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12309      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12310      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12311      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12312      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12313      * reports or unit testing the {@link PixelCopy} API is recommended.
12314      */
12315     @Deprecated
12316     @DrawingCacheQuality
12317     @InspectableProperty(enumMapping = {
12318             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
12319             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
12320             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
12321     })
12322     public int getDrawingCacheQuality() {
12323         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
12324     }
12325 
12326     /**
12327      * Set the drawing cache quality of this view. This value is used only when the
12328      * drawing cache is enabled
12329      *
12330      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
12331      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
12332      *
12333      * @see #getDrawingCacheQuality()
12334      * @see #setDrawingCacheEnabled(boolean)
12335      * @see #isDrawingCacheEnabled()
12336      *
12337      * @attr ref android.R.styleable#View_drawingCacheQuality
12338      *
12339      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12340      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12341      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12342      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12343      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12344      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12345      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12346      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12347      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12348      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12349      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12350      * reports or unit testing the {@link PixelCopy} API is recommended.
12351      */
12352     @Deprecated
12353     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
12354         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
12355     }
12356 
12357     /**
12358      * Returns whether the screen should remain on, corresponding to the current
12359      * value of {@link #KEEP_SCREEN_ON}.
12360      *
12361      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
12362      *
12363      * @see #setKeepScreenOn(boolean)
12364      *
12365      * @attr ref android.R.styleable#View_keepScreenOn
12366      */
12367     @InspectableProperty
12368     public boolean getKeepScreenOn() {
12369         return (mViewFlags & KEEP_SCREEN_ON) != 0;
12370     }
12371 
12372     /**
12373      * Controls whether the screen should remain on, modifying the
12374      * value of {@link #KEEP_SCREEN_ON}.
12375      *
12376      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
12377      *
12378      * @see #getKeepScreenOn()
12379      *
12380      * @attr ref android.R.styleable#View_keepScreenOn
12381      */
12382     public void setKeepScreenOn(boolean keepScreenOn) {
12383         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
12384     }
12385 
12386     /**
12387      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
12388      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12389      *
12390      * @attr ref android.R.styleable#View_nextFocusLeft
12391      */
12392     @IdRes
12393     @InspectableProperty(name = "nextFocusLeft")
12394     public int getNextFocusLeftId() {
12395         return mNextFocusLeftId;
12396     }
12397 
12398     /**
12399      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
12400      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
12401      * decide automatically.
12402      *
12403      * @attr ref android.R.styleable#View_nextFocusLeft
12404      */
12405     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
12406         mNextFocusLeftId = nextFocusLeftId;
12407     }
12408 
12409     /**
12410      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
12411      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12412      *
12413      * @attr ref android.R.styleable#View_nextFocusRight
12414      */
12415     @IdRes
12416     @InspectableProperty(name = "nextFocusRight")
12417     public int getNextFocusRightId() {
12418         return mNextFocusRightId;
12419     }
12420 
12421     /**
12422      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
12423      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
12424      * decide automatically.
12425      *
12426      * @attr ref android.R.styleable#View_nextFocusRight
12427      */
12428     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
12429         mNextFocusRightId = nextFocusRightId;
12430     }
12431 
12432     /**
12433      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
12434      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12435      *
12436      * @attr ref android.R.styleable#View_nextFocusUp
12437      */
12438     @IdRes
12439     @InspectableProperty(name = "nextFocusUp")
12440     public int getNextFocusUpId() {
12441         return mNextFocusUpId;
12442     }
12443 
12444     /**
12445      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
12446      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
12447      * decide automatically.
12448      *
12449      * @attr ref android.R.styleable#View_nextFocusUp
12450      */
12451     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
12452         mNextFocusUpId = nextFocusUpId;
12453     }
12454 
12455     /**
12456      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
12457      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12458      *
12459      * @attr ref android.R.styleable#View_nextFocusDown
12460      */
12461     @IdRes
12462     @InspectableProperty(name = "nextFocusDown")
12463     public int getNextFocusDownId() {
12464         return mNextFocusDownId;
12465     }
12466 
12467     /**
12468      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
12469      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
12470      * decide automatically.
12471      *
12472      * @attr ref android.R.styleable#View_nextFocusDown
12473      */
12474     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
12475         mNextFocusDownId = nextFocusDownId;
12476     }
12477 
12478     /**
12479      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
12480      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
12481      *
12482      * @attr ref android.R.styleable#View_nextFocusForward
12483      */
12484     @IdRes
12485     @InspectableProperty(name = "nextFocusForward")
12486     public int getNextFocusForwardId() {
12487         return mNextFocusForwardId;
12488     }
12489 
12490     /**
12491      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
12492      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
12493      * decide automatically.
12494      *
12495      * @attr ref android.R.styleable#View_nextFocusForward
12496      */
12497     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
12498         mNextFocusForwardId = nextFocusForwardId;
12499     }
12500 
12501     /**
12502      * Gets the id of the root of the next keyboard navigation cluster.
12503      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
12504      * decide automatically.
12505      *
12506      * @attr ref android.R.styleable#View_nextClusterForward
12507      */
12508     @IdRes
12509     @InspectableProperty(name = "nextClusterForward")
12510     public int getNextClusterForwardId() {
12511         return mNextClusterForwardId;
12512     }
12513 
12514     /**
12515      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
12516      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
12517      * decide automatically.
12518      *
12519      * @attr ref android.R.styleable#View_nextClusterForward
12520      */
12521     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
12522         mNextClusterForwardId = nextClusterForwardId;
12523     }
12524 
12525     /**
12526      * Returns the visibility of this view and all of its ancestors
12527      *
12528      * @return True if this view and all of its ancestors are {@link #VISIBLE}
12529      */
12530     public boolean isShown() {
12531         View current = this;
12532         //noinspection ConstantConditions
12533         do {
12534             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
12535                 return false;
12536             }
12537             ViewParent parent = current.mParent;
12538             if (parent == null) {
12539                 return false; // We are not attached to the view root
12540             }
12541             if (!(parent instanceof View)) {
12542                 return true;
12543             }
12544             current = (View) parent;
12545         } while (current != null);
12546 
12547         return false;
12548     }
12549 
12550     private boolean detached() {
12551         View current = this;
12552         //noinspection ConstantConditions
12553         do {
12554             if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
12555                 return true;
12556             }
12557             ViewParent parent = current.mParent;
12558             if (parent == null) {
12559                 return false;
12560             }
12561             if (!(parent instanceof View)) {
12562                 return false;
12563             }
12564             current = (View) parent;
12565         } while (current != null);
12566 
12567         return false;
12568     }
12569 
12570     /**
12571      * Called by the view hierarchy when the content insets for a window have
12572      * changed, to allow it to adjust its content to fit within those windows.
12573      * The content insets tell you the space that the status bar, input method,
12574      * and other system windows infringe on the application's window.
12575      *
12576      * <p>You do not normally need to deal with this function, since the default
12577      * window decoration given to applications takes care of applying it to the
12578      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
12579      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
12580      * and your content can be placed under those system elements.  You can then
12581      * use this method within your view hierarchy if you have parts of your UI
12582      * which you would like to ensure are not being covered.
12583      *
12584      * <p>The default implementation of this method simply applies the content
12585      * insets to the view's padding, consuming that content (modifying the
12586      * insets to be 0), and returning true.  This behavior is off by default, but can
12587      * be enabled through {@link #setFitsSystemWindows(boolean)}.
12588      *
12589      * <p>This function's traversal down the hierarchy is depth-first.  The same content
12590      * insets object is propagated down the hierarchy, so any changes made to it will
12591      * be seen by all following views (including potentially ones above in
12592      * the hierarchy since this is a depth-first traversal).  The first view
12593      * that returns true will abort the entire traversal.
12594      *
12595      * <p>The default implementation works well for a situation where it is
12596      * used with a container that covers the entire window, allowing it to
12597      * apply the appropriate insets to its content on all edges.  If you need
12598      * a more complicated layout (such as two different views fitting system
12599      * windows, one on the top of the window, and one on the bottom),
12600      * you can override the method and handle the insets however you would like.
12601      * Note that the insets provided by the framework are always relative to the
12602      * far edges of the window, not accounting for the location of the called view
12603      * within that window.  (In fact when this method is called you do not yet know
12604      * where the layout will place the view, as it is done before layout happens.)
12605      *
12606      * <p>Note: unlike many View methods, there is no dispatch phase to this
12607      * call.  If you are overriding it in a ViewGroup and want to allow the
12608      * call to continue to your children, you must be sure to call the super
12609      * implementation.
12610      *
12611      * <p>Here is a sample layout that makes use of fitting system windows
12612      * to have controls for a video view placed inside of the window decorations
12613      * that it hides and shows.  This can be used with code like the second
12614      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
12615      *
12616      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
12617      *
12618      * @param insets Current content insets of the window.  Prior to
12619      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
12620      * the insets or else you and Android will be unhappy.
12621      *
12622      * @return {@code true} if this view applied the insets and it should not
12623      * continue propagating further down the hierarchy, {@code false} otherwise.
12624      * @see #getFitsSystemWindows()
12625      * @see #setFitsSystemWindows(boolean)
12626      * @see #setSystemUiVisibility(int)
12627      *
12628      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
12629      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
12630      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
12631      * to implement handling their own insets.
12632      */
12633     @Deprecated
12634     protected boolean fitSystemWindows(Rect insets) {
12635         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
12636             if (insets == null) {
12637                 // Null insets by definition have already been consumed.
12638                 // This call cannot apply insets since there are none to apply,
12639                 // so return false.
12640                 return false;
12641             }
12642             // If we're not in the process of dispatching the newer apply insets call,
12643             // that means we're not in the compatibility path. Dispatch into the newer
12644             // apply insets path and take things from there.
12645             try {
12646                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
12647                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
12648             } finally {
12649                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
12650             }
12651         } else {
12652             // We're being called from the newer apply insets path.
12653             // Perform the standard fallback behavior.
12654             return fitSystemWindowsInt(insets);
12655         }
12656     }
12657 
12658     private boolean fitSystemWindowsInt(Rect insets) {
12659         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
12660             Rect localInsets = sThreadLocal.get();
12661             boolean res = computeFitSystemWindows(insets, localInsets);
12662             applyInsets(localInsets);
12663             return res;
12664         }
12665         return false;
12666     }
12667 
12668     private void applyInsets(Rect insets) {
12669         mUserPaddingStart = UNDEFINED_PADDING;
12670         mUserPaddingEnd = UNDEFINED_PADDING;
12671         mUserPaddingLeftInitial = insets.left;
12672         mUserPaddingRightInitial = insets.right;
12673         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
12674     }
12675 
12676     /**
12677      * Called when the view should apply {@link WindowInsets} according to its internal policy.
12678      *
12679      * <p>This method should be overridden by views that wish to apply a policy different from or
12680      * in addition to the default behavior. Clients that wish to force a view subtree
12681      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
12682      *
12683      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
12684      * it will be called during dispatch instead of this method. The listener may optionally
12685      * call this method from its own implementation if it wishes to apply the view's default
12686      * insets policy in addition to its own.</p>
12687      *
12688      * <p>Implementations of this method should either return the insets parameter unchanged
12689      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
12690      * that this view applied itself. This allows new inset types added in future platform
12691      * versions to pass through existing implementations unchanged without being erroneously
12692      * consumed.</p>
12693      *
12694      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
12695      * property is set then the view will consume the system window insets and apply them
12696      * as padding for the view.</p>
12697      *
12698      * @param insets Insets to apply
12699      * @return The supplied insets with any applied insets consumed
12700      */
12701     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
12702         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
12703                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
12704             return onApplyFrameworkOptionalFitSystemWindows(insets);
12705         }
12706         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
12707             // We weren't called from within a direct call to fitSystemWindows,
12708             // call into it as a fallback in case we're in a class that overrides it
12709             // and has logic to perform.
12710             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
12711                 return insets.consumeSystemWindowInsets();
12712             }
12713         } else {
12714             // We were called from within a direct call to fitSystemWindows.
12715             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
12716                 return insets.consumeSystemWindowInsets();
12717             }
12718         }
12719         return insets;
12720     }
12721 
12722     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
12723         Rect localInsets = sThreadLocal.get();
12724         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
12725         applyInsets(localInsets);
12726         return result;
12727     }
12728 
12729     /**
12730      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
12731      * window insets to this view. The listener's
12732      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
12733      * method will be called instead of the view's
12734      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
12735      *
12736      * @param listener Listener to set
12737      *
12738      * @see #onApplyWindowInsets(WindowInsets)
12739      */
12740     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
12741         getListenerInfo().mOnApplyWindowInsetsListener = listener;
12742     }
12743 
12744     /**
12745      * Request to apply the given window insets to this view or another view in its subtree.
12746      *
12747      * <p>This method should be called by clients wishing to apply insets corresponding to areas
12748      * obscured by window decorations or overlays. This can include the status and navigation bars,
12749      * action bars, input methods and more. New inset categories may be added in the future.
12750      * The method returns the insets provided minus any that were applied by this view or its
12751      * children.</p>
12752      *
12753      * <p>Clients wishing to provide custom behavior should override the
12754      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
12755      * {@link OnApplyWindowInsetsListener} via the
12756      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
12757      * method.</p>
12758      *
12759      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
12760      * </p>
12761      *
12762      * @param insets Insets to apply
12763      * @return The provided insets minus the insets that were consumed
12764      */
12765     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
12766         try {
12767             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
12768             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
12769                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
12770             } else {
12771                 return onApplyWindowInsets(insets);
12772             }
12773         } finally {
12774             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
12775         }
12776     }
12777 
12778     /**
12779      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
12780      * cause insets.
12781      * <p>
12782      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
12783      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
12784      * this view.
12785      * </p>
12786      * @param callback The callback to set.
12787      */
12788     public void setWindowInsetsAnimationCallback(
12789             @Nullable WindowInsetsAnimation.Callback callback) {
12790         getListenerInfo().mWindowInsetsAnimationCallback = callback;
12791     }
12792 
12793     /**
12794      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
12795      *         or view tree of the sub-hierarchy {@code false} otherwise.
12796      * @hide
12797      */
12798     public boolean hasWindowInsetsAnimationCallback() {
12799         return getListenerInfo().mWindowInsetsAnimationCallback != null;
12800     }
12801 
12802     /**
12803      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
12804      * when Window Insets animation is being prepared.
12805      * @param animation current animation
12806      *
12807      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
12808      */
12809     public void dispatchWindowInsetsAnimationPrepare(
12810             @NonNull WindowInsetsAnimation animation) {
12811         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12812             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
12813         }
12814     }
12815 
12816     /**
12817      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
12818      * when Window Insets animation is started.
12819      * @param animation current animation
12820      * @param bounds the upper and lower {@link Bounds} that provides range of
12821      *  {@link WindowInsetsAnimation}.
12822      * @return the upper and lower {@link Bounds}.
12823      */
12824     @NonNull
12825     public Bounds dispatchWindowInsetsAnimationStart(
12826             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
12827         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12828             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
12829         }
12830         return bounds;
12831     }
12832 
12833     /**
12834      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
12835      * when Window Insets animation makes progress.
12836      * @param insets The current {@link WindowInsets}.
12837      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
12838      * @return current {@link WindowInsets}.
12839      */
12840     @NonNull
12841     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
12842             @NonNull List<WindowInsetsAnimation> runningAnimations) {
12843         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12844             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
12845                     runningAnimations);
12846         } else {
12847             return insets;
12848         }
12849     }
12850 
12851     /**
12852      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
12853      * when Window Insets animation ends.
12854      * @param animation The current ongoing {@link WindowInsetsAnimation}.
12855      */
12856     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
12857         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12858             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
12859         }
12860     }
12861 
12862     /**
12863      * Sets a list of areas within this view's post-layout coordinate space where the system
12864      * should not intercept touch or other pointing device gestures. <em>This method should
12865      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
12866      *
12867      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
12868      * input in order to function correctly in the presence of global system gestures that may
12869      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
12870      * to provide system-level navigation functionality, a view such as a navigation drawer
12871      * container can mark the left (or starting) edge of itself as requiring gesture capture
12872      * priority using this API. The system may then choose to relax its own gesture recognition
12873      * to allow the app to consume the user's gesture. It is not necessary for an app to register
12874      * exclusion rects for broadly spanning regions such as the entirety of a
12875      * <code>ScrollView</code> or for simple press and release click targets such as
12876      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
12877      * a precision touch gesture in a small area in either the X or Y dimension, such as
12878      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
12879      *
12880      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
12881      * exclusions it takes into account. The limit does not apply while the navigation
12882      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
12883      * {@link android.inputmethodservice.InputMethodService input method} and
12884      * {@link Intent#CATEGORY_HOME home activity}.
12885      * </p>
12886      *
12887      * @param rects A list of precision gesture regions that this view needs to function correctly
12888      */
12889     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
12890         if (rects.isEmpty() && mListenerInfo == null) return;
12891 
12892         final ListenerInfo info = getListenerInfo();
12893         final boolean rectsChanged = !reduceChangedExclusionRectsMsgs()
12894                 || !Objects.deepEquals(info.mSystemGestureExclusionRects, rects);
12895         if (info.mSystemGestureExclusionRects == null) {
12896             info.mSystemGestureExclusionRects = new ArrayList<>();
12897         }
12898         if (rectsChanged) {
12899             deepCopyRectsObjectRecycling(info.mSystemGestureExclusionRects, rects);
12900             updatePositionUpdateListener();
12901             postUpdate(this::updateSystemGestureExclusionRects);
12902         }
12903     }
12904 
12905     private void deepCopyRectsObjectRecycling(@NonNull ArrayList<Rect> dest, List<Rect> src) {
12906         dest.ensureCapacity(src.size());
12907         for (int i = 0; i < src.size(); i++) {
12908             if (i < dest.size()) {
12909                 // Replace if there is an old rect to refresh
12910                 dest.get(i).set(src.get(i));
12911             } else {
12912                 // Add a rect if the list enlarged
12913                 dest.add(Rect.copyOrNull(src.get(i)));
12914             }
12915         }
12916         while (dest.size() > src.size()) {
12917             // Remove elements if the list shrank
12918             dest.removeLast();
12919         }
12920     }
12921 
12922     private void updatePositionUpdateListener() {
12923         final ListenerInfo info = getListenerInfo();
12924         if (getSystemGestureExclusionRects().isEmpty()
12925                 && collectPreferKeepClearRects().isEmpty()
12926                 && collectUnrestrictedPreferKeepClearRects().isEmpty()
12927                 && (info.mHandwritingArea == null || !shouldTrackHandwritingArea())) {
12928             if (info.mPositionUpdateListener != null) {
12929                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
12930                 info.mPositionUpdateListener = null;
12931                 info.mPositionChangedUpdate = null;
12932             }
12933         } else {
12934             if (info.mPositionUpdateListener == null) {
12935                 info.mPositionChangedUpdate = () -> {
12936                     updateSystemGestureExclusionRects();
12937                     updateKeepClearRects();
12938                     updateHandwritingArea();
12939                 };
12940                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
12941                     @Override
12942                     public void positionChanged(long n, int l, int t, int r, int b) {
12943                         postUpdate(info.mPositionChangedUpdate);
12944                     }
12945 
12946                     @Override
12947                     public void positionLost(long frameNumber) {
12948                         postUpdate(info.mPositionChangedUpdate);
12949                     }
12950                 };
12951                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
12952             }
12953         }
12954     }
12955 
12956     /**
12957      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
12958      */
12959     private void postUpdate(Runnable r) {
12960         // Potentially racey from a background thread. It's ok if it's not perfect.
12961         final Handler h = getHandler();
12962         if (h != null) {
12963             h.postAtFrontOfQueue(r);
12964         }
12965     }
12966 
12967     void updateSystemGestureExclusionRects() {
12968         final AttachInfo ai = mAttachInfo;
12969         if (ai != null) {
12970             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
12971         }
12972     }
12973 
12974     /**
12975      * Retrieve the list of areas within this view's post-layout coordinate space where the system
12976      * should not intercept touch or other pointing device gestures.
12977      *
12978      * <p>Do not modify the returned list.</p>
12979      *
12980      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
12981      */
12982     @NonNull
12983     public List<Rect> getSystemGestureExclusionRects() {
12984         final ListenerInfo info = mListenerInfo;
12985         if (info != null) {
12986             final List<Rect> list = info.mSystemGestureExclusionRects;
12987             if (list != null) {
12988                 return list;
12989             }
12990         }
12991         return Collections.emptyList();
12992     }
12993 
12994     /**
12995      * Set a preference to keep the bounds of this view clear from floating windows above this
12996      * view's window. This informs the system that the view is considered a vital area for the
12997      * user and that ideally it should not be covered. Setting this is only appropriate for UI
12998      * where the user would likely take action to uncover it.
12999      * <p>
13000      * The system will try to respect this preference, but when not possible will ignore it.
13001      * <p>
13002      * Note: This is independent from {@link #setPreferKeepClearRects}. If both are set, both will
13003      * be taken into account.
13004      * <p>
13005      * @see #setPreferKeepClearRects
13006      * @see #isPreferKeepClear
13007      * @attr ref android.R.styleable#View_preferKeepClear
13008      */
13009     public final void setPreferKeepClear(boolean preferKeepClear) {
13010         getListenerInfo().mPreferKeepClear = preferKeepClear;
13011         updatePositionUpdateListener();
13012         postUpdate(this::updateKeepClearRects);
13013     }
13014 
13015     /**
13016      * Retrieve the preference for this view to be kept clear. This is set either by
13017      * {@link #setPreferKeepClear} or via the attribute android.R.styleable#View_preferKeepClear.
13018      * <p>
13019      * If this is {@code true}, the system will ignore the Rects set by
13020      * {@link #setPreferKeepClearRects} and try to keep the whole view clear.
13021      * <p>
13022      * @see #setPreferKeepClear
13023      * @attr ref android.R.styleable#View_preferKeepClear
13024      */
13025     public final boolean isPreferKeepClear() {
13026         return mListenerInfo != null && mListenerInfo.mPreferKeepClear;
13027     }
13028 
13029     /**
13030      * Set a preference to keep the provided rects clear from floating windows above this
13031      * view's window. This informs the system that these rects are considered vital areas for the
13032      * user and that ideally they should not be covered. Setting this is only appropriate for UI
13033      * where the user would likely take action to uncover it.
13034      * <p>
13035      * The system will try to respect this preference, but when not possible will ignore it.
13036      * <p>
13037      * Note: This is independent from {@link #setPreferKeepClear}. If both are set, both will be
13038      * taken into account.
13039      * <p>
13040      * @see #setPreferKeepClear
13041      * @see #getPreferKeepClearRects
13042      *
13043      * @param rects A list of rects in this view's local coordinate system
13044      */
13045     public final void setPreferKeepClearRects(@NonNull List<Rect> rects) {
13046         final ListenerInfo info = getListenerInfo();
13047         final boolean rectsChanged = !reduceChangedExclusionRectsMsgs()
13048                 || !Objects.deepEquals(info.mKeepClearRects, rects);
13049         if (info.mKeepClearRects == null) {
13050             info.mKeepClearRects = new ArrayList<>();
13051         }
13052         if (rectsChanged) {
13053             deepCopyRectsObjectRecycling(info.mKeepClearRects, rects);
13054             updatePositionUpdateListener();
13055             postUpdate(this::updateKeepClearRects);
13056         }
13057     }
13058 
13059     /**
13060      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
13061      *
13062      * @see #setPreferKeepClearRects
13063      */
13064     @NonNull
13065     public final List<Rect> getPreferKeepClearRects() {
13066         final ListenerInfo info = mListenerInfo;
13067         if (info != null && info.mKeepClearRects != null) {
13068             return new ArrayList(info.mKeepClearRects);
13069         }
13070 
13071         return Collections.emptyList();
13072     }
13073 
13074     /**
13075      * Set a preference to keep the provided rects clear from floating windows above this
13076      * view's window. This informs the system that these rects are considered vital areas for the
13077      * user and that ideally they should not be covered. Setting this is only appropriate for UI
13078      * where the user would likely take action to uncover it.
13079      * <p>
13080      * Note: The difference with {@link #setPreferKeepClearRects} is that the system won't apply
13081      * restrictions to the rects set here.
13082      * <p>
13083      * @see #setPreferKeepClear
13084      * @see #getPreferKeepClearRects
13085      *
13086      * @param rects A list of rects in this view's local coordinate system
13087      *
13088      * @hide
13089      */
13090     @SystemApi
13091     @RequiresPermission(android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS)
13092     public final void setUnrestrictedPreferKeepClearRects(@NonNull List<Rect> rects) {
13093         final ListenerInfo info = getListenerInfo();
13094         final boolean rectsChanged = !reduceChangedExclusionRectsMsgs()
13095                 || !Objects.deepEquals(info.mUnrestrictedKeepClearRects, rects);
13096         if (info.mUnrestrictedKeepClearRects == null) {
13097             info.mUnrestrictedKeepClearRects = new ArrayList<>();
13098         }
13099         if (rectsChanged) {
13100             deepCopyRectsObjectRecycling(info.mUnrestrictedKeepClearRects, rects);
13101             updatePositionUpdateListener();
13102             postUpdate(this::updateKeepClearRects);
13103         }
13104     }
13105 
13106     /**
13107      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
13108      *
13109      * @see #setPreferKeepClearRects
13110      *
13111      * @hide
13112      */
13113     @SystemApi
13114     @NonNull
13115     public final List<Rect> getUnrestrictedPreferKeepClearRects() {
13116         final ListenerInfo info = mListenerInfo;
13117         if (info != null && info.mUnrestrictedKeepClearRects != null) {
13118             return new ArrayList(info.mUnrestrictedKeepClearRects);
13119         }
13120 
13121         return Collections.emptyList();
13122     }
13123 
13124     void updateKeepClearRects() {
13125         final AttachInfo ai = mAttachInfo;
13126         if (ai != null) {
13127             ai.mViewRootImpl.updateKeepClearRectsForView(this);
13128         }
13129     }
13130 
13131     /**
13132      * Retrieve the list of areas within this view's post-layout coordinate space which the
13133      * system will try to not cover with other floating elements, like the pip window.
13134      */
13135     @NonNull
13136     List<Rect> collectPreferKeepClearRects() {
13137         ListenerInfo info = mListenerInfo;
13138         boolean keepClearForFocus = isFocused()
13139                 && ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled();
13140         boolean keepBoundsClear = (info != null && info.mPreferKeepClear) || keepClearForFocus;
13141         boolean hasCustomKeepClearRects = info != null && info.mKeepClearRects != null;
13142 
13143         if (!keepBoundsClear && !hasCustomKeepClearRects) {
13144             return Collections.emptyList();
13145         } else if (keepBoundsClear && !hasCustomKeepClearRects) {
13146             return Collections.singletonList(new Rect(0, 0, getWidth(), getHeight()));
13147         }
13148 
13149         final List<Rect> list = new ArrayList<>();
13150         if (keepBoundsClear) {
13151             list.add(new Rect(0, 0, getWidth(), getHeight()));
13152         }
13153 
13154         if (hasCustomKeepClearRects) {
13155             list.addAll(info.mKeepClearRects);
13156         }
13157 
13158         return list;
13159     }
13160 
13161     private void updatePreferKeepClearForFocus() {
13162         if (ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled()) {
13163             updatePositionUpdateListener();
13164             post(this::updateKeepClearRects);
13165         }
13166     }
13167 
13168     /**
13169      * Retrieve the list of unrestricted areas within this view's post-layout coordinate space
13170      * which the system will try to not cover with other floating elements, like the pip window.
13171      */
13172     @NonNull
13173     List<Rect> collectUnrestrictedPreferKeepClearRects() {
13174         final ListenerInfo info = mListenerInfo;
13175         if (info != null && info.mUnrestrictedKeepClearRects != null) {
13176             return info.mUnrestrictedKeepClearRects;
13177         }
13178 
13179         return Collections.emptyList();
13180     }
13181 
13182     /**
13183      * Set the amount of offset applied to this view's stylus handwriting bounds. A positive offset
13184      * will offset the edge outwards.The base handwriting bounds of a view is its visible bounds.
13185      * The handwriting bounds offsets are applied to the base handwriting bounds to determine the
13186      * final handwriting bounds.
13187      * <p> This method is mainly used to enlarge the view's handwriting bounds for a better user
13188      * experience.
13189      * <p> Note that when the view is clipped (e.g. the view is in a
13190      * {@link android.widget.ScrollView}), the offsets are applied after the view's handwriting
13191      * bounds is clipped.
13192      *
13193      * @param offsetLeft the amount of pixel offset applied to the left edge outwards of the view's
13194      *                   handwriting bounds.
13195      * @param offsetTop the amount of pixel offset applied to the top edge outwards of the view's
13196      *                  handwriting bounds.
13197      * @param offsetRight the amount of pixel offset applied to the right edge outwards of the
13198      *                    view's handwriting bounds.
13199      * @param offsetBottom the amount of pixel offset applied to the bottom edge outwards of the
13200      *                     view's handwriting bounds.
13201      *
13202      * @see #setAutoHandwritingEnabled(boolean)
13203      * @see #getHandwritingBoundsOffsetLeft()
13204      * @see #getHandwritingBoundsOffsetTop()
13205      * @see #getHandwritingBoundsOffsetRight()
13206      * @see #getHandwritingBoundsOffsetBottom()
13207      */
13208     public void setHandwritingBoundsOffsets(float offsetLeft, float offsetTop,
13209             float offsetRight, float offsetBottom) {
13210         mHandwritingBoundsOffsetLeft = offsetLeft;
13211         mHandwritingBoundsOffsetTop = offsetTop;
13212         mHandwritingBoundsOffsetRight = offsetRight;
13213         mHandwritingBoundsOffsetBottom = offsetBottom;
13214     }
13215 
13216     /**
13217      * Return the amount of offset applied to the left edge of this view's handwriting bounds,
13218      * in the unit of pixel.
13219      *
13220      * @see #setAutoHandwritingEnabled(boolean)
13221      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13222      */
13223     public float getHandwritingBoundsOffsetLeft() {
13224         return mHandwritingBoundsOffsetLeft;
13225     }
13226 
13227     /**
13228      * Return the amount of offset applied to the top edge of this view's handwriting bounds,
13229      * in the unit of pixel.
13230      *
13231      * @see #setAutoHandwritingEnabled(boolean)
13232      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13233      */
13234     public float getHandwritingBoundsOffsetTop() {
13235         return mHandwritingBoundsOffsetTop;
13236     }
13237 
13238     /**
13239      * Return the amount of offset applied to the right edge of this view's handwriting bounds, in
13240      * the unit of pixel.
13241      *
13242      * @see #setAutoHandwritingEnabled(boolean)
13243      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13244      */
13245     public float getHandwritingBoundsOffsetRight() {
13246         return mHandwritingBoundsOffsetRight;
13247     }
13248 
13249     /**
13250      * Return the amount of offset applied to the bottom edge of this view's handwriting bounds, in
13251      * the unit of pixel.
13252      *
13253      * @see #setAutoHandwritingEnabled(boolean)
13254      * @see #setHandwritingBoundsOffsets(float, float, float, float)
13255      */
13256     public float getHandwritingBoundsOffsetBottom() {
13257         return mHandwritingBoundsOffsetBottom;
13258     }
13259 
13260 
13261     /**
13262      * Set a handwriting area in this view. If there is any stylus {@link MotionEvent}
13263      * occurs within this area, it will trigger stylus handwriting mode. This can be disabled by
13264      * disabling the auto handwriting initiation by calling
13265      * {@link #setAutoHandwritingEnabled(boolean)} with false.
13266      *
13267      * @attr rect the handwriting area in the view's local coordiniates.
13268      *
13269      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
13270      * @see #setAutoHandwritingEnabled(boolean)
13271      *
13272      * @hide
13273      */
13274     public void setHandwritingArea(@Nullable Rect rect) {
13275         final ListenerInfo info = getListenerInfo();
13276         info.mHandwritingArea = rect;
13277         updatePositionUpdateListener();
13278         postUpdate(this::updateHandwritingArea);
13279     }
13280 
13281     /**
13282      * Return the handwriting areas set on this view, in its local coordinates.
13283      * @see #setHandwritingArea(Rect)
13284      *
13285      * @hide
13286      */
13287     @Nullable
13288     public Rect getHandwritingArea() {
13289         final ListenerInfo info = mListenerInfo;
13290         if (info != null && info.mHandwritingArea != null) {
13291             return new Rect(info.mHandwritingArea);
13292         }
13293         return null;
13294     }
13295 
13296     void updateHandwritingArea() {
13297         // If autoHandwritingArea is not enabled, do nothing.
13298         if (!shouldTrackHandwritingArea()) return;
13299         final AttachInfo ai = mAttachInfo;
13300         if (ai != null) {
13301             ai.mViewRootImpl.getHandwritingInitiator().updateHandwritingAreasForView(this);
13302         }
13303     }
13304 
13305     /**
13306      * Returns true if a stylus {@link MotionEvent} within this view's bounds should initiate
13307      * handwriting mode, either for this view ({@link #isAutoHandwritingEnabled()} is {@code true})
13308      * or for a handwriting delegate view ({@link #getHandwritingDelegatorCallback()} is not {@code
13309      * null}).
13310      */
13311     boolean shouldInitiateHandwriting() {
13312         return isAutoHandwritingEnabled() || getHandwritingDelegatorCallback() != null;
13313     }
13314 
13315     /**
13316      * Returns whether the handwriting initiator should track the handwriting area for this view,
13317      * either to initiate handwriting mode, or to prepare handwriting delegation, or to show the
13318      * handwriting unsupported message.
13319      * @hide
13320      */
13321     public boolean shouldTrackHandwritingArea() {
13322         return shouldInitiateHandwriting();
13323     }
13324 
13325     /**
13326      * Sets a callback which should be called when a stylus {@link MotionEvent} occurs within this
13327      * view's bounds. The callback will be called from the UI thread.
13328      *
13329      * <p>Setting a callback allows this view to act as a handwriting delegator, so that handwriting
13330      * mode for a delegate editor view can be initiated by stylus movement on this delegator view.
13331      * The callback implementation is expected to show and focus the delegate editor view. If a view
13332      * which returns {@code true} for {@link #isHandwritingDelegate()} creates an input connection
13333      * while the same stylus {@link MotionEvent} sequence is ongoing, handwriting mode will be
13334      * initiated for that view.
13335      *
13336      * <p>A common use case is a custom view which looks like a text editor but does not actually
13337      * support text editing itself, and clicking on the custom view causes an EditText to be shown.
13338      * To support handwriting initiation in this case, this method can be called on the custom view
13339      * to configure it as a delegator. The EditText should call {@link #setIsHandwritingDelegate} to
13340      * set it as a delegate. The {@code callback} implementation is typically the same as the click
13341      * listener implementation which shows the EditText.
13342      *
13343      * <p>If {@code null} is passed, this view will no longer act as a handwriting initiation
13344      * delegator.
13345      *
13346      * @param callback a callback which should be called when a stylus {@link MotionEvent} occurs
13347      *     within this view's bounds
13348      */
13349     public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
13350         mHandwritingDelegatorCallback = callback;
13351         if (callback != null) {
13352             setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
13353         }
13354     }
13355 
13356     /**
13357      * Returns the callback set by {@link #setHandwritingDelegatorCallback} which should be called
13358      * when a stylus {@link MotionEvent} occurs within this view's bounds. The callback should only
13359      * be called from the UI thread.
13360      */
13361     @Nullable
13362     public Runnable getHandwritingDelegatorCallback() {
13363         return mHandwritingDelegatorCallback;
13364     }
13365 
13366     /**
13367      * Specifies that this view may act as a handwriting initiation delegator for a delegate editor
13368      * view from the specified package. If this method is not called, delegators may only be used to
13369      * initiate handwriting mode for a delegate editor view from the same package as the delegator
13370      * view. This method allows specifying a different trusted package which may contain a delegate
13371      * editor view linked to this delegator view.
13372      *
13373      * <p>This method has no effect unless {@link #setHandwritingDelegatorCallback} is also called
13374      * to configure this view to act as a handwriting delegator.
13375      *
13376      * <p>If this method is called on the delegator view, then {@link
13377      * #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
13378      *
13379      * <p>For example, to configure a delegator view in package 1:
13380      *
13381      * <pre>
13382      * delegatorView.setHandwritingDelegatorCallback(callback);
13383      * delegatorView.setAllowedHandwritingDelegatePackage(package2);</pre>
13384      *
13385      * Then to configure the corresponding delegate editor view in package 2:
13386      *
13387      * <pre>
13388      * delegateEditorView.setIsHandwritingDelegate(true);
13389      * delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
13390      *
13391      * @param allowedPackageName the package name of a delegate editor view linked to this delegator
13392      *     view, or {@code null} to restore the default behavior of only allowing delegate editor
13393      *     views from the same package as this delegator view
13394      */
13395     public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
13396         mAllowedHandwritingDelegatePackageName = allowedPackageName;
13397     }
13398 
13399     /**
13400      * Returns the allowed package for delegate editor views for which this view may act as a
13401      * handwriting delegator, as set by {@link #setAllowedHandwritingDelegatePackage}. If {@link
13402      * #setAllowedHandwritingDelegatePackage} has not been called, or called with {@code null}
13403      * argument, this will return {@code null}, meaning that this delegator view may only be used to
13404      * initiate handwriting mode for a delegate editor view from the same package as this delegator
13405      * view.
13406      */
13407     @Nullable
13408     public String getAllowedHandwritingDelegatePackageName() {
13409         return mAllowedHandwritingDelegatePackageName;
13410     }
13411 
13412     /**
13413      * Sets this view to be a handwriting delegate. If a delegate view creates an input connection
13414      * while a stylus {@link MotionEvent} sequence from a delegator view is ongoing, handwriting
13415      * mode will be initiated for the delegate view.
13416      *
13417      * @param isHandwritingDelegate whether this view is a handwriting initiation delegate
13418      * @see #setHandwritingDelegatorCallback(Runnable)
13419      */
13420     public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
13421         mIsHandwritingDelegate = isHandwritingDelegate;
13422     }
13423 
13424     /**
13425      * Returns whether this view has been set as a handwriting delegate by {@link
13426      * #setIsHandwritingDelegate}.
13427      */
13428     public boolean isHandwritingDelegate() {
13429         return mIsHandwritingDelegate;
13430     }
13431 
13432     /**
13433      * Specifies that a view from the specified package may act as a handwriting delegator for this
13434      * delegate editor view. If this method is not called, only views from the same package as this
13435      * delegate editor view may act as a handwriting delegator. This method allows specifying a
13436      * different trusted package which may contain a delegator view linked to this delegate editor
13437      * view.
13438      *
13439      * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
13440      * configure this view to act as a handwriting delegate.
13441      *
13442      * <p>If this method is called on the delegate editor view, then {@link
13443      * #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
13444      *
13445      * @param allowedPackageName the package name of a delegator view linked to this delegate editor
13446      *     view, or {@code null} to restore the default behavior of only allowing delegator views
13447      *     from the same package as this delegate editor view
13448      */
13449     public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
13450         mAllowedHandwritingDelegatorPackageName = allowedPackageName;
13451     }
13452 
13453     /**
13454      * Returns the allowed package for views which may act as a handwriting delegator for this
13455      * delegate editor view, as set by {@link #setAllowedHandwritingDelegatorPackage}. If {@link
13456      * #setAllowedHandwritingDelegatorPackage} has not been called, or called with {@code null}
13457      * argument, this will return {@code null}, meaning that only views from the same package as
13458      * this delegator editor view may act as a handwriting delegator.
13459      */
13460     @Nullable
13461     public String getAllowedHandwritingDelegatorPackageName() {
13462         return mAllowedHandwritingDelegatorPackageName;
13463     }
13464 
13465     /**
13466      * Sets flags configuring the handwriting delegation behavior for this delegate editor view.
13467      *
13468      * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
13469      * configure this view to act as a handwriting delegate.
13470      *
13471      * @param flags {@link InputMethodManager#HANDWRITING_DELEGATE_FLAG_HOME_DELEGATOR_ALLOWED} or
13472      *     {@code 0}
13473      */
13474     @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR)
13475     public void setHandwritingDelegateFlags(
13476             @InputMethodManager.HandwritingDelegateFlags int flags) {
13477         mHandwritingDelegateFlags = flags;
13478     }
13479 
13480     /**
13481      * Returns flags configuring the handwriting delegation behavior for this delegate editor view,
13482      * as set by {@link #setHandwritingDelegateFlags}.
13483      */
13484     @FlaggedApi(FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR)
13485     public @InputMethodManager.HandwritingDelegateFlags int getHandwritingDelegateFlags() {
13486         return mHandwritingDelegateFlags;
13487     }
13488 
13489     /**
13490      * Gets the coordinates of this view in the coordinate space of the
13491      * {@link Surface} that contains the view.
13492      *
13493      * <p>In multiple-screen scenarios, if the surface spans multiple screens,
13494      * the coordinate space of the surface also spans multiple screens.
13495      *
13496      * <p>After the method returns, the argument array contains the x and y
13497      * coordinates of the view relative to the view's left and top edges,
13498      * respectively.
13499      *
13500      * @param location A two-element integer array in which the view coordinates
13501      *      are stored. The x-coordinate is at index 0; the y-coordinate, at
13502      *      index 1.
13503      */
13504     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
13505         getLocationInWindow(location);
13506         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
13507             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
13508             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
13509         }
13510     }
13511 
13512     /**
13513      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
13514      * only available if the view is attached.
13515      *
13516      * @return WindowInsets from the top of the view hierarchy or null if View is detached
13517      */
13518     public WindowInsets getRootWindowInsets() {
13519         if (mAttachInfo != null) {
13520             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
13521         }
13522         return null;
13523     }
13524 
13525     /**
13526      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
13527      *
13528      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
13529      *         a window nor a view tree with a decor.
13530      * @see Window#getInsetsController()
13531      */
13532     public @Nullable WindowInsetsController getWindowInsetsController() {
13533         if (mAttachInfo != null) {
13534             return mAttachInfo.mViewRootImpl.getInsetsController();
13535         }
13536         ViewParent parent = getParent();
13537         if (parent instanceof View) {
13538             return ((View) parent).getWindowInsetsController();
13539         } else if (parent instanceof ViewRootImpl) {
13540             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
13541             return ((ViewRootImpl) parent).getInsetsController();
13542         }
13543         return null;
13544     }
13545 
13546 
13547     /**
13548      * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}.
13549      *
13550      * @return The {@link OnBackInvokedDispatcher} from this or the nearest
13551      * ancestor, or null if this view is both not attached and have no ancestor providing an
13552      * {@link OnBackInvokedDispatcher}.
13553      */
13554     @Nullable
13555     public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() {
13556         ViewParent parent = getParent();
13557         if (parent != null) {
13558             return parent.findOnBackInvokedDispatcherForChild(this, this);
13559         }
13560         return null;
13561     }
13562 
13563     /**
13564      * @hide Compute the insets that should be consumed by this view and the ones
13565      * that should propagate to those under it.
13566      *
13567      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
13568      *
13569      * @param inoutInsets the insets given to this view
13570      * @param outLocalInsets the insets that should be applied to this view
13571      * @deprecated use {@link #computeSystemWindowInsets}
13572      * @return
13573      */
13574     @Deprecated
13575     @UnsupportedAppUsage
13576     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
13577         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
13578                 outLocalInsets);
13579         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
13580         return innerInsets.isSystemWindowInsetsConsumed();
13581     }
13582 
13583     /**
13584      * Compute insets that should be consumed by this view and the ones that should propagate
13585      * to those under it.
13586      *
13587      * @param in Insets currently being processed by this View, likely received as a parameter
13588      *           to {@link #onApplyWindowInsets(WindowInsets)}.
13589      * @param outLocalInsets A Rect that will receive the insets that should be consumed
13590      *                       by this view
13591      * @return Insets that should be passed along to views under this one
13592      */
13593     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
13594         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
13595                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
13596         if (isOptionalFitSystemWindows && mAttachInfo != null) {
13597             OnContentApplyWindowInsetsListener listener =
13598                     mAttachInfo.mContentOnApplyWindowInsetsListener;
13599             if (listener == null) {
13600                 // The application wants to take care of fitting system window for
13601                 // the content.
13602                 outLocalInsets.setEmpty();
13603                 return in;
13604             }
13605             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
13606             outLocalInsets.set(result.first.toRect());
13607             return result.second;
13608         } else {
13609             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
13610             return in.consumeSystemWindowInsets().inset(outLocalInsets);
13611         }
13612     }
13613 
13614     /**
13615      * @return True if the window has the {@link OnContentApplyWindowInsetsListener}, and this means
13616      *         the framework will apply window insets on the content of the window.
13617      * @hide
13618      */
13619     protected boolean hasContentOnApplyWindowInsetsListener() {
13620         return mAttachInfo != null && mAttachInfo.mContentOnApplyWindowInsetsListener != null;
13621     }
13622 
13623     /**
13624      * Sets whether or not this view should account for system screen decorations
13625      * such as the status bar and inset its content; that is, controlling whether
13626      * the default implementation of {@link #fitSystemWindows(Rect)} will be
13627      * executed.  See that method for more details.
13628      *
13629      * <p>Note that if you are providing your own implementation of
13630      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
13631      * flag to true -- your implementation will be overriding the default
13632      * implementation that checks this flag.
13633      *
13634      * @param fitSystemWindows If true, then the default implementation of
13635      * {@link #fitSystemWindows(Rect)} will be executed.
13636      *
13637      * @attr ref android.R.styleable#View_fitsSystemWindows
13638      * @see #getFitsSystemWindows()
13639      * @see #fitSystemWindows(Rect)
13640      * @see #setSystemUiVisibility(int)
13641      */
13642     public void setFitsSystemWindows(boolean fitSystemWindows) {
13643         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
13644     }
13645 
13646     /**
13647      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
13648      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
13649      * will be executed.
13650      *
13651      * @return {@code true} if the default implementation of
13652      * {@link #fitSystemWindows(Rect)} will be executed.
13653      *
13654      * @attr ref android.R.styleable#View_fitsSystemWindows
13655      * @see #setFitsSystemWindows(boolean)
13656      * @see #fitSystemWindows(Rect)
13657      * @see #setSystemUiVisibility(int)
13658      */
13659     @ViewDebug.ExportedProperty
13660     @InspectableProperty
13661     public boolean getFitsSystemWindows() {
13662         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
13663     }
13664 
13665     /** @hide */
13666     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
13667     public boolean fitsSystemWindows() {
13668         return getFitsSystemWindows();
13669     }
13670 
13671     /**
13672      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
13673      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
13674      */
13675     @Deprecated
13676     public void requestFitSystemWindows() {
13677         if (mParent != null) {
13678             mParent.requestFitSystemWindows();
13679         }
13680     }
13681 
13682     /**
13683      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
13684      */
13685     public void requestApplyInsets() {
13686         requestFitSystemWindows();
13687     }
13688 
13689     /**
13690      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
13691      * @hide
13692      */
13693     @UnsupportedAppUsage
13694     public void makeOptionalFitsSystemWindows() {
13695         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
13696     }
13697 
13698     /**
13699      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
13700      * @hide
13701      */
13702     public void makeFrameworkOptionalFitsSystemWindows() {
13703         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
13704     }
13705 
13706     /**
13707      * @hide
13708      */
13709     public boolean isFrameworkOptionalFitsSystemWindows() {
13710         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
13711     }
13712 
13713     /**
13714      * Returns the visibility status for this view.
13715      *
13716      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
13717      * @attr ref android.R.styleable#View_visibility
13718      */
13719     @ViewDebug.ExportedProperty(mapping = {
13720         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
13721         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
13722         @ViewDebug.IntToString(from = GONE,      to = "GONE")
13723     })
13724     @InspectableProperty(enumMapping = {
13725             @EnumEntry(value = VISIBLE, name = "visible"),
13726             @EnumEntry(value = INVISIBLE, name = "invisible"),
13727             @EnumEntry(value = GONE, name = "gone")
13728     })
13729     @Visibility
13730     public int getVisibility() {
13731         return mViewFlags & VISIBILITY_MASK;
13732     }
13733 
13734     /**
13735      * Set the visibility state of this view.
13736      *
13737      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
13738      * @attr ref android.R.styleable#View_visibility
13739      */
13740     @RemotableViewMethod
13741     public void setVisibility(@Visibility int visibility) {
13742         setFlags(visibility, VISIBILITY_MASK);
13743     }
13744 
13745     /**
13746      * Returns the enabled status for this view. The interpretation of the
13747      * enabled state varies by subclass.
13748      *
13749      * @return True if this view is enabled, false otherwise.
13750      */
13751     @ViewDebug.ExportedProperty
13752     @InspectableProperty
13753     public boolean isEnabled() {
13754         return (mViewFlags & ENABLED_MASK) == ENABLED;
13755     }
13756 
13757     /**
13758      * Set the enabled state of this view. The interpretation of the enabled
13759      * state varies by subclass.
13760      *
13761      * @param enabled True if this view is enabled, false otherwise.
13762      */
13763     @RemotableViewMethod
13764     public void setEnabled(boolean enabled) {
13765         if (enabled == isEnabled()) return;
13766 
13767         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
13768 
13769         /*
13770          * The View most likely has to change its appearance, so refresh
13771          * the drawable state.
13772          */
13773         refreshDrawableState();
13774 
13775         // Invalidate too, since the default behavior for views is to be
13776         // be drawn at 50% alpha rather than to change the drawable.
13777         invalidate(true);
13778 
13779         if (!enabled) {
13780             cancelPendingInputEvents();
13781         }
13782         notifyViewAccessibilityStateChangedIfNeeded(
13783                 AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED);
13784     }
13785 
13786     /**
13787      * Set whether this view can receive the focus.
13788      * <p>
13789      * Setting this to false will also ensure that this view is not focusable
13790      * in touch mode.
13791      *
13792      * @param focusable If true, this view can receive the focus.
13793      *
13794      * @see #setFocusableInTouchMode(boolean)
13795      * @see #setFocusable(int)
13796      * @attr ref android.R.styleable#View_focusable
13797      */
13798     @RemotableViewMethod
13799     public void setFocusable(boolean focusable) {
13800         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
13801     }
13802 
13803     /**
13804      * Sets whether this view can receive focus.
13805      * <p>
13806      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
13807      * automatically based on the view's interactivity. This is the default.
13808      * <p>
13809      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
13810      * in touch mode.
13811      *
13812      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
13813      *                  or {@link #FOCUSABLE_AUTO}.
13814      * @see #setFocusableInTouchMode(boolean)
13815      * @attr ref android.R.styleable#View_focusable
13816      */
13817     @RemotableViewMethod
13818     public void setFocusable(@Focusable int focusable) {
13819         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
13820             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
13821         }
13822         setFlags(focusable, FOCUSABLE_MASK);
13823     }
13824 
13825     /**
13826      * Set whether this view can receive focus while in touch mode.
13827      *
13828      * Setting this to true will also ensure that this view is focusable.
13829      *
13830      * @param focusableInTouchMode If true, this view can receive the focus while
13831      *   in touch mode.
13832      *
13833      * @see #setFocusable(boolean)
13834      * @attr ref android.R.styleable#View_focusableInTouchMode
13835      */
13836     @RemotableViewMethod
13837     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
13838         // Focusable in touch mode should always be set before the focusable flag
13839         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
13840         // which, in touch mode, will not successfully request focus on this view
13841         // because the focusable in touch mode flag is not set
13842         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
13843 
13844         // Clear FOCUSABLE_AUTO if set.
13845         if (focusableInTouchMode) {
13846             // Clears FOCUSABLE_AUTO if set.
13847             setFlags(FOCUSABLE, FOCUSABLE_MASK);
13848         }
13849     }
13850 
13851     /**
13852      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
13853      * to autofill the view with the user's data.
13854      *
13855      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
13856      * For example, if the application accepts either an username or email address to identify
13857      * an user.
13858      *
13859      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
13860      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
13861      * constants such as:
13862      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
13863      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
13864      * {@link #AUTOFILL_HINT_NAME},
13865      * {@link #AUTOFILL_HINT_PHONE},
13866      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
13867      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
13868      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
13869      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
13870      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
13871      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
13872      *
13873      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
13874      * @attr ref android.R.styleable#View_autofillHints
13875      */
13876     public void setAutofillHints(@Nullable String... autofillHints) {
13877         if (autofillHints == null || autofillHints.length == 0) {
13878             mAutofillHints = null;
13879         } else {
13880             mAutofillHints = autofillHints;
13881         }
13882         if (sensitiveContentAppProtection()) {
13883             if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) {
13884                 updateSensitiveViewsCountIfNeeded(isAggregatedVisible());
13885             }
13886         }
13887     }
13888 
13889     /**
13890      * @hide
13891      */
13892     @TestApi
13893     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
13894         boolean wasChanged = isAutofilled != isAutofilled();
13895 
13896         if (wasChanged) {
13897             if (isAutofilled) {
13898                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
13899             } else {
13900                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
13901             }
13902 
13903             if (hideHighlight) {
13904                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
13905             } else {
13906                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
13907             }
13908 
13909             invalidate();
13910         }
13911     }
13912 
13913     /**
13914      * Set whether this view should have sound effects enabled for events such as
13915      * clicking and touching.
13916      *
13917      * <p>You may wish to disable sound effects for a view if you already play sounds,
13918      * for instance, a dial key that plays dtmf tones.
13919      *
13920      * @param soundEffectsEnabled whether sound effects are enabled for this view.
13921      * @see #isSoundEffectsEnabled()
13922      * @see #playSoundEffect(int)
13923      * @attr ref android.R.styleable#View_soundEffectsEnabled
13924      */
13925     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
13926         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
13927     }
13928 
13929     /**
13930      * @return whether this view should have sound effects enabled for events such as
13931      *     clicking and touching.
13932      *
13933      * @see #setSoundEffectsEnabled(boolean)
13934      * @see #playSoundEffect(int)
13935      * @attr ref android.R.styleable#View_soundEffectsEnabled
13936      */
13937     @ViewDebug.ExportedProperty
13938     @InspectableProperty
13939     public boolean isSoundEffectsEnabled() {
13940         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
13941     }
13942 
13943     /**
13944      * Set whether this view should have haptic feedback for events such as
13945      * long presses.
13946      *
13947      * <p>You may wish to disable haptic feedback if your view already controls
13948      * its own haptic feedback.
13949      *
13950      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
13951      * @see #isHapticFeedbackEnabled()
13952      * @see #performHapticFeedback(int)
13953      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
13954      */
13955     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
13956         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
13957     }
13958 
13959     /**
13960      * @return whether this view should have haptic feedback enabled for events
13961      * such as long presses.
13962      *
13963      * @see #setHapticFeedbackEnabled(boolean)
13964      * @see #performHapticFeedback(int)
13965      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
13966      */
13967     @ViewDebug.ExportedProperty
13968     @InspectableProperty
13969     public boolean isHapticFeedbackEnabled() {
13970         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
13971     }
13972 
13973     /**
13974      * Returns the layout direction for this view.
13975      *
13976      * @return One of {@link #LAYOUT_DIRECTION_LTR},
13977      *   {@link #LAYOUT_DIRECTION_RTL},
13978      *   {@link #LAYOUT_DIRECTION_INHERIT} or
13979      *   {@link #LAYOUT_DIRECTION_LOCALE}.
13980      *
13981      * @attr ref android.R.styleable#View_layoutDirection
13982      *
13983      * @hide
13984      */
13985     @ViewDebug.ExportedProperty(category = "layout", mapping = {
13986         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
13987         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
13988         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
13989         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
13990     })
13991     @InspectableProperty(hasAttributeId = false, enumMapping = {
13992             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
13993             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
13994             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
13995             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
13996     })
13997     @LayoutDir
13998     public int getRawLayoutDirection() {
13999         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
14000     }
14001 
14002     /**
14003      * Set the layout direction for this view. This will propagate a reset of layout direction
14004      * resolution to the view's children and resolve layout direction for this view.
14005      *
14006      * @param layoutDirection the layout direction to set. Should be one of:
14007      *
14008      * {@link #LAYOUT_DIRECTION_LTR},
14009      * {@link #LAYOUT_DIRECTION_RTL},
14010      * {@link #LAYOUT_DIRECTION_INHERIT},
14011      * {@link #LAYOUT_DIRECTION_LOCALE}.
14012      *
14013      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
14014      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
14015      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
14016      *
14017      * @attr ref android.R.styleable#View_layoutDirection
14018      */
14019     @RemotableViewMethod
14020     public void setLayoutDirection(@LayoutDir int layoutDirection) {
14021         if (getRawLayoutDirection() != layoutDirection) {
14022             // Reset the current layout direction and the resolved one
14023             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
14024             resetRtlProperties();
14025             // Set the new layout direction (filtered)
14026             mPrivateFlags2 |=
14027                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
14028             // We need to resolve all RTL properties as they all depend on layout direction
14029             resolveRtlPropertiesIfNeeded();
14030             requestLayout();
14031             invalidate(true);
14032         }
14033     }
14034 
14035     /**
14036      * Returns the resolved layout direction for this view.
14037      *
14038      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
14039      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
14040      *
14041      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
14042      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
14043      *
14044      * @attr ref android.R.styleable#View_layoutDirection
14045      */
14046     @ViewDebug.ExportedProperty(category = "layout", mapping = {
14047         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
14048         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
14049     })
14050     @InspectableProperty(enumMapping = {
14051             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
14052             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
14053     })
14054     @ResolvedLayoutDir
14055     public int getLayoutDirection() {
14056         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
14057                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
14058     }
14059 
14060     /**
14061      * Indicates whether or not this view's layout is right-to-left. This is resolved from
14062      * layout attribute and/or the inherited value from the parent
14063      *
14064      * @return true if the layout is right-to-left.
14065      *
14066      * @hide
14067      */
14068     @ViewDebug.ExportedProperty(category = "layout")
14069     @UnsupportedAppUsage
14070     public boolean isLayoutRtl() {
14071         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
14072     }
14073 
14074     /**
14075      * Indicates whether the view is currently tracking transient state that the
14076      * app should not need to concern itself with saving and restoring, but that
14077      * the framework should take special note to preserve when possible.
14078      *
14079      * <p>A view with transient state cannot be trivially rebound from an external
14080      * data source, such as an adapter binding item views in a list. This may be
14081      * because the view is performing an animation, tracking user selection
14082      * of content, or similar.</p>
14083      *
14084      * @return true if the view has transient state
14085      */
14086     @ViewDebug.ExportedProperty(category = "layout")
14087     public boolean hasTransientState() {
14088         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
14089     }
14090 
14091     /**
14092      * Set whether this view is currently tracking transient state that the
14093      * framework should attempt to preserve when possible. This flag is reference counted,
14094      * so every call to setHasTransientState(true) should be paired with a later call
14095      * to setHasTransientState(false).
14096      *
14097      * <p>A view with transient state cannot be trivially rebound from an external
14098      * data source, such as an adapter binding item views in a list. This may be
14099      * because the view is performing an animation, tracking user selection
14100      * of content, or similar.</p>
14101      *
14102      * @param hasTransientState true if this view has transient state
14103      */
14104     public void setHasTransientState(boolean hasTransientState) {
14105         final boolean oldHasTransientState = hasTransientState();
14106         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
14107                 mTransientStateCount - 1;
14108         if (mTransientStateCount < 0) {
14109             mTransientStateCount = 0;
14110             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
14111                     "unmatched pair of setHasTransientState calls");
14112         } else if ((hasTransientState && mTransientStateCount == 1) ||
14113                 (!hasTransientState && mTransientStateCount == 0)) {
14114             // update flag if we've just incremented up from 0 or decremented down to 0
14115             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
14116                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
14117             final boolean newHasTransientState = hasTransientState();
14118             if (mParent != null && newHasTransientState != oldHasTransientState) {
14119                 try {
14120                     mParent.childHasTransientStateChanged(this, newHasTransientState);
14121                 } catch (AbstractMethodError e) {
14122                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14123                             " does not fully implement ViewParent", e);
14124                 }
14125             }
14126         }
14127     }
14128 
14129     /**
14130      * Set the view is tracking translation transient state. This flag is used to check if the view
14131      * need to call setHasTransientState(false) to reset transient state that set when starting
14132      * translation.
14133      *
14134      * @param hasTranslationTransientState true if this view has translation transient state
14135      * @hide
14136      */
14137     public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
14138         if (hasTranslationTransientState) {
14139             mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
14140         } else {
14141             mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
14142         }
14143     }
14144 
14145     /**
14146      * @hide
14147      */
14148     public boolean hasTranslationTransientState() {
14149         return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
14150                 == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
14151     }
14152 
14153     /**
14154      * @hide
14155      */
14156     public void clearTranslationState() {
14157         if (mViewTranslationCallback != null) {
14158             mViewTranslationCallback.onClearTranslation(this);
14159         }
14160         clearViewTranslationResponse();
14161         if (hasTranslationTransientState()) {
14162             setHasTransientState(false);
14163             setHasTranslationTransientState(false);
14164         }
14165     }
14166 
14167     /**
14168      * Returns true if this view is currently attached to a window.
14169      */
14170     public boolean isAttachedToWindow() {
14171         return mAttachInfo != null;
14172     }
14173 
14174     /**
14175      * Returns true if this view has been through at least one layout since it
14176      * was last attached to or detached from a window.
14177      */
14178     public boolean isLaidOut() {
14179         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
14180     }
14181 
14182     /**
14183      * @return {@code true} if laid-out and not about to do another layout.
14184      */
14185     boolean isLayoutValid() {
14186         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
14187     }
14188 
14189     /**
14190      * If this view doesn't do any drawing on its own, set this flag to
14191      * allow further optimizations. By default, this flag is not set on
14192      * View, but could be set on some View subclasses such as ViewGroup.
14193      *
14194      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
14195      * you should clear this flag.
14196      *
14197      * @param willNotDraw whether or not this View draw on its own
14198      */
14199     public void setWillNotDraw(boolean willNotDraw) {
14200         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
14201     }
14202 
14203     /**
14204      * Returns whether or not this View draws on its own.
14205      *
14206      * @return true if this view has nothing to draw, false otherwise
14207      */
14208     @ViewDebug.ExportedProperty(category = "drawing")
14209     public boolean willNotDraw() {
14210         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
14211     }
14212 
14213     /**
14214      * When a View's drawing cache is enabled, drawing is redirected to an
14215      * offscreen bitmap. Some views, like an ImageView, must be able to
14216      * bypass this mechanism if they already draw a single bitmap, to avoid
14217      * unnecessary usage of the memory.
14218      *
14219      * @param willNotCacheDrawing true if this view does not cache its
14220      *        drawing, false otherwise
14221      *
14222      * @deprecated The view drawing cache was largely made obsolete with the introduction of
14223      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
14224      * layers are largely unnecessary and can easily result in a net loss in performance due to the
14225      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
14226      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
14227      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
14228      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
14229      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
14230      * software-rendered usages are discouraged and have compatibility issues with hardware-only
14231      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
14232      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
14233      * reports or unit testing the {@link PixelCopy} API is recommended.
14234      */
14235     @Deprecated
14236     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
14237         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
14238     }
14239 
14240     /**
14241      * Returns whether or not this View can cache its drawing or not.
14242      *
14243      * @return true if this view does not cache its drawing, false otherwise
14244      *
14245      * @deprecated The view drawing cache was largely made obsolete with the introduction of
14246      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
14247      * layers are largely unnecessary and can easily result in a net loss in performance due to the
14248      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
14249      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
14250      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
14251      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
14252      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
14253      * software-rendered usages are discouraged and have compatibility issues with hardware-only
14254      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
14255      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
14256      * reports or unit testing the {@link PixelCopy} API is recommended.
14257      */
14258     @ViewDebug.ExportedProperty(category = "drawing")
14259     @Deprecated
14260     public boolean willNotCacheDrawing() {
14261         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
14262     }
14263 
14264     /**
14265      * Indicates whether this view reacts to click events or not.
14266      *
14267      * @return true if the view is clickable, false otherwise
14268      *
14269      * @see #setClickable(boolean)
14270      * @attr ref android.R.styleable#View_clickable
14271      */
14272     @ViewDebug.ExportedProperty
14273     @InspectableProperty
14274     public boolean isClickable() {
14275         return (mViewFlags & CLICKABLE) == CLICKABLE;
14276     }
14277 
14278     /**
14279      * Enables or disables click events for this view. When a view
14280      * is clickable it will change its state to "pressed" on every click.
14281      * Subclasses should set the view clickable to visually react to
14282      * user's clicks.
14283      *
14284      * @param clickable true to make the view clickable, false otherwise
14285      *
14286      * @see #isClickable()
14287      * @attr ref android.R.styleable#View_clickable
14288      */
14289     public void setClickable(boolean clickable) {
14290         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
14291     }
14292 
14293     /**
14294      * Enables or disables click events for this view when disabled.
14295      *
14296      * @param clickableWhenDisabled true to make the view clickable, false otherwise
14297      *
14298      * @attr ref android.R.styleable#View_allowClickWhenDisabled
14299      */
14300     public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
14301         if (clickableWhenDisabled) {
14302             mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
14303         } else {
14304             mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
14305         }
14306     }
14307 
14308     /**
14309      * Indicates whether this view reacts to long click events or not.
14310      *
14311      * @return true if the view is long clickable, false otherwise
14312      *
14313      * @see #setLongClickable(boolean)
14314      * @attr ref android.R.styleable#View_longClickable
14315      */
14316     @InspectableProperty
14317     public boolean isLongClickable() {
14318         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
14319     }
14320 
14321     /**
14322      * Enables or disables long click events for this view. When a view is long
14323      * clickable it reacts to the user holding down the button for a longer
14324      * duration than a tap. This event can either launch the listener or a
14325      * context menu.
14326      *
14327      * @param longClickable true to make the view long clickable, false otherwise
14328      * @see #isLongClickable()
14329      * @attr ref android.R.styleable#View_longClickable
14330      */
14331     public void setLongClickable(boolean longClickable) {
14332         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
14333     }
14334 
14335     /**
14336      * Indicates whether this view reacts to context clicks or not.
14337      *
14338      * @return true if the view is context clickable, false otherwise
14339      * @see #setContextClickable(boolean)
14340      * @attr ref android.R.styleable#View_contextClickable
14341      */
14342     @InspectableProperty
14343     public boolean isContextClickable() {
14344         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
14345     }
14346 
14347     /**
14348      * Enables or disables context clicking for this view. This event can launch the listener.
14349      *
14350      * @param contextClickable true to make the view react to a context click, false otherwise
14351      * @see #isContextClickable()
14352      * @attr ref android.R.styleable#View_contextClickable
14353      */
14354     public void setContextClickable(boolean contextClickable) {
14355         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
14356     }
14357 
14358     /**
14359      * Sets the pressed state for this view and provides a touch coordinate for
14360      * animation hinting.
14361      *
14362      * @param pressed Pass true to set the View's internal state to "pressed",
14363      *            or false to reverts the View's internal state from a
14364      *            previously set "pressed" state.
14365      * @param x The x coordinate of the touch that caused the press
14366      * @param y The y coordinate of the touch that caused the press
14367      */
14368     private void setPressed(boolean pressed, float x, float y) {
14369         if (pressed) {
14370             drawableHotspotChanged(x, y);
14371         }
14372 
14373         setPressed(pressed);
14374     }
14375 
14376     /**
14377      * Sets the pressed state for this view.
14378      *
14379      * @see #isClickable()
14380      * @see #setClickable(boolean)
14381      *
14382      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
14383      *        the View's internal state from a previously set "pressed" state.
14384      */
14385     public void setPressed(boolean pressed) {
14386         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
14387 
14388         if (pressed) {
14389             mPrivateFlags |= PFLAG_PRESSED;
14390         } else {
14391             mPrivateFlags &= ~PFLAG_PRESSED;
14392         }
14393 
14394         if (needsRefresh) {
14395             refreshDrawableState();
14396         }
14397         dispatchSetPressed(pressed);
14398     }
14399 
14400     /**
14401      * Dispatch setPressed to all of this View's children.
14402      *
14403      * @see #setPressed(boolean)
14404      *
14405      * @param pressed The new pressed state
14406      */
14407     protected void dispatchSetPressed(boolean pressed) {
14408     }
14409 
14410     /**
14411      * Indicates whether the view is currently in pressed state. Unless
14412      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
14413      * the pressed state.
14414      *
14415      * @see #setPressed(boolean)
14416      * @see #isClickable()
14417      * @see #setClickable(boolean)
14418      *
14419      * @return true if the view is currently pressed, false otherwise
14420      */
14421     @ViewDebug.ExportedProperty
14422     @InspectableProperty(hasAttributeId = false)
14423     public boolean isPressed() {
14424         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
14425     }
14426 
14427     /**
14428      * @hide
14429      * Indicates whether this view will participate in data collection through
14430      * {@link ViewStructure}.  If true, it will not provide any data
14431      * for itself or its children.  If false, the normal data collection will be allowed.
14432      *
14433      * @return Returns false if assist data collection is not blocked, else true.
14434      *
14435      * @see #setAssistBlocked(boolean)
14436      * @attr ref android.R.styleable#View_assistBlocked
14437      */
14438     public boolean isAssistBlocked() {
14439         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
14440     }
14441 
14442     /**
14443      * @hide
14444      * Controls whether assist data collection from this view and its children is enabled
14445      * (that is, whether {@link #onProvideStructure} and
14446      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
14447      * allowing normal assist collection.  Setting this to false will disable assist collection.
14448      *
14449      * @param enabled Set to true to <em>disable</em> assist data collection, or false
14450      * (the default) to allow it.
14451      *
14452      * @see #isAssistBlocked()
14453      * @see #onProvideStructure
14454      * @see #onProvideVirtualStructure
14455      * @attr ref android.R.styleable#View_assistBlocked
14456      */
14457     @UnsupportedAppUsage
14458     public void setAssistBlocked(boolean enabled) {
14459         if (enabled) {
14460             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
14461         } else {
14462             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
14463         }
14464     }
14465 
14466     /**
14467      * Indicates whether this view will save its state (that is,
14468      * whether its {@link #onSaveInstanceState} method will be called).
14469      *
14470      * @return Returns true if the view state saving is enabled, else false.
14471      *
14472      * @see #setSaveEnabled(boolean)
14473      * @attr ref android.R.styleable#View_saveEnabled
14474      */
14475     @InspectableProperty
14476     public boolean isSaveEnabled() {
14477         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
14478     }
14479 
14480     /**
14481      * Controls whether the saving of this view's state is
14482      * enabled (that is, whether its {@link #onSaveInstanceState} method
14483      * will be called).  Note that even if freezing is enabled, the
14484      * view still must have an id assigned to it (via {@link #setId(int)})
14485      * for its state to be saved.  This flag can only disable the
14486      * saving of this view; any child views may still have their state saved.
14487      *
14488      * @param enabled Set to false to <em>disable</em> state saving, or true
14489      * (the default) to allow it.
14490      *
14491      * @see #isSaveEnabled()
14492      * @see #setId(int)
14493      * @see #onSaveInstanceState()
14494      * @attr ref android.R.styleable#View_saveEnabled
14495      */
14496     public void setSaveEnabled(boolean enabled) {
14497         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
14498     }
14499 
14500     /**
14501      * Gets whether the framework should discard touches when the view's
14502      * window is obscured by another visible window at the touched location.
14503      * Refer to the {@link View} security documentation for more details.
14504      *
14505      * @return True if touch filtering is enabled.
14506      *
14507      * @see #setFilterTouchesWhenObscured(boolean)
14508      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
14509      */
14510     @ViewDebug.ExportedProperty
14511     @InspectableProperty
14512     public boolean getFilterTouchesWhenObscured() {
14513         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
14514     }
14515 
14516     /**
14517      * Sets whether the framework should discard touches when the view's
14518      * window is obscured by another visible window at the touched location.
14519      * Refer to the {@link View} security documentation for more details.
14520      *
14521      * @param enabled True if touch filtering should be enabled.
14522      *
14523      * @see #getFilterTouchesWhenObscured
14524      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
14525      */
14526     public void setFilterTouchesWhenObscured(boolean enabled) {
14527         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
14528                 FILTER_TOUCHES_WHEN_OBSCURED);
14529         calculateAccessibilityDataSensitive();
14530     }
14531 
14532     /**
14533      * Indicates whether the entire hierarchy under this view will save its
14534      * state when a state saving traversal occurs from its parent.  The default
14535      * is true; if false, these views will not be saved unless
14536      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
14537      *
14538      * @return Returns true if the view state saving from parent is enabled, else false.
14539      *
14540      * @see #setSaveFromParentEnabled(boolean)
14541      */
14542     public boolean isSaveFromParentEnabled() {
14543         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
14544     }
14545 
14546     /**
14547      * Controls whether the entire hierarchy under this view will save its
14548      * state when a state saving traversal occurs from its parent.  The default
14549      * is true; if false, these views will not be saved unless
14550      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
14551      *
14552      * @param enabled Set to false to <em>disable</em> state saving, or true
14553      * (the default) to allow it.
14554      *
14555      * @see #isSaveFromParentEnabled()
14556      * @see #setId(int)
14557      * @see #onSaveInstanceState()
14558      */
14559     public void setSaveFromParentEnabled(boolean enabled) {
14560         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
14561     }
14562 
14563 
14564     /**
14565      * Returns whether this View is currently able to take focus.
14566      *
14567      * @return True if this view can take focus, or false otherwise.
14568      */
14569     @ViewDebug.ExportedProperty(category = "focus")
14570     public final boolean isFocusable() {
14571         return FOCUSABLE == (mViewFlags & FOCUSABLE);
14572     }
14573 
14574     /**
14575      * Returns the focusable setting for this view.
14576      *
14577      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
14578      * @attr ref android.R.styleable#View_focusable
14579      */
14580     @ViewDebug.ExportedProperty(mapping = {
14581             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
14582             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
14583             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
14584             }, category = "focus")
14585     @InspectableProperty(enumMapping = {
14586             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
14587             @EnumEntry(value = FOCUSABLE, name = "true"),
14588             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
14589     })
14590     @Focusable
14591     public int getFocusable() {
14592         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
14593     }
14594 
14595     /**
14596      * When a view is focusable, it may not want to take focus when in touch mode.
14597      * For example, a button would like focus when the user is navigating via a D-pad
14598      * so that the user can click on it, but once the user starts touching the screen,
14599      * the button shouldn't take focus
14600      * @return Whether the view is focusable in touch mode.
14601      * @attr ref android.R.styleable#View_focusableInTouchMode
14602      */
14603     @ViewDebug.ExportedProperty(category = "focus")
14604     @InspectableProperty
14605     public final boolean isFocusableInTouchMode() {
14606         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
14607     }
14608 
14609     /**
14610      * Returns whether the view should be treated as a focusable unit by screen reader
14611      * accessibility tools.
14612      * <p>
14613      * <b>Note:</b> Use
14614      * {@link androidx.core.view.ViewCompat#setScreenReaderFocusable(View, boolean)}
14615      * for backwards-compatibility. </aside>
14616      * @see #setScreenReaderFocusable(boolean)
14617      *
14618      * @return Whether the view should be treated as a focusable unit by screen reader.
14619      *
14620      * @attr ref android.R.styleable#View_screenReaderFocusable
14621      */
14622     @InspectableProperty
14623     public boolean isScreenReaderFocusable() {
14624         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
14625     }
14626 
14627     /**
14628      * Sets whether this View should be a focusable element for screen readers
14629      * and include non-focusable Views from its subtree when providing feedback.
14630      * <p>
14631      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
14632      * but does not impact input focus behavior.
14633      *
14634      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
14635      *                              accessibility tools.
14636      *
14637      * @attr ref android.R.styleable#View_screenReaderFocusable
14638      */
14639     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
14640         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
14641     }
14642 
14643     /**
14644      * Gets whether this view is a heading for accessibility purposes.
14645      *
14646      * @return {@code true} if the view is a heading, {@code false} otherwise.
14647      *
14648      * @attr ref android.R.styleable#View_accessibilityHeading
14649      */
14650     @InspectableProperty
14651     public boolean isAccessibilityHeading() {
14652         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
14653     }
14654 
14655     /**
14656      * Set if view is a heading for a section of content for accessibility purposes.
14657      * <p>
14658      * Users of some accessibility services can choose to navigate between headings
14659      * instead of between paragraphs, words, etc. Apps that provide headings on
14660      * sections of text can help the text navigation experience.
14661      * <p>
14662      * <b>Note:</b> Use {@link androidx.core.view.ViewCompat#setAccessibilityHeading(View, boolean)}
14663      * for backwards-compatibility. </aside>
14664      *
14665      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
14666      *
14667      * @attr ref android.R.styleable#View_accessibilityHeading
14668      */
14669     public void setAccessibilityHeading(boolean isHeading) {
14670         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
14671     }
14672 
14673     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
14674         int pflags3 = mPrivateFlags3;
14675         if (newValue) {
14676             pflags3 |= mask;
14677         } else {
14678             pflags3 &= ~mask;
14679         }
14680 
14681         if (pflags3 != mPrivateFlags3) {
14682             mPrivateFlags3 = pflags3;
14683             notifyViewAccessibilityStateChangedIfNeeded(
14684                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14685         }
14686     }
14687 
14688     /**
14689      * Find the nearest view in the specified direction that can take focus.
14690      * This does not actually give focus to that view.
14691      *
14692      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
14693      *
14694      * @return The nearest focusable in the specified direction, or null if none
14695      *         can be found.
14696      */
14697     public View focusSearch(@FocusRealDirection int direction) {
14698         if (mParent != null) {
14699             return mParent.focusSearch(this, direction);
14700         } else {
14701             return null;
14702         }
14703     }
14704 
14705     /**
14706      * Returns whether this View is a root of a keyboard navigation cluster.
14707      *
14708      * @return True if this view is a root of a cluster, or false otherwise.
14709      * @attr ref android.R.styleable#View_keyboardNavigationCluster
14710      */
14711     @ViewDebug.ExportedProperty(category = "focus")
14712     @InspectableProperty
14713     public final boolean isKeyboardNavigationCluster() {
14714         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
14715     }
14716 
14717     /**
14718      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
14719      * will be ignored.
14720      *
14721      * @return the keyboard navigation cluster that this view is in (can be this view)
14722      *         or {@code null} if not in one
14723      */
14724     View findKeyboardNavigationCluster() {
14725         if (mParent instanceof View) {
14726             View cluster = ((View) mParent).findKeyboardNavigationCluster();
14727             if (cluster != null) {
14728                 return cluster;
14729             } else if (isKeyboardNavigationCluster()) {
14730                 return this;
14731             }
14732         }
14733         return null;
14734     }
14735 
14736     /**
14737      * Set whether this view is a root of a keyboard navigation cluster.
14738      *
14739      * @param isCluster If true, this view is a root of a cluster.
14740      *
14741      * @attr ref android.R.styleable#View_keyboardNavigationCluster
14742      */
14743     public void setKeyboardNavigationCluster(boolean isCluster) {
14744         if (isCluster) {
14745             mPrivateFlags3 |= PFLAG3_CLUSTER;
14746         } else {
14747             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
14748         }
14749     }
14750 
14751     /**
14752      * Sets this View as the one which receives focus the next time cluster navigation jumps
14753      * to the cluster containing this View. This does NOT change focus even if the cluster
14754      * containing this view is current.
14755      *
14756      * @hide
14757      */
14758     @TestApi
14759     public final void setFocusedInCluster() {
14760         setFocusedInCluster(findKeyboardNavigationCluster());
14761     }
14762 
14763     private void setFocusedInCluster(View cluster) {
14764         if (this instanceof ViewGroup) {
14765             ((ViewGroup) this).mFocusedInCluster = null;
14766         }
14767         if (cluster == this) {
14768             return;
14769         }
14770         ViewParent parent = mParent;
14771         View child = this;
14772         while (parent instanceof ViewGroup) {
14773             ((ViewGroup) parent).mFocusedInCluster = child;
14774             if (parent == cluster) {
14775                 break;
14776             }
14777             child = (View) parent;
14778             parent = parent.getParent();
14779         }
14780     }
14781 
14782     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
14783         if (oldFocus != null) {
14784             View oldCluster = oldFocus.findKeyboardNavigationCluster();
14785             View cluster = findKeyboardNavigationCluster();
14786             if (oldCluster != cluster) {
14787                 // Going from one cluster to another, so save last-focused.
14788                 // This covers cluster jumps because they are always FOCUS_DOWN
14789                 oldFocus.setFocusedInCluster(oldCluster);
14790                 if (!(oldFocus.mParent instanceof ViewGroup)) {
14791                     return;
14792                 }
14793                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
14794                     // This is a result of ordered navigation so consider navigation through
14795                     // the previous cluster "complete" and clear its last-focused memory.
14796                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
14797                 } else if (oldFocus instanceof ViewGroup
14798                         && ((ViewGroup) oldFocus).getDescendantFocusability()
14799                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
14800                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
14801                     // This means oldFocus is not focusable since it obviously has a focusable
14802                     // child (this). Don't restore focus to it in the future.
14803                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
14804                 }
14805             }
14806         }
14807     }
14808 
14809     /**
14810      * Returns whether this View should receive focus when the focus is restored for the view
14811      * hierarchy containing this view.
14812      * <p>
14813      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
14814      * window or serves as a target of cluster navigation.
14815      *
14816      * @see #restoreDefaultFocus()
14817      *
14818      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
14819      * @attr ref android.R.styleable#View_focusedByDefault
14820      */
14821     @ViewDebug.ExportedProperty(category = "focus")
14822     @InspectableProperty
14823     public final boolean isFocusedByDefault() {
14824         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
14825     }
14826 
14827     /**
14828      * Sets whether this View should receive focus when the focus is restored for the view
14829      * hierarchy containing this view.
14830      * <p>
14831      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
14832      * window or serves as a target of cluster navigation.
14833      *
14834      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
14835      *                           {@code false} otherwise.
14836      *
14837      * @see #restoreDefaultFocus()
14838      *
14839      * @attr ref android.R.styleable#View_focusedByDefault
14840      */
14841     @RemotableViewMethod
14842     public void setFocusedByDefault(boolean isFocusedByDefault) {
14843         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
14844             return;
14845         }
14846 
14847         if (isFocusedByDefault) {
14848             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
14849         } else {
14850             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
14851         }
14852 
14853         if (mParent instanceof ViewGroup) {
14854             if (isFocusedByDefault) {
14855                 ((ViewGroup) mParent).setDefaultFocus(this);
14856             } else {
14857                 ((ViewGroup) mParent).clearDefaultFocus(this);
14858             }
14859         }
14860     }
14861 
14862     /**
14863      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
14864      *
14865      * @return {@code true} if this view has default focus, {@code false} otherwise
14866      */
14867     boolean hasDefaultFocus() {
14868         return isFocusedByDefault();
14869     }
14870 
14871     /**
14872      * Find the nearest keyboard navigation cluster in the specified direction.
14873      * This does not actually give focus to that cluster.
14874      *
14875      * @param currentCluster The starting point of the search. Null means the current cluster is not
14876      *                       found yet
14877      * @param direction Direction to look
14878      *
14879      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
14880      *         can be found
14881      */
14882     public View keyboardNavigationClusterSearch(View currentCluster,
14883             @FocusDirection int direction) {
14884         if (isKeyboardNavigationCluster()) {
14885             currentCluster = this;
14886         }
14887         if (isRootNamespace()) {
14888             // Root namespace means we should consider ourselves the top of the
14889             // tree for group searching; otherwise we could be group searching
14890             // into other tabs.  see LocalActivityManager and TabHost for more info.
14891             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
14892                     this, currentCluster, direction);
14893         } else if (mParent != null) {
14894             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
14895         }
14896         return null;
14897     }
14898 
14899     /**
14900      * This method is the last chance for the focused view and its ancestors to
14901      * respond to an arrow key. This is called when the focused view did not
14902      * consume the key internally, nor could the view system find a new view in
14903      * the requested direction to give focus to.
14904      *
14905      * @param focused The currently focused view.
14906      * @param direction The direction focus wants to move. One of FOCUS_UP,
14907      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
14908      * @return True if the this view consumed this unhandled move.
14909      */
14910     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
14911         return false;
14912     }
14913 
14914     /**
14915      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
14916      * have {@link android.R.attr#state_focused} defined in its background.
14917      *
14918      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
14919      *                                      highlight, {@code false} otherwise.
14920      *
14921      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
14922      */
14923     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
14924         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
14925     }
14926 
14927     /**
14928      * Returns whether this View should use a default focus highlight when it gets focused but
14929      * doesn't have {@link android.R.attr#state_focused} defined in its background.
14930      *
14931      * @return True if this View should use a default focus highlight.
14932      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
14933      */
14934     @ViewDebug.ExportedProperty(category = "focus")
14935     @InspectableProperty
14936     public final boolean getDefaultFocusHighlightEnabled() {
14937         return mDefaultFocusHighlightEnabled;
14938     }
14939 
14940     /**
14941      * If a user manually specified the next view id for a particular direction,
14942      * use the root to look up the view.
14943      * @param root The root view of the hierarchy containing this view.
14944      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
14945      * or FOCUS_BACKWARD.
14946      * @return The user specified next view, or null if there is none.
14947      */
14948     View findUserSetNextFocus(View root, @FocusDirection int direction) {
14949         switch (direction) {
14950             case FOCUS_LEFT:
14951                 if (mNextFocusLeftId == View.NO_ID) return null;
14952                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
14953             case FOCUS_RIGHT:
14954                 if (mNextFocusRightId == View.NO_ID) return null;
14955                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
14956             case FOCUS_UP:
14957                 if (mNextFocusUpId == View.NO_ID) return null;
14958                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
14959             case FOCUS_DOWN:
14960                 if (mNextFocusDownId == View.NO_ID) return null;
14961                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
14962             case FOCUS_FORWARD:
14963                 if (mNextFocusForwardId == View.NO_ID) return null;
14964                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
14965             case FOCUS_BACKWARD: {
14966                 if (mID == View.NO_ID) return null;
14967                 final View rootView = root;
14968                 final View startView = this;
14969                 // Since we have forward links but no backward links, we need to find the view that
14970                 // forward links to this view. We can't just find the view with the specified ID
14971                 // because view IDs need not be unique throughout the tree.
14972                 return root.findViewByPredicateInsideOut(startView,
14973                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
14974                             == startView);
14975             }
14976         }
14977         return null;
14978     }
14979 
14980     /**
14981      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
14982      * use the root to look up the view.
14983      *
14984      * @param root the root view of the hierarchy containing this view
14985      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
14986      * @return the user-specified next cluster, or {@code null} if there is none
14987      */
14988     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
14989         switch (direction) {
14990             case FOCUS_FORWARD:
14991                 if (mNextClusterForwardId == View.NO_ID) return null;
14992                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
14993             case FOCUS_BACKWARD: {
14994                 if (mID == View.NO_ID) return null;
14995                 final int id = mID;
14996                 return root.findViewByPredicateInsideOut(this,
14997                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
14998             }
14999         }
15000         return null;
15001     }
15002 
15003     private View findViewInsideOutShouldExist(View root, int id) {
15004         return findViewInsideOutShouldExist(root, this, id);
15005     }
15006 
15007     private View findViewInsideOutShouldExist(View root, View start, int id) {
15008         if (mMatchIdPredicate == null) {
15009             mMatchIdPredicate = new MatchIdPredicate();
15010         }
15011         mMatchIdPredicate.mId = id;
15012         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
15013         if (result == null) {
15014             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
15015         }
15016         return result;
15017     }
15018 
15019     /**
15020      * Find and return all focusable views that are descendants of this view,
15021      * possibly including this view if it is focusable itself.
15022      *
15023      * @param direction The direction of the focus
15024      * @return A list of focusable views
15025      */
15026     public ArrayList<View> getFocusables(@FocusDirection int direction) {
15027         ArrayList<View> result = new ArrayList<View>(24);
15028         addFocusables(result, direction);
15029         return result;
15030     }
15031 
15032     /**
15033      * Add any focusable views that are descendants of this view (possibly
15034      * including this view if it is focusable itself) to views.  If we are in touch mode,
15035      * only add views that are also focusable in touch mode.
15036      *
15037      * @param views Focusable views found so far
15038      * @param direction The direction of the focus
15039      */
15040     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
15041         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
15042     }
15043 
15044     /**
15045      * Adds any focusable views that are descendants of this view (possibly
15046      * including this view if it is focusable itself) to views. This method
15047      * adds all focusable views regardless if we are in touch mode or
15048      * only views focusable in touch mode if we are in touch mode or
15049      * only views that can take accessibility focus if accessibility is enabled
15050      * depending on the focusable mode parameter.
15051      *
15052      * @param views Focusable views found so far or null if all we are interested is
15053      *        the number of focusables.
15054      * @param direction The direction of the focus.
15055      * @param focusableMode The type of focusables to be added.
15056      *
15057      * @see #FOCUSABLES_ALL
15058      * @see #FOCUSABLES_TOUCH_MODE
15059      */
15060     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
15061             @FocusableMode int focusableMode) {
15062         if (views == null) {
15063             return;
15064         }
15065         if (!canTakeFocus()) {
15066             return;
15067         }
15068         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
15069                 && !isFocusableInTouchMode()) {
15070             return;
15071         }
15072         views.add(this);
15073     }
15074 
15075     /**
15076      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
15077      * including this view if it is a cluster root itself) to views.
15078      *
15079      * @param views Keyboard navigation cluster roots found so far
15080      * @param direction Direction to look
15081      */
15082     public void addKeyboardNavigationClusters(
15083             @NonNull Collection<View> views,
15084             int direction) {
15085         if (!isKeyboardNavigationCluster()) {
15086             return;
15087         }
15088         if (!hasFocusable()) {
15089             return;
15090         }
15091         views.add(this);
15092     }
15093 
15094     /**
15095      * Finds the Views that contain given text. The containment is case insensitive.
15096      * The search is performed by either the text that the View renders or the content
15097      * description that describes the view for accessibility purposes and the view does
15098      * not render or both. Clients can specify how the search is to be performed via
15099      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
15100      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
15101      *
15102      * @param outViews The output list of matching Views.
15103      * @param searched The text to match against.
15104      *
15105      * @see #FIND_VIEWS_WITH_TEXT
15106      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
15107      * @see #setContentDescription(CharSequence)
15108      */
15109     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
15110             @FindViewFlags int flags) {
15111         if (getAccessibilityNodeProvider() != null) {
15112             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
15113                 outViews.add(this);
15114             }
15115         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
15116                 && (searched != null && searched.length() > 0)
15117                 && (mContentDescription != null && mContentDescription.length() > 0)) {
15118             String searchedLowerCase = searched.toString().toLowerCase();
15119             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
15120             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
15121                 outViews.add(this);
15122             }
15123         }
15124     }
15125 
15126     /**
15127      * Find and return all touchable views that are descendants of this view,
15128      * possibly including this view if it is touchable itself.
15129      *
15130      * @return A list of touchable views
15131      */
15132     public ArrayList<View> getTouchables() {
15133         ArrayList<View> result = new ArrayList<View>();
15134         addTouchables(result);
15135         return result;
15136     }
15137 
15138     /**
15139      * Add any touchable views that are descendants of this view (possibly
15140      * including this view if it is touchable itself) to views.
15141      *
15142      * @param views Touchable views found so far
15143      */
15144     public void addTouchables(ArrayList<View> views) {
15145         final int viewFlags = mViewFlags;
15146 
15147         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
15148                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
15149                 && (viewFlags & ENABLED_MASK) == ENABLED) {
15150             views.add(this);
15151         }
15152     }
15153 
15154     /**
15155      * Returns whether this View is accessibility focused.
15156      *
15157      * @return True if this View is accessibility focused.
15158      */
15159     @InspectableProperty(hasAttributeId = false)
15160     public boolean isAccessibilityFocused() {
15161         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
15162     }
15163 
15164     /**
15165      * Call this to try to give accessibility focus to this view.
15166      *
15167      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
15168      * returns false or the view is no visible or the view already has accessibility
15169      * focus.
15170      *
15171      * See also {@link #focusSearch(int)}, which is what you call to say that you
15172      * have focus, and you want your parent to look for the next one.
15173      *
15174      * <p>
15175      * <b>Note:</b> Avoid setting accessibility focus. This is intended to be controlled by screen
15176      * readers. Apps changing focus can confuse screen readers, so the resulting behavior can vary
15177      * by device and screen reader version.
15178      *
15179      * @return Whether this view actually took accessibility focus.
15180      *
15181      * @hide
15182      */
15183     @UnsupportedAppUsage
15184     public boolean requestAccessibilityFocus() {
15185         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
15186         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
15187             return false;
15188         }
15189         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
15190             return false;
15191         }
15192         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
15193             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
15194             ViewRootImpl viewRootImpl = getViewRootImpl();
15195             if (viewRootImpl != null) {
15196                 viewRootImpl.setAccessibilityFocus(this, null);
15197             }
15198             invalidate();
15199             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
15200             return true;
15201         }
15202         return false;
15203     }
15204 
15205     /**
15206      * Call this to try to clear accessibility focus of this view.
15207      *
15208      * See also {@link #focusSearch(int)}, which is what you call to say that you
15209      * have focus, and you want your parent to look for the next one.
15210      *
15211      * @hide
15212      */
15213     @UnsupportedAppUsage
15214     public void clearAccessibilityFocus() {
15215         clearAccessibilityFocusNoCallbacks(0);
15216 
15217         // Clear the global reference of accessibility focus if this view or
15218         // any of its descendants had accessibility focus. This will NOT send
15219         // an event or update internal state if focus is cleared from a
15220         // descendant view, which may leave views in inconsistent states.
15221         final ViewRootImpl viewRootImpl = getViewRootImpl();
15222         if (viewRootImpl != null) {
15223             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
15224             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
15225                 viewRootImpl.setAccessibilityFocus(null, null);
15226             }
15227         }
15228     }
15229 
15230     private void sendAccessibilityHoverEvent(int eventType) {
15231         // Since we are not delivering to a client accessibility events from not
15232         // important views (unless the clinet request that) we need to fire the
15233         // event from the deepest view exposed to the client. As a consequence if
15234         // the user crosses a not exposed view the client will see enter and exit
15235         // of the exposed predecessor followed by and enter and exit of that same
15236         // predecessor when entering and exiting the not exposed descendant. This
15237         // is fine since the client has a clear idea which view is hovered at the
15238         // price of a couple more events being sent. This is a simple and
15239         // working solution.
15240         View source = this;
15241         while (true) {
15242             if (source.includeForAccessibility(false)) {
15243                 source.sendAccessibilityEvent(eventType);
15244                 return;
15245             }
15246             ViewParent parent = source.getParent();
15247             if (parent instanceof View) {
15248                 source = (View) parent;
15249             } else {
15250                 return;
15251             }
15252         }
15253     }
15254 
15255     /**
15256      * Clears accessibility focus without calling any callback methods
15257      * normally invoked in {@link #clearAccessibilityFocus()}. This method
15258      * is used separately from that one for clearing accessibility focus when
15259      * giving this focus to another view.
15260      *
15261      * @param action The action, if any, that led to focus being cleared. Set to
15262      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
15263      * the window.
15264      */
15265     void clearAccessibilityFocusNoCallbacks(int action) {
15266         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
15267             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
15268             invalidate();
15269             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
15270                 AccessibilityEvent event = AccessibilityEvent.obtain(
15271                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
15272                 event.setAction(action);
15273                 if (mAccessibilityDelegate != null) {
15274                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
15275                 } else {
15276                     sendAccessibilityEventUnchecked(event);
15277                 }
15278             }
15279 
15280             updatePreferKeepClearForFocus();
15281         }
15282     }
15283 
15284     /**
15285      * Call this to try to give focus to a specific view or to one of its
15286      * descendants.
15287      *
15288      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
15289      * false), or if it can't be focused due to other conditions (not focusable in touch mode
15290      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
15291      * enabled, or has no size).
15292      *
15293      * See also {@link #focusSearch(int)}, which is what you call to say that you
15294      * have focus, and you want your parent to look for the next one.
15295      *
15296      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
15297      * {@link #FOCUS_DOWN} and <code>null</code>.
15298      *
15299      * @return Whether this view or one of its descendants actually took focus.
15300      */
15301     public final boolean requestFocus() {
15302         return requestFocus(View.FOCUS_DOWN);
15303     }
15304 
15305     /**
15306      * This will request focus for whichever View was last focused within this
15307      * cluster before a focus-jump out of it.
15308      *
15309      * @hide
15310      */
15311     @TestApi
15312     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
15313         // Prioritize focusableByDefault over algorithmic focus selection.
15314         if (restoreDefaultFocus()) {
15315             return true;
15316         }
15317         return requestFocus(direction);
15318     }
15319 
15320     /**
15321      * This will request focus for whichever View not in a cluster was last focused before a
15322      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
15323      * the "first" focusable view it finds.
15324      *
15325      * @hide
15326      */
15327     @TestApi
15328     public boolean restoreFocusNotInCluster() {
15329         return requestFocus(View.FOCUS_DOWN);
15330     }
15331 
15332     /**
15333      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
15334      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
15335      *
15336      * @return Whether this view or one of its descendants actually took focus
15337      */
15338     public boolean restoreDefaultFocus() {
15339         return requestFocus(View.FOCUS_DOWN);
15340     }
15341 
15342     /**
15343      * Call this to try to give focus to a specific view or to one of its
15344      * descendants and give it a hint about what direction focus is heading.
15345      *
15346      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
15347      * false), or if it is focusable and it is not focusable in touch mode
15348      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
15349      *
15350      * See also {@link #focusSearch(int)}, which is what you call to say that you
15351      * have focus, and you want your parent to look for the next one.
15352      *
15353      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
15354      * <code>null</code> set for the previously focused rectangle.
15355      *
15356      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
15357      * @return Whether this view or one of its descendants actually took focus.
15358      */
15359     public final boolean requestFocus(int direction) {
15360         return requestFocus(direction, null);
15361     }
15362 
15363     /**
15364      * Call this to try to give focus to a specific view or to one of its descendants
15365      * and give it hints about the direction and a specific rectangle that the focus
15366      * is coming from.  The rectangle can help give larger views a finer grained hint
15367      * about where focus is coming from, and therefore, where to show selection, or
15368      * forward focus change internally.
15369      *
15370      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
15371      * false), or if it is focusable and it is not focusable in touch mode
15372      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
15373      *
15374      * A View will not take focus if it is not visible.
15375      *
15376      * A View will not take focus if one of its parents has
15377      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
15378      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
15379      *
15380      * See also {@link #focusSearch(int)}, which is what you call to say that you
15381      * have focus, and you want your parent to look for the next one.
15382      *
15383      * You may wish to override this method if your custom {@link View} has an internal
15384      * {@link View} that it wishes to forward the request to.
15385      *
15386      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
15387      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
15388      *        to give a finer grained hint about where focus is coming from.  May be null
15389      *        if there is no hint.
15390      * @return Whether this view or one of its descendants actually took focus.
15391      */
15392     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
15393         return requestFocusNoSearch(direction, previouslyFocusedRect);
15394     }
15395 
15396     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
15397         // need to be focusable
15398         if (!canTakeFocus()) {
15399             return false;
15400         }
15401 
15402         // need to be focusable in touch mode if in touch mode
15403         if (isInTouchMode() &&
15404             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
15405                return false;
15406         }
15407 
15408         // need to not have any parents blocking us
15409         if (hasAncestorThatBlocksDescendantFocus()) {
15410             return false;
15411         }
15412 
15413         if (!isLayoutValid()) {
15414             mPrivateFlags |= PFLAG_WANTS_FOCUS;
15415         } else {
15416             clearParentsWantFocus();
15417         }
15418 
15419         handleFocusGainInternal(direction, previouslyFocusedRect);
15420         return true;
15421     }
15422 
15423     void clearParentsWantFocus() {
15424         if (mParent instanceof View) {
15425             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
15426             ((View) mParent).clearParentsWantFocus();
15427         }
15428     }
15429 
15430     /**
15431      * Call this to try to give focus to a specific view or to one of its descendants. This is a
15432      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
15433      * touch mode to request focus when they are touched.
15434      *
15435      * @return Whether this view or one of its descendants actually took focus.
15436      *
15437      * @see #isInTouchMode()
15438      *
15439      */
15440     public final boolean requestFocusFromTouch() {
15441         // Leave touch mode if we need to
15442         if (isInTouchMode()) {
15443             ViewRootImpl viewRoot = getViewRootImpl();
15444             if (viewRoot != null) {
15445                 viewRoot.ensureTouchMode(false);
15446             }
15447         }
15448         return requestFocus(View.FOCUS_DOWN);
15449     }
15450 
15451     /**
15452      * @return Whether any ancestor of this view blocks descendant focus.
15453      */
15454     private boolean hasAncestorThatBlocksDescendantFocus() {
15455         final boolean focusableInTouchMode = isFocusableInTouchMode();
15456         ViewParent ancestor = mParent;
15457         while (ancestor instanceof ViewGroup) {
15458             final ViewGroup vgAncestor = (ViewGroup) ancestor;
15459             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
15460                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
15461                 return true;
15462             } else {
15463                 ancestor = vgAncestor.getParent();
15464             }
15465         }
15466         return false;
15467     }
15468 
15469     /**
15470      * Gets the mode for determining whether this View is important for accessibility.
15471      * A view is important for accessibility if it fires accessibility events and if it
15472      * is reported to accessibility services that query the screen.
15473      *
15474      * @return The mode for determining whether a view is important for accessibility, one
15475      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
15476      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
15477      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
15478      *
15479      * @attr ref android.R.styleable#View_importantForAccessibility
15480      *
15481      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
15482      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
15483      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
15484      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
15485      */
15486     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
15487             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
15488             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
15489             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
15490             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
15491                     to = "noHideDescendants")
15492         })
15493     @InspectableProperty(enumMapping = {
15494             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
15495             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
15496             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
15497             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
15498                     name = "noHideDescendants"),
15499     })
15500     public int getImportantForAccessibility() {
15501         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
15502                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
15503     }
15504 
15505     /**
15506      * Sets the live region mode for this view. This indicates to accessibility
15507      * services whether they should automatically notify the user about changes
15508      * to the view's content description or text, or to the content descriptions
15509      * or text of the view's children (where applicable).
15510      * <p>
15511      * Different priority levels are available:
15512      * <ul>
15513      *   <li>
15514      *       {@link #ACCESSIBILITY_LIVE_REGION_POLITE}:
15515      *       Indicates that updates to the region should be presented to the user. Suitable in most
15516      *       cases for prominent updates within app content that don't require the user's immediate
15517      *       attention.
15518      *   </li>
15519      *   <li>
15520      *       {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}: Indicates that updates to the region have
15521      *       the highest priority and should be presented to the user immediately. This may result
15522      *       in disruptive notifications from an accessibility service, which may potentially
15523      *       interrupt other feedback or user actions, so it should generally be used only for
15524      *       critical, time-sensitive information.
15525      *   </li>
15526      *   <li>
15527      *       {@link #ACCESSIBILITY_LIVE_REGION_NONE}: Disables change announcements (the default for
15528      *       most views).
15529      *   </li>
15530      * </ul>
15531      * <p>
15532      * Examples:
15533      * <ul>
15534      *     <li>
15535      *         Selecting an option in a dropdown menu updates a panel below with the updated
15536      *         content. This panel may be marked as a live region with
15537      *         {@link #ACCESSIBILITY_LIVE_REGION_POLITE} to notify users of the change. A screen
15538      *         reader may queue changes as announcements that don't disrupt ongoing speech.
15539      *      </li>
15540      *      <li>
15541      *          An emergency alert may be marked with {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
15542      *          to immediately inform users of the emergency.
15543      *      </li>
15544      * </ul>
15545      * <p>
15546      * For error notifications, like an "incorrect password" warning in a login screen, views
15547      * should send a {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
15548      * {@code AccessibilityEvent} with a content change type
15549      * {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR} and set
15550      * {@link AccessibilityNodeInfo#setError(CharSequence)}. Custom widgets should provide
15551      * error-setting methods that support accessibility. For example, use
15552      * {@link android.widget.TextView#setError(CharSequence)} instead of explicitly sending events.
15553      * <p>
15554      * Don't use live regions for frequently-updating UI elements (e.g., progress bars), as this can
15555      * overwhelm the user with feedback from accessibility services. If necessary, use
15556      * {@link AccessibilityNodeInfo#setMinDurationBetweenContentChanges(Duration)} to throttle
15557      * feedback and reduce disruptions.
15558      * <p>
15559      * <aside><b>Note:</b> Use
15560      * {@link androidx.core.view.ViewCompat#setAccessibilityLiveRegion(View, int)}
15561      * for backwards-compatibility. </aside>
15562      *
15563      * @param mode The live region mode for this view, one of:
15564      *        <ul>
15565      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
15566      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
15567      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
15568      *        </ul>
15569      * @attr ref android.R.styleable#View_accessibilityLiveRegion
15570      */
15571     public void setAccessibilityLiveRegion(int mode) {
15572         if (mode != getAccessibilityLiveRegion()) {
15573             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
15574             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
15575                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
15576             notifyViewAccessibilityStateChangedIfNeeded(
15577                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15578         }
15579     }
15580 
15581     /**
15582      * Gets the live region mode for this View.
15583      *
15584      * @return The live region mode for the view.
15585      *
15586      * @attr ref android.R.styleable#View_accessibilityLiveRegion
15587      *
15588      * @see #setAccessibilityLiveRegion(int)
15589      */
15590     @InspectableProperty(enumMapping = {
15591             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
15592             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
15593             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
15594     })
15595     public int getAccessibilityLiveRegion() {
15596         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
15597                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
15598     }
15599 
15600     /**
15601      * Sets how to determine whether this view is important for accessibility
15602      * which is if it fires accessibility events and if it is reported to
15603      * accessibility services that query the screen.
15604      *
15605      * @param mode How to determine whether this view is important for accessibility.
15606      *
15607      * @attr ref android.R.styleable#View_importantForAccessibility
15608      *
15609      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
15610      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
15611      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
15612      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
15613      */
15614     public void setImportantForAccessibility(int mode) {
15615         final int oldMode = getImportantForAccessibility();
15616         if (mode != oldMode) {
15617             final boolean hideDescendants =
15618                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
15619 
15620             // If this node or its descendants are no longer important, try to
15621             // clear accessibility focus.
15622             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
15623                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
15624                 if (focusHost != null) {
15625                     focusHost.clearAccessibilityFocus();
15626                 }
15627             }
15628 
15629             // If we're moving between AUTO and another state, we might not need
15630             // to send a subtree changed notification. We'll store the computed
15631             // importance, since we'll need to check it later to make sure.
15632             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
15633                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
15634             final boolean oldIncludeForAccessibility =
15635                     maySkipNotify && includeForAccessibility(false);
15636             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
15637             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
15638                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
15639             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility(false)) {
15640                 notifySubtreeAccessibilityStateChangedIfNeeded();
15641             } else {
15642                 notifyViewAccessibilityStateChangedIfNeeded(
15643                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15644             }
15645         }
15646     }
15647 
15648     /**
15649      * Returns the view within this view's hierarchy that is hosting
15650      * accessibility focus.
15651      *
15652      * @param searchDescendants whether to search for focus in descendant views
15653      * @return the view hosting accessibility focus, or {@code null}
15654      */
15655     private View findAccessibilityFocusHost(boolean searchDescendants) {
15656         if (isAccessibilityFocusedViewOrHost()) {
15657             return this;
15658         }
15659 
15660         if (searchDescendants) {
15661             final ViewRootImpl viewRoot = getViewRootImpl();
15662             if (viewRoot != null) {
15663                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
15664                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
15665                     return focusHost;
15666                 }
15667             }
15668         }
15669 
15670         return null;
15671     }
15672 
15673     /**
15674      * Computes whether this view should be exposed for accessibility. In
15675      * general, views that are interactive or provide information are exposed
15676      * while views that serve only as containers are hidden.
15677      * <p>
15678      * If an ancestor of this view has importance
15679      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
15680      * returns <code>false</code>.
15681      * <p>
15682      * Otherwise, the value is computed according to the view's
15683      * {@link #getImportantForAccessibility()} value:
15684      * <ol>
15685      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
15686      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
15687      * </code>
15688      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
15689      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
15690      * view satisfies any of the following:
15691      * <ul>
15692      * <li>Is actionable, e.g. {@link #isClickable()},
15693      * {@link #isLongClickable()}, {@link #isContextClickable()},
15694      * {@link #isScreenReaderFocusable()}, or {@link #isFocusable()}
15695      * <li>Has an {@link AccessibilityDelegate}
15696      * <li>Has an {@link AccessibilityNodeProvider}
15697      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
15698      * {@link OnKeyListener}, etc.
15699      * <li>Is an accessibility live region, e.g.
15700      * {@link #getAccessibilityLiveRegion()} is not
15701      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
15702      * </ul>
15703      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
15704      * <li>Is an accessibility heading, see {@link #setAccessibilityHeading(boolean)}.</li>
15705      * </ol>
15706      *
15707      * @return Whether the view is exposed for accessibility.
15708      * @see #setImportantForAccessibility(int)
15709      * @see #getImportantForAccessibility()
15710      */
15711     public boolean isImportantForAccessibility() {
15712         final int mode = getImportantForAccessibility();
15713         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
15714                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
15715             return false;
15716         }
15717 
15718         // Check parent mode to ensure we're not hidden.
15719         ViewParent parent = mParent;
15720         while (parent instanceof View) {
15721             if (((View) parent).getImportantForAccessibility()
15722                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
15723                 return false;
15724             }
15725             parent = parent.getParent();
15726         }
15727 
15728         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
15729                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
15730                 || getAccessibilityDelegate() != null
15731                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
15732                 || isAccessibilityPane() || isAccessibilityHeading();
15733     }
15734 
15735     /**
15736      * Gets the parent for accessibility purposes. Note that the parent for
15737      * accessibility is not necessary the immediate parent. It is the first
15738      * predecessor that is important for accessibility.
15739      *
15740      * @return The parent for accessibility purposes.
15741      */
15742     public ViewParent getParentForAccessibility() {
15743         if (mParent instanceof View) {
15744             View parentView = (View) mParent;
15745             if (parentView.includeForAccessibility()) {
15746                 return mParent;
15747             } else {
15748                 return mParent.getParentForAccessibility();
15749             }
15750         }
15751         return null;
15752     }
15753 
15754     /** @hide */
15755     @Nullable
15756     View getSelfOrParentImportantForA11y() {
15757         if (isImportantForAccessibility()) return this;
15758         ViewParent parent = getParentForAccessibility();
15759         if (parent instanceof View) return (View) parent;
15760         return null;
15761     }
15762 
15763     /**
15764      * Adds the children of this View relevant for accessibility to the given list
15765      * as output. Since some Views are not important for accessibility the added
15766      * child views are not necessarily direct children of this view, rather they are
15767      * the first level of descendants important for accessibility.
15768      *
15769      * @param outChildren The output list that will receive children for accessibility.
15770      */
15771     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
15772 
15773     }
15774 
15775     /**
15776      * @see #includeForAccessibility(boolean)
15777      * @hide
15778      */
15779     @UnsupportedAppUsage
15780     public boolean includeForAccessibility() {
15781         return includeForAccessibility(true);
15782     }
15783 
15784     /**
15785      * Whether to regard this view for accessibility.
15786      *
15787      * <p>
15788      * If this decision is used for generating the accessibility node tree then this returns false
15789      * for {@link #isAccessibilityDataPrivate()} views queried by non-accessibility tools.
15790      * </p>
15791      * <p>
15792      * Otherwise, a view is regarded for accessibility if:
15793      * <li>the view returns true for {@link #isImportantForAccessibility()}, or</li>
15794      * <li>the querying accessibility service has explicitly requested that views not important for
15795      * accessibility are regarded by setting
15796      * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}</li>
15797      * </p>
15798      *
15799      * @param forNodeTree True if the result of this function will be used for generating a node
15800      *                    tree, otherwise false (like when sending {@link AccessibilityEvent}s).
15801      * @return Whether to regard the view for accessibility.
15802      * @hide
15803      */
15804     public boolean includeForAccessibility(boolean forNodeTree) {
15805         if (mAttachInfo == null) {
15806             return false;
15807         }
15808 
15809         if (forNodeTree) {
15810             // The AccessibilityDataPrivate property should not effect whether this View is
15811             // included for consideration when sending AccessibilityEvents. Events copy their
15812             // source View's AccessibilityDataPrivate value, and then filtering is done when
15813             // AccessibilityManagerService propagates events to each recipient AccessibilityService.
15814             if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
15815                     && isAccessibilityDataSensitive()) {
15816                 return false;
15817             }
15818         }
15819 
15820         return (mAttachInfo.mAccessibilityFetchFlags
15821                 & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
15822                 || isImportantForAccessibility();
15823     }
15824 
15825     /**
15826      * Whether this view should restrict accessibility service access only to services that have the
15827      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
15828      * set to true.
15829      *
15830      * <p>
15831      * See default behavior provided by {@link #ACCESSIBILITY_DATA_SENSITIVE_AUTO}. Otherwise,
15832      * returns true for {@link #ACCESSIBILITY_DATA_SENSITIVE_YES} or false for {@link
15833      * #ACCESSIBILITY_DATA_SENSITIVE_NO}.
15834      * </p>
15835      *
15836      * @return True if this view should restrict accessibility service access to services that have
15837      * the isAccessibilityTool property.
15838      */
15839     @ViewDebug.ExportedProperty(category = "accessibility")
15840     public boolean isAccessibilityDataSensitive() {
15841         if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
15842             calculateAccessibilityDataSensitive();
15843         }
15844         return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
15845     }
15846 
15847     /**
15848      * Calculate and cache the inferred value for {@link #isAccessibilityDataSensitive()}.
15849      *
15850      * <p>
15851      * <strong>Note:</strong> This method needs to be called any time one of the below conditions
15852      * changes, to recalculate the new value.
15853      * </p>
15854      */
15855     void calculateAccessibilityDataSensitive() {
15856         // Use the explicit value if set.
15857         if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
15858             mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
15859         } else if (getFilterTouchesWhenObscured()) {
15860             // Views that set filterTouchesWhenObscured default to accessibilityDataSensitive.
15861             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
15862         } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
15863             // Descendants of accessibilityDataSensitive Views are also accessibilityDataSensitive.
15864             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
15865         } else {
15866             // Otherwise, default to not accessibilityDataSensitive.
15867             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
15868         }
15869     }
15870 
15871     /**
15872      * Specifies whether this view should only allow interactions from
15873      * {@link android.accessibilityservice.AccessibilityService}s with the
15874      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
15875      * set to true.
15876      */
15877     public void setAccessibilityDataSensitive(
15878             @AccessibilityDataSensitive int accessibilityDataSensitive) {
15879         mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
15880         calculateAccessibilityDataSensitive();
15881     }
15882 
15883     /**
15884      * Returns whether the View is considered actionable from
15885      * accessibility perspective. Such view are important for
15886      * accessibility.
15887      *
15888      * @return True if the view is actionable for accessibility.
15889      *
15890      * @hide
15891      */
15892     public boolean isActionableForAccessibility() {
15893         return (isClickable() || isLongClickable() || isFocusable() || isContextClickable()
15894                 || isScreenReaderFocusable());
15895     }
15896 
15897     /**
15898      * Returns whether the View has registered callbacks which makes it
15899      * important for accessibility.
15900      *
15901      * @return True if the view is actionable for accessibility.
15902      */
15903     private boolean hasListenersForAccessibility() {
15904         ListenerInfo info = getListenerInfo();
15905         return mTouchDelegate != null || info.mOnKeyListener != null
15906                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
15907                 || info.mOnHoverListener != null || info.mOnDragListener != null;
15908     }
15909 
15910     /**
15911      * Notifies that the accessibility state of this view changed. The change
15912      * is local to this view and does not represent structural changes such
15913      * as children and parent. For example, the view became focusable. Some of
15914      * the notification is at at most once every
15915      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
15916      * to avoid unnecessary load to the system. Also once a view has a pending
15917      * notification this method is a NOP until the notification has been sent.
15918      *
15919      * @hide
15920      */
15921     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
15922     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
15923         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
15924             return;
15925         }
15926 
15927         // Changes to views with a pane title count as window state changes, as the pane title
15928         // marks them as significant parts of the UI. A visible view with a nulled title may send
15929         // a disappeared event.
15930         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
15931                 && (isAccessibilityPane()
15932                 || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)
15933                 && isAggregatedVisible())) {
15934             // If the pane isn't visible, content changed events are sufficient unless we're
15935             // reporting that the view just disappeared
15936             if ((isAggregatedVisible())
15937                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
15938                 final AccessibilityEvent event = AccessibilityEvent.obtain();
15939                 onInitializeAccessibilityEvent(event);
15940                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
15941                 event.setContentChangeTypes(changeType);
15942                 event.setSource(this);
15943                 onPopulateAccessibilityEvent(event);
15944                 if (mParent != null) {
15945                     try {
15946                         mParent.requestSendAccessibilityEvent(this, event);
15947                     } catch (AbstractMethodError e) {
15948                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
15949                                 + " does not fully implement ViewParent", e);
15950                     }
15951                 }
15952                 return;
15953             }
15954         }
15955 
15956         // If this is a live region, we should send a subtree change event
15957         // from this view immediately. Otherwise, we can let it propagate up.
15958         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
15959             final AccessibilityEvent event = AccessibilityEvent.obtain();
15960             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
15961             event.setContentChangeTypes(changeType);
15962             sendAccessibilityEventUnchecked(event);
15963         } else if (mParent != null) {
15964             try {
15965                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
15966             } catch (AbstractMethodError e) {
15967                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15968                         " does not fully implement ViewParent", e);
15969             }
15970         }
15971     }
15972 
15973     /**
15974      * Notifies that the accessibility state of this view changed. The change
15975      * is *not* local to this view and does represent structural changes such
15976      * as children and parent. For example, the view size changed. Some of the
15977      * notification is at at most once every
15978      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
15979      * to avoid unnecessary load to the system. Also once a view has a pending
15980      * notification this method is a NOP until the notification has been sent.
15981      *
15982      * @hide
15983      */
15984     @UnsupportedAppUsage
15985     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
15986         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
15987             return;
15988         }
15989 
15990         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
15991             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
15992             if (mParent != null) {
15993                 try {
15994                     mParent.notifySubtreeAccessibilityStateChanged(
15995                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
15996                 } catch (AbstractMethodError e) {
15997                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15998                             " does not fully implement ViewParent", e);
15999                 }
16000             }
16001         }
16002     }
16003 
16004     private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
16005         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
16006             return;
16007         }
16008 
16009         final View sendA11yEventView = (View) getParentForAccessibility();
16010         if (sendA11yEventView != null && sendA11yEventView.isShown()) {
16011             sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
16012         }
16013     }
16014 
16015     /**
16016      * Changes the visibility of this View without triggering any other changes. This should only
16017      * be used by animation frameworks, such as {@link android.transition.Transition}, where
16018      * visibility changes should not adjust focus or trigger a new layout. Application developers
16019      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
16020      *
16021      * <p>Only call this method when a temporary visibility must be applied during an
16022      * animation and the original visibility value is guaranteed to be reset after the
16023      * animation completes. Use {@link #setVisibility} in all other cases.</p>
16024      *
16025      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
16026      * @see #setVisibility(int)
16027      */
16028     public void setTransitionVisibility(@Visibility int visibility) {
16029         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
16030     }
16031 
16032     /**
16033      * Reset the flag indicating the accessibility state of the subtree rooted
16034      * at this view changed.
16035      */
16036     void resetSubtreeAccessibilityStateChanged() {
16037         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
16038     }
16039 
16040     /**
16041      * Report an accessibility action to this view's parents for delegated processing.
16042      *
16043      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
16044      * call this method to delegate an accessibility action to a supporting parent. If the parent
16045      * returns true from its
16046      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
16047      * method this method will return true to signify that the action was consumed.</p>
16048      *
16049      * <p>This method is useful for implementing nested scrolling child views. If
16050      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
16051      * a custom view implementation may invoke this method to allow a parent to consume the
16052      * scroll first. If this method returns true the custom view should skip its own scrolling
16053      * behavior.</p>
16054      *
16055      * @param action Accessibility action to delegate
16056      * @param arguments Optional action arguments
16057      * @return true if the action was consumed by a parent
16058      */
16059     public boolean dispatchNestedPrePerformAccessibilityAction(int action,
16060             @Nullable Bundle arguments) {
16061         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
16062             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
16063                 return true;
16064             }
16065         }
16066         return false;
16067     }
16068 
16069     /**
16070      * Performs the specified accessibility action on the view. For
16071      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
16072      * <p>
16073      * If an {@link AccessibilityDelegate} has been specified via calling
16074      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
16075      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
16076      * is responsible for handling this call.
16077      * </p>
16078      *
16079      * <p>The default implementation will delegate
16080      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
16081      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
16082      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
16083      *
16084      * <p>
16085      * <b>Note:</b> Avoid setting accessibility focus with
16086      * {@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}. This is intended to be controlled
16087      * by screen readers. Apps changing focus can confuse screen readers, so the resulting behavior
16088      * can vary by device and screen reader version.
16089      *
16090      * @param action The action to perform.
16091      * @param arguments Optional action arguments.
16092      * @return Whether the action was performed.
16093      */
16094     public boolean performAccessibilityAction(int action, @Nullable Bundle arguments) {
16095       if (mAccessibilityDelegate != null) {
16096           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
16097       } else {
16098           return performAccessibilityActionInternal(action, arguments);
16099       }
16100     }
16101 
16102     /**
16103      * @see #performAccessibilityAction(int, Bundle)
16104      *
16105      * Note: Called from the default {@link AccessibilityDelegate}.
16106      *
16107      * @hide
16108      */
16109     @UnsupportedAppUsage
16110     public boolean performAccessibilityActionInternal(int action, @Nullable Bundle arguments) {
16111         if (isNestedScrollingEnabled()
16112                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
16113                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
16114                 || action == R.id.accessibilityActionScrollUp
16115                 || action == R.id.accessibilityActionScrollLeft
16116                 || action == R.id.accessibilityActionScrollDown
16117                 || action == R.id.accessibilityActionScrollRight)) {
16118             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
16119                 return true;
16120             }
16121         }
16122 
16123         switch (action) {
16124             case AccessibilityNodeInfo.ACTION_CLICK: {
16125                 if (isClickable()) {
16126                     performClickInternal();
16127                     return true;
16128                 }
16129             } break;
16130             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
16131                 if (isLongClickable()) {
16132                     performLongClick();
16133                     return true;
16134                 }
16135             } break;
16136             case AccessibilityNodeInfo.ACTION_FOCUS: {
16137                 if (!hasFocus()) {
16138                     // Get out of touch mode since accessibility
16139                     // wants to move focus around.
16140                     getViewRootImpl().ensureTouchMode(false);
16141                     return requestFocus();
16142                 }
16143             } break;
16144             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
16145                 if (hasFocus()) {
16146                     clearFocus();
16147                     return !isFocused();
16148                 }
16149             } break;
16150             case AccessibilityNodeInfo.ACTION_SELECT: {
16151                 if (!isSelected()) {
16152                     setSelected(true);
16153                     return isSelected();
16154                 }
16155             } break;
16156             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
16157                 if (isSelected()) {
16158                     setSelected(false);
16159                     return !isSelected();
16160                 }
16161             } break;
16162             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
16163                 if (!isAccessibilityFocused()) {
16164                     return requestAccessibilityFocus();
16165                 }
16166             } break;
16167             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
16168                 if (isAccessibilityFocused()) {
16169                     clearAccessibilityFocus();
16170                     return true;
16171                 }
16172             } break;
16173             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
16174                 if (arguments != null) {
16175                     final int granularity = arguments.getInt(
16176                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
16177                     final boolean extendSelection = arguments.getBoolean(
16178                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
16179                     return traverseAtGranularity(granularity, true, extendSelection);
16180                 }
16181             } break;
16182             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
16183                 if (arguments != null) {
16184                     final int granularity = arguments.getInt(
16185                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
16186                     final boolean extendSelection = arguments.getBoolean(
16187                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
16188                     return traverseAtGranularity(granularity, false, extendSelection);
16189                 }
16190             } break;
16191             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
16192                 CharSequence text = getIterableTextForAccessibility();
16193                 if (text == null) {
16194                     return false;
16195                 }
16196                 final int start = (arguments != null) ? arguments.getInt(
16197                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
16198                 final int end = (arguments != null) ? arguments.getInt(
16199                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
16200                 // Only cursor position can be specified (selection length == 0)
16201                 if ((getAccessibilitySelectionStart() != start
16202                         || getAccessibilitySelectionEnd() != end)
16203                         && (start == end)) {
16204                     setAccessibilitySelection(start, end);
16205                     notifyViewAccessibilityStateChangedIfNeeded(
16206                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16207                     return true;
16208                 }
16209             } break;
16210             case R.id.accessibilityActionShowOnScreen: {
16211                 if (mAttachInfo != null) {
16212                     final Rect r = mAttachInfo.mTmpInvalRect;
16213                     getDrawingRect(r);
16214                     return requestRectangleOnScreen(r, true);
16215                 }
16216             } break;
16217             case R.id.accessibilityActionContextClick: {
16218                 if (isContextClickable()) {
16219                     performContextClick();
16220                     return true;
16221                 }
16222             } break;
16223             case R.id.accessibilityActionShowTooltip: {
16224                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
16225                     // Tooltip already showing
16226                     return false;
16227                 }
16228                 return showLongClickTooltip(0, 0);
16229             }
16230             case R.id.accessibilityActionHideTooltip: {
16231                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
16232                     // No tooltip showing
16233                     return false;
16234                 }
16235                 hideTooltip();
16236                 return true;
16237             }
16238             case R.id.accessibilityActionDragDrop: {
16239                 if (!canAcceptAccessibilityDrop()) {
16240                     return false;
16241                 }
16242                 try {
16243                     if (mAttachInfo != null && mAttachInfo.mSession != null) {
16244                         final int[] location = new int[2];
16245                         getLocationInWindow(location);
16246                         final int centerX = location[0] + getWidth() / 2;
16247                         final int centerY = location[1] + getHeight() / 2;
16248                         return mAttachInfo.mSession.dropForAccessibility(mAttachInfo.mWindow,
16249                                 centerX, centerY);
16250                     }
16251                 } catch (RemoteException e) {
16252                     Log.e(VIEW_LOG_TAG, "Unable to drop for accessibility", e);
16253                 }
16254                 return false;
16255             }
16256             case R.id.accessibilityActionDragCancel: {
16257                 if (!startedSystemDragForAccessibility()) {
16258                     return false;
16259                 }
16260                 if (mAttachInfo != null && mAttachInfo.mDragToken != null) {
16261                     cancelDragAndDrop();
16262                     return true;
16263                 }
16264                 return false;
16265             }
16266         }
16267         return false;
16268     }
16269 
16270     private boolean canAcceptAccessibilityDrop() {
16271         if (!canAcceptDrag()) {
16272             return false;
16273         }
16274         ListenerInfo li = mListenerInfo;
16275         return (li != null) && (li.mOnDragListener != null || li.mOnReceiveContentListener != null);
16276     }
16277 
16278     private boolean traverseAtGranularity(int granularity, boolean forward,
16279             boolean extendSelection) {
16280         CharSequence text = getIterableTextForAccessibility();
16281         if (text == null || text.length() == 0) {
16282             return false;
16283         }
16284         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
16285         if (iterator == null) {
16286             return false;
16287         }
16288         int current = getAccessibilitySelectionEnd();
16289         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
16290             current = forward ? 0 : text.length();
16291         }
16292         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
16293         if (range == null) {
16294             return false;
16295         }
16296         final int segmentStart = range[0];
16297         final int segmentEnd = range[1];
16298         int selectionStart;
16299         int selectionEnd;
16300         if (extendSelection && isAccessibilitySelectionExtendable()) {
16301             prepareForExtendedAccessibilitySelection();
16302             selectionStart = getAccessibilitySelectionStart();
16303             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
16304                 selectionStart = forward ? segmentStart : segmentEnd;
16305             }
16306             selectionEnd = forward ? segmentEnd : segmentStart;
16307         } else {
16308             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
16309         }
16310         setAccessibilitySelection(selectionStart, selectionEnd);
16311         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
16312                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
16313         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
16314         return true;
16315     }
16316 
16317     /**
16318      * Gets the text reported for accessibility purposes.
16319      *
16320      * @return The accessibility text.
16321      *
16322      * @hide
16323      */
16324     @UnsupportedAppUsage
16325     public CharSequence getIterableTextForAccessibility() {
16326         return getContentDescription();
16327     }
16328 
16329     /**
16330      * Gets whether accessibility selection can be extended.
16331      *
16332      * @return If selection is extensible.
16333      *
16334      * @hide
16335      */
16336     public boolean isAccessibilitySelectionExtendable() {
16337         return false;
16338     }
16339 
16340     /**
16341      * Prepare for extended selection.
16342      * @hide
16343      */
16344     public void prepareForExtendedAccessibilitySelection() {
16345         return;
16346     }
16347 
16348     /**
16349      * @hide
16350      */
16351     public int getAccessibilitySelectionStart() {
16352         return mAccessibilityCursorPosition;
16353     }
16354 
16355     /**
16356      * @hide
16357      */
16358     public int getAccessibilitySelectionEnd() {
16359         return getAccessibilitySelectionStart();
16360     }
16361 
16362     /**
16363      * @hide
16364      */
16365     public void setAccessibilitySelection(int start, int end) {
16366         if (start ==  end && end == mAccessibilityCursorPosition) {
16367             return;
16368         }
16369         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
16370             mAccessibilityCursorPosition = start;
16371         } else {
16372             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
16373         }
16374         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
16375     }
16376 
16377     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
16378             int fromIndex, int toIndex) {
16379         if (mParent == null) {
16380             return;
16381         }
16382         AccessibilityEvent event = AccessibilityEvent.obtain(
16383                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
16384         onInitializeAccessibilityEvent(event);
16385         onPopulateAccessibilityEvent(event);
16386         event.setFromIndex(fromIndex);
16387         event.setToIndex(toIndex);
16388         event.setAction(action);
16389         event.setMovementGranularity(granularity);
16390         mParent.requestSendAccessibilityEvent(this, event);
16391     }
16392 
16393     /**
16394      * @hide
16395      */
16396     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
16397     public TextSegmentIterator getIteratorForGranularity(int granularity) {
16398         switch (granularity) {
16399             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
16400                 CharSequence text = getIterableTextForAccessibility();
16401                 if (text != null && text.length() > 0) {
16402                     CharacterTextSegmentIterator iterator =
16403                         CharacterTextSegmentIterator.getInstance(
16404                                 mContext.getResources().getConfiguration().locale);
16405                     iterator.initialize(text.toString());
16406                     return iterator;
16407                 }
16408             } break;
16409             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
16410                 CharSequence text = getIterableTextForAccessibility();
16411                 if (text != null && text.length() > 0) {
16412                     WordTextSegmentIterator iterator =
16413                         WordTextSegmentIterator.getInstance(
16414                                 mContext.getResources().getConfiguration().locale);
16415                     iterator.initialize(text.toString());
16416                     return iterator;
16417                 }
16418             } break;
16419             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
16420                 CharSequence text = getIterableTextForAccessibility();
16421                 if (text != null && text.length() > 0) {
16422                     ParagraphTextSegmentIterator iterator =
16423                         ParagraphTextSegmentIterator.getInstance();
16424                     iterator.initialize(text.toString());
16425                     return iterator;
16426                 }
16427             } break;
16428         }
16429         return null;
16430     }
16431 
16432     /**
16433      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
16434      * and {@link #onFinishTemporaryDetach()}.
16435      *
16436      * <p>This method always returns {@code true} when called directly or indirectly from
16437      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
16438      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
16439      * <ul>
16440      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
16441      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
16442      * </ul>
16443      * </p>
16444      *
16445      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
16446      * and {@link #onFinishTemporaryDetach()}.
16447      */
isTemporarilyDetached()16448     public final boolean isTemporarilyDetached() {
16449         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
16450     }
16451 
16452     /**
16453      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
16454      * a container View.
16455      */
16456     @CallSuper
dispatchStartTemporaryDetach()16457     public void dispatchStartTemporaryDetach() {
16458         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
16459         notifyEnterOrExitForAutoFillIfNeeded(false);
16460         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
16461         onStartTemporaryDetach();
16462     }
16463 
16464     /**
16465      * This is called when a container is going to temporarily detach a child, with
16466      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
16467      * It will either be followed by {@link #onFinishTemporaryDetach()} or
16468      * {@link #onDetachedFromWindow()} when the container is done.
16469      */
onStartTemporaryDetach()16470     public void onStartTemporaryDetach() {
16471         removeUnsetPressCallback();
16472         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
16473     }
16474 
16475     /**
16476      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
16477      * a container View.
16478      */
16479     @CallSuper
dispatchFinishTemporaryDetach()16480     public void dispatchFinishTemporaryDetach() {
16481         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16482         onFinishTemporaryDetach();
16483         if (hasWindowFocus() && hasFocus()) {
16484             notifyFocusChangeToImeFocusController(true /* hasFocus */);
16485         }
16486         notifyEnterOrExitForAutoFillIfNeeded(true);
16487         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
16488     }
16489 
16490     /**
16491      * Called after {@link #onStartTemporaryDetach} when the container is done
16492      * changing the view.
16493      */
onFinishTemporaryDetach()16494     public void onFinishTemporaryDetach() {
16495     }
16496 
16497     /**
16498      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
16499      * for this view's window.  Returns null if the view is not currently attached
16500      * to the window.  Normally you will not need to use this directly, but
16501      * just use the standard high-level event callbacks like
16502      * {@link #onKeyDown(int, KeyEvent)}.
16503      */
getKeyDispatcherState()16504     public KeyEvent.DispatcherState getKeyDispatcherState() {
16505         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
16506     }
16507 
16508     /**
16509      * Dispatch a key event before it is processed by any input method
16510      * associated with the view hierarchy.  This can be used to intercept
16511      * key events in special situations before the IME consumes them; a
16512      * typical example would be handling the BACK key to update the application's
16513      * UI instead of allowing the IME to see it and close itself.
16514      *
16515      * @param event The key event to be dispatched.
16516      * @return True if the event was handled, false otherwise.
16517      */
dispatchKeyEventPreIme(KeyEvent event)16518     public boolean dispatchKeyEventPreIme(KeyEvent event) {
16519         return onKeyPreIme(event.getKeyCode(), event);
16520     }
16521 
16522     /**
16523      * Dispatch a key event to the next view on the focus path. This path runs
16524      * from the top of the view tree down to the currently focused view. If this
16525      * view has focus, it will dispatch to itself. Otherwise it will dispatch
16526      * the next node down the focus path. This method also fires any key
16527      * listeners.
16528      *
16529      * @param event The key event to be dispatched.
16530      * @return True if the event was handled, false otherwise.
16531      */
dispatchKeyEvent(KeyEvent event)16532     public boolean dispatchKeyEvent(KeyEvent event) {
16533         if (mInputEventConsistencyVerifier != null) {
16534             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
16535         }
16536 
16537         // Give any attached key listener a first crack at the event.
16538         //noinspection SimplifiableIfStatement
16539         ListenerInfo li = mListenerInfo;
16540         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16541                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
16542             return true;
16543         }
16544 
16545         if (event.dispatch(this, mAttachInfo != null
16546                 ? mAttachInfo.mKeyDispatchState : null, this)) {
16547             return true;
16548         }
16549 
16550         if (mInputEventConsistencyVerifier != null) {
16551             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16552         }
16553         return false;
16554     }
16555 
16556     /**
16557      * Dispatches a key shortcut event.
16558      *
16559      * @param event The key event to be dispatched.
16560      * @return True if the event was handled by the view, false otherwise.
16561      */
dispatchKeyShortcutEvent(KeyEvent event)16562     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
16563         return onKeyShortcut(event.getKeyCode(), event);
16564     }
16565 
16566     /**
16567      * Pass the touch screen motion event down to the target view, or this
16568      * view if it is the target.
16569      *
16570      * @param event The motion event to be dispatched.
16571      * @return True if the event was handled by the view, false otherwise.
16572      *
16573      * @see #onTouchEvent(MotionEvent)
16574      */
dispatchTouchEvent(MotionEvent event)16575     public boolean dispatchTouchEvent(MotionEvent event) {
16576         // If the event should be handled by accessibility focus first.
16577         if (event.isTargetAccessibilityFocus()) {
16578             // We don't have focus or no virtual descendant has it, do not handle the event.
16579             if (!isAccessibilityFocusedViewOrHost()) {
16580                 return false;
16581             }
16582             // We have focus and got the event, then use normal event dispatch.
16583             event.setTargetAccessibilityFocus(false);
16584         }
16585         boolean result = false;
16586 
16587         if (mInputEventConsistencyVerifier != null) {
16588             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
16589         }
16590 
16591         final int actionMasked = event.getActionMasked();
16592         if (actionMasked == MotionEvent.ACTION_DOWN) {
16593             // Defensive cleanup for new gesture
16594             stopNestedScroll();
16595         }
16596 
16597         if (onFilterTouchEventForSecurity(event)) {
16598             result = performOnTouchCallback(event);
16599         }
16600 
16601         if (!result && mInputEventConsistencyVerifier != null) {
16602             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16603         }
16604 
16605         // Clean up after nested scrolls if this is the end of a gesture;
16606         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
16607         // of the gesture.
16608         if (actionMasked == MotionEvent.ACTION_UP ||
16609                 actionMasked == MotionEvent.ACTION_CANCEL ||
16610                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
16611             stopNestedScroll();
16612         }
16613 
16614         return result;
16615     }
16616 
16617     /**
16618      * Returns {@code true} if the {@link MotionEvent} from {@link #dispatchTouchEvent} was
16619      * handled by this view.
16620      */
performOnTouchCallback(MotionEvent event)16621     private boolean performOnTouchCallback(MotionEvent event) {
16622         boolean handled = false;
16623         if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
16624             handled = true;
16625         }
16626         //noinspection SimplifiableIfStatement
16627         ListenerInfo li = mListenerInfo;
16628         if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED) {
16629             try {
16630                 if (Trace.isTagEnabled(TRACE_TAG_VIEW)) {
16631                     Trace.traceBegin(TRACE_TAG_VIEW,
16632                             "View.onTouchListener#onTouch - " + getClass().getSimpleName()
16633                                     + ", eventId - " + event.getId());
16634                 }
16635                 handled = li.mOnTouchListener.onTouch(this, event);
16636             } finally {
16637                 Trace.traceEnd(TRACE_TAG_VIEW);
16638             }
16639         }
16640         if (handled) {
16641             return true;
16642         }
16643         try {
16644             Trace.traceBegin(TRACE_TAG_VIEW, "View#onTouchEvent");
16645             return onTouchEvent(event);
16646         } finally {
16647             Trace.traceEnd(TRACE_TAG_VIEW);
16648         }
16649     }
16650 
isAccessibilityFocusedViewOrHost()16651     boolean isAccessibilityFocusedViewOrHost() {
16652         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
16653                 .getAccessibilityFocusedHost() == this);
16654     }
16655 
16656     /**
16657      * Returns whether this view can receive pointer events.
16658      *
16659      * @return {@code true} if this view can receive pointer events.
16660      * @hide
16661      */
canReceivePointerEvents()16662     protected boolean canReceivePointerEvents() {
16663         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
16664     }
16665 
16666     /**
16667      * Filter the touch event to apply security policies.
16668      *
16669      * @param event The motion event to be filtered.
16670      * @return True if the event should be dispatched, false if the event should be dropped.
16671      *
16672      * @see #getFilterTouchesWhenObscured
16673      */
onFilterTouchEventForSecurity(MotionEvent event)16674     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
16675         //noinspection RedundantIfStatement
16676         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
16677                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
16678             // Window is obscured, drop this touch.
16679             return false;
16680         }
16681         if (android.view.accessibility.Flags.preventA11yNontoolFromInjectingIntoSensitiveViews()) {
16682             if (event.isInjectedFromAccessibilityService()
16683                     // If the event came from an Accessibility Service that does *not* declare
16684                     // itself as AccessibilityServiceInfo#isAccessibilityTool and this View is
16685                     // declared sensitive then drop the event.
16686                     // Only Accessibility Tools are allowed to interact with sensitive Views.
16687                     && !event.isInjectedFromAccessibilityTool() && isAccessibilityDataSensitive()) {
16688                 return false;
16689             }
16690         }
16691         return true;
16692     }
16693 
16694     /**
16695      * Pass a trackball motion event down to the focused view.
16696      *
16697      * @param event The motion event to be dispatched.
16698      * @return True if the event was handled by the view, false otherwise.
16699      *
16700      * @see #onTrackballEvent(MotionEvent)
16701      */
dispatchTrackballEvent(MotionEvent event)16702     public boolean dispatchTrackballEvent(MotionEvent event) {
16703         if (mInputEventConsistencyVerifier != null) {
16704             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
16705         }
16706 
16707         return onTrackballEvent(event);
16708     }
16709 
16710     /**
16711      * Pass a captured pointer event down to the focused view.
16712      *
16713      * @param event The motion event to be dispatched.
16714      * @return True if the event was handled by the view, false otherwise.
16715      */
dispatchCapturedPointerEvent(MotionEvent event)16716     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
16717         if (!hasPointerCapture()) {
16718             return false;
16719         }
16720         //noinspection SimplifiableIfStatement
16721         ListenerInfo li = mListenerInfo;
16722         if (li != null && li.mOnCapturedPointerListener != null
16723                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
16724             return true;
16725         }
16726         return onCapturedPointerEvent(event);
16727     }
16728 
16729     /**
16730      * Dispatch a generic motion event.
16731      * <p>
16732      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
16733      * are delivered to the view under the pointer.  All other generic motion events are
16734      * delivered to the focused view.  Hover events are handled specially and are delivered
16735      * to {@link #onHoverEvent(MotionEvent)} first.
16736      * </p>
16737      *
16738      * @param event The motion event to be dispatched.
16739      * @return True if the event was handled by the view, false otherwise.
16740      *
16741      * @see #onHoverEvent(MotionEvent)
16742      * @see #onGenericMotionEvent(MotionEvent)
16743      */
dispatchGenericMotionEvent(MotionEvent event)16744     public boolean dispatchGenericMotionEvent(MotionEvent event) {
16745         if (mInputEventConsistencyVerifier != null) {
16746             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
16747         }
16748 
16749         final int source = event.getSource();
16750         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
16751             final int action = event.getAction();
16752             if (action == MotionEvent.ACTION_HOVER_ENTER
16753                     || action == MotionEvent.ACTION_HOVER_MOVE
16754                     || action == MotionEvent.ACTION_HOVER_EXIT) {
16755                 if (dispatchHoverEvent(event)) {
16756                     return true;
16757                 }
16758             } else if (dispatchGenericPointerEvent(event)) {
16759                 return true;
16760             }
16761         } else if (dispatchGenericFocusedEvent(event)) {
16762             return true;
16763         }
16764 
16765         if (dispatchGenericMotionEventInternal(event)) {
16766             return true;
16767         }
16768 
16769         if (mInputEventConsistencyVerifier != null) {
16770             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16771         }
16772         return false;
16773     }
16774 
dispatchGenericMotionEventInternal(MotionEvent event)16775     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
16776         final boolean isRotaryEncoderEvent = event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER);
16777         if (isRotaryEncoderEvent) {
16778             // Determine and cache rotary scroll haptics support if it's not yet determined.
16779             // Caching the support is important for two reasons:
16780             // 1) Limits call to `ViewConfiguration#get`, which we should avoid if possible.
16781             // 2) Limits latency from the `ViewConfiguration` API, which may be slow due to feature
16782             //    flag querying.
16783             if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_DETERMINED) == 0) {
16784                 if (ViewConfiguration.get(mContext)
16785                         .isViewBasedRotaryEncoderHapticScrollFeedbackEnabled()) {
16786                     mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_ENABLED;
16787                 }
16788                 mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_DETERMINED;
16789             }
16790         }
16791         if (isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0)) {
16792             mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
16793             mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
16794         }
16795 
16796         //noinspection SimplifiableIfStatement
16797         ListenerInfo li = mListenerInfo;
16798         if (li != null && li.mOnGenericMotionListener != null
16799                 && (mViewFlags & ENABLED_MASK) == ENABLED
16800                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
16801             return true;
16802         }
16803 
16804         final boolean onGenericMotionEventResult = onGenericMotionEvent(event);
16805         // Process scroll haptics after `onGenericMotionEvent`, since that's where scrolling usually
16806         // happens. Some views may return false from `onGenericMotionEvent` even if they have done
16807         // scrolling, so disregard the return value when processing for scroll haptics.
16808         // Check for `PFLAG4_ROTARY_HAPTICS_ENABLED` again, because the View implementation may
16809         // call `disableRotaryScrollFeedback` in `onGenericMotionEvent`, which could change the
16810         // value of `PFLAG4_ROTARY_HAPTICS_ENABLED`.
16811         if (isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0)) {
16812             if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT) != 0) {
16813                 doRotaryProgressForScrollHaptics(event);
16814             } else {
16815                 doRotaryLimitForScrollHaptics(event);
16816             }
16817         }
16818         if (onGenericMotionEventResult) {
16819             return true;
16820         }
16821 
16822         final int actionButton = event.getActionButton();
16823         switch (event.getActionMasked()) {
16824             case MotionEvent.ACTION_BUTTON_PRESS:
16825                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
16826                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
16827                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
16828                     if (performContextClick(event.getX(), event.getY())) {
16829                         mInContextButtonPress = true;
16830                         setPressed(true, event.getX(), event.getY());
16831                         removeTapCallback();
16832                         removeLongPressCallback();
16833                         return true;
16834                     }
16835                 }
16836                 break;
16837 
16838             case MotionEvent.ACTION_BUTTON_RELEASE:
16839                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
16840                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
16841                     mInContextButtonPress = false;
16842                     mIgnoreNextUpEvent = true;
16843                 }
16844                 break;
16845         }
16846 
16847         if (mInputEventConsistencyVerifier != null) {
16848             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
16849         }
16850         return false;
16851     }
16852 
16853     /**
16854      * Dispatch a hover event.
16855      * <p>
16856      * Do not call this method directly.
16857      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
16858      * </p>
16859      *
16860      * @param event The motion event to be dispatched.
16861      * @return True if the event was handled by the view, false otherwise.
16862      */
dispatchHoverEvent(MotionEvent event)16863     protected boolean dispatchHoverEvent(MotionEvent event) {
16864         ListenerInfo li = mListenerInfo;
16865         //noinspection SimplifiableIfStatement
16866         if (li != null && li.mOnHoverListener != null
16867                 && (mViewFlags & ENABLED_MASK) == ENABLED
16868                 && li.mOnHoverListener.onHover(this, event)) {
16869             return true;
16870         }
16871 
16872         return onHoverEvent(event);
16873     }
16874 
16875     /**
16876      * Returns true if the view has a child to which it has recently sent
16877      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
16878      * it does not have a hovered child, then it must be the innermost hovered view.
16879      * @hide
16880      */
hasHoveredChild()16881     protected boolean hasHoveredChild() {
16882         return false;
16883     }
16884 
16885     /**
16886      * Returns true if the given point, in local coordinates, is inside the hovered child.
16887      *
16888      * @hide
16889      */
pointInHoveredChild(MotionEvent event)16890     protected boolean pointInHoveredChild(MotionEvent event) {
16891         return false;
16892     }
16893 
16894     /**
16895      * Dispatch a generic motion event to the view under the first pointer.
16896      * <p>
16897      * Do not call this method directly.
16898      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
16899      * </p>
16900      *
16901      * @param event The motion event to be dispatched.
16902      * @return True if the event was handled by the view, false otherwise.
16903      */
dispatchGenericPointerEvent(MotionEvent event)16904     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
16905         return false;
16906     }
16907 
16908     /**
16909      * Dispatch a generic motion event to the currently focused view.
16910      * <p>
16911      * Do not call this method directly.
16912      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
16913      * </p>
16914      *
16915      * @param event The motion event to be dispatched.
16916      * @return True if the event was handled by the view, false otherwise.
16917      */
dispatchGenericFocusedEvent(MotionEvent event)16918     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
16919         return false;
16920     }
16921 
16922     /**
16923      * Dispatch a pointer event.
16924      * <p>
16925      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
16926      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
16927      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
16928      * and should not be expected to handle other pointing device features.
16929      * </p>
16930      *
16931      * @param event The motion event to be dispatched.
16932      * @return True if the event was handled by the view, false otherwise.
16933      * @hide
16934      */
16935     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchPointerEvent(MotionEvent event)16936     public final boolean dispatchPointerEvent(MotionEvent event) {
16937         if (event.isTouchEvent()) {
16938             return dispatchTouchEvent(event);
16939         } else {
16940             return dispatchGenericMotionEvent(event);
16941         }
16942     }
16943 
16944     /**
16945      * Called when the window containing this view gains or loses window focus.
16946      * ViewGroups should override to route to their children.
16947      *
16948      * @param hasFocus True if the window containing this view now has focus,
16949      *        false otherwise.
16950      */
dispatchWindowFocusChanged(boolean hasFocus)16951     public void dispatchWindowFocusChanged(boolean hasFocus) {
16952         onWindowFocusChanged(hasFocus);
16953     }
16954 
16955     /**
16956      * Called when the window containing this view gains or loses focus.  Note
16957      * that this is separate from view focus: to receive key events, both
16958      * your view and its window must have focus.  If a window is displayed
16959      * on top of yours that takes input focus, then your own window will lose
16960      * focus but the view focus will remain unchanged.
16961      *
16962      * @param hasWindowFocus True if the window containing this view now has
16963      *        focus, false otherwise.
16964      */
onWindowFocusChanged(boolean hasWindowFocus)16965     public void onWindowFocusChanged(boolean hasWindowFocus) {
16966         if (!hasWindowFocus) {
16967             if (isPressed()) {
16968                 setPressed(false);
16969             }
16970             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
16971             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
16972                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
16973             }
16974             removeLongPressCallback();
16975             removeTapCallback();
16976             onFocusLost();
16977         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
16978             notifyFocusChangeToImeFocusController(true /* hasFocus */);
16979             ViewRootImpl viewRoot = getViewRootImpl();
16980             if (viewRoot != null && initiationWithoutInputConnection() && onCheckIsTextEditor()) {
16981                 viewRoot.getHandwritingInitiator().onEditorFocused(this);
16982             }
16983         }
16984 
16985         refreshDrawableState();
16986     }
16987 
16988     /**
16989      * Returns true if this view is in a window that currently has window focus.
16990      * Note that this is not the same as the view itself having focus.
16991      *
16992      * @return True if this view is in a window that currently has window focus.
16993      */
hasWindowFocus()16994     public boolean hasWindowFocus() {
16995         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
16996     }
16997 
16998     /**
16999      * @return {@code true} if this view is in a window that currently has IME focusable state.
17000      * @hide
17001      */
hasImeFocus()17002     public boolean hasImeFocus() {
17003         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
17004     }
17005 
17006     /**
17007      * Dispatch a view visibility change down the view hierarchy.
17008      * ViewGroups should override to route to their children.
17009      * @param changedView The view whose visibility changed. Could be 'this' or
17010      * an ancestor view.
17011      * @param visibility The new visibility of changedView: {@link #VISIBLE},
17012      * {@link #INVISIBLE} or {@link #GONE}.
17013      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)17014     protected void dispatchVisibilityChanged(@NonNull View changedView,
17015             @Visibility int visibility) {
17016         onVisibilityChanged(changedView, visibility);
17017     }
17018 
17019     /**
17020      * Called when the visibility of the view or an ancestor of the view has
17021      * changed.
17022      *
17023      * @param changedView The view whose visibility changed. May be
17024      *                    {@code this} or an ancestor view.
17025      * @param visibility The new visibility, one of {@link #VISIBLE},
17026      *                   {@link #INVISIBLE} or {@link #GONE}.
17027      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)17028     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
17029     }
17030 
17031     /**
17032      * Dispatch a hint about whether this view is displayed. For instance, when
17033      * a View moves out of the screen, it might receives a display hint indicating
17034      * the view is not displayed. Applications should not <em>rely</em> on this hint
17035      * as there is no guarantee that they will receive one.
17036      *
17037      * @param hint A hint about whether or not this view is displayed:
17038      * {@link #VISIBLE} or {@link #INVISIBLE}.
17039      */
dispatchDisplayHint(@isibility int hint)17040     public void dispatchDisplayHint(@Visibility int hint) {
17041         onDisplayHint(hint);
17042     }
17043 
17044     /**
17045      * Gives this view a hint about whether is displayed or not. For instance, when
17046      * a View moves out of the screen, it might receives a display hint indicating
17047      * the view is not displayed. Applications should not <em>rely</em> on this hint
17048      * as there is no guarantee that they will receive one.
17049      *
17050      * @param hint A hint about whether or not this view is displayed:
17051      * {@link #VISIBLE} or {@link #INVISIBLE}.
17052      */
onDisplayHint(@isibility int hint)17053     protected void onDisplayHint(@Visibility int hint) {
17054     }
17055 
17056     /**
17057      * Dispatch a window visibility change down the view hierarchy.
17058      * ViewGroups should override to route to their children.
17059      *
17060      * @param visibility The new visibility of the window.
17061      *
17062      * @see #onWindowVisibilityChanged(int)
17063      */
dispatchWindowVisibilityChanged(@isibility int visibility)17064     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
17065         onWindowVisibilityChanged(visibility);
17066     }
17067 
17068     /**
17069      * Called when the window containing has change its visibility
17070      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
17071      * that this tells you whether or not your window is being made visible
17072      * to the window manager; this does <em>not</em> tell you whether or not
17073      * your window is obscured by other windows on the screen, even if it
17074      * is itself visible.
17075      *
17076      * @param visibility The new visibility of the window.
17077      */
onWindowVisibilityChanged(@isibility int visibility)17078     protected void onWindowVisibilityChanged(@Visibility int visibility) {
17079         if (visibility == VISIBLE) {
17080             initialAwakenScrollBars();
17081         }
17082     }
17083 
17084     /**
17085      * @return true if this view and all ancestors are visible as of the last
17086      * {@link #onVisibilityAggregated(boolean)} call.
17087      *
17088      * @hide
17089      */
isAggregatedVisible()17090     public boolean isAggregatedVisible() {
17091         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
17092     }
17093 
17094     /**
17095      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
17096      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
17097      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
17098      *
17099      * @param isVisible true if this view's visibility to the user is uninterrupted by its
17100      *                  ancestors or by window visibility
17101      * @return true if this view is visible to the user, not counting clipping or overlapping
17102      */
dispatchVisibilityAggregated(boolean isVisible)17103     boolean dispatchVisibilityAggregated(boolean isVisible) {
17104         final boolean thisVisible = getVisibility() == VISIBLE;
17105         // If we're not visible but something is telling us we are, ignore it.
17106         if (thisVisible || !isVisible) {
17107             onVisibilityAggregated(isVisible);
17108         }
17109         return thisVisible && isVisible;
17110     }
17111 
17112     /**
17113      * Called when the user-visibility of this View is potentially affected by a change
17114      * to this view itself, an ancestor view or the window this view is attached to.
17115      *
17116      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
17117      *                  and this view's window is also visible
17118      */
17119     @CallSuper
onVisibilityAggregated(boolean isVisible)17120     public void onVisibilityAggregated(boolean isVisible) {
17121         // Update our internal visibility tracking so we can detect changes
17122         boolean oldVisible = isAggregatedVisible();
17123         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
17124                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
17125         if (isVisible && mAttachInfo != null) {
17126             initialAwakenScrollBars();
17127         }
17128 
17129         final Drawable dr = mBackground;
17130         if (dr != null && isVisible != dr.isVisible()) {
17131             dr.setVisible(isVisible, false);
17132         }
17133         final Drawable hl = mDefaultFocusHighlight;
17134         if (hl != null && isVisible != hl.isVisible()) {
17135             hl.setVisible(isVisible, false);
17136         }
17137         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17138         if (fg != null && isVisible != fg.isVisible()) {
17139             fg.setVisible(isVisible, false);
17140         }
17141         notifyAutofillManagerViewVisibilityChanged(isVisible);
17142         if (isVisible != oldVisible) {
17143             if (isAccessibilityPane()) {
17144                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
17145                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
17146                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
17147             }
17148 
17149             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
17150             updateSensitiveViewsCountIfNeeded(isVisible);
17151 
17152             if (!getSystemGestureExclusionRects().isEmpty()) {
17153                 postUpdate(this::updateSystemGestureExclusionRects);
17154             }
17155 
17156             if (!collectPreferKeepClearRects().isEmpty()) {
17157                 postUpdate(this::updateKeepClearRects);
17158             }
17159         }
17160     }
17161 
notifyAutofillManagerViewVisibilityChanged(boolean isVisible)17162     private void notifyAutofillManagerViewVisibilityChanged(boolean isVisible) {
17163         if (isAutofillable()) {
17164             AutofillManager afm = getAutofillManager();
17165 
17166             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
17167                 if (mVisibilityChangeForAutofillHandler != null) {
17168                     mVisibilityChangeForAutofillHandler.removeMessages(0);
17169                 }
17170 
17171                 // If the view is in the background but still part of the hierarchy this is called
17172                 // with isVisible=false. Hence visibility==false requires further checks
17173                 if (isVisible) {
17174                     afm.notifyViewVisibilityChanged(this, true);
17175                 } else {
17176                     if (mVisibilityChangeForAutofillHandler == null) {
17177                         mVisibilityChangeForAutofillHandler =
17178                                 new VisibilityChangeForAutofillHandler(afm, this);
17179                     }
17180                     // Let current operation (e.g. removal of the view from the hierarchy)
17181                     // finish before checking state
17182                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
17183                 }
17184             }
17185         }
17186     }
17187 
17188     /**
17189      * Returns the current visibility of the window this view is attached to
17190      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
17191      *
17192      * @return Returns the current visibility of the view's window.
17193      */
17194     @Visibility
getWindowVisibility()17195     public int getWindowVisibility() {
17196         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
17197     }
17198 
17199     /**
17200      * Retrieve the overall visible display size in which the window this view is
17201      * attached to has been positioned in.  This takes into account screen
17202      * decorations above the window, for both cases where the window itself
17203      * is being position inside of them or the window is being placed under
17204      * then and covered insets are used for the window to position its content
17205      * inside.  In effect, this tells you the available area where content can
17206      * be placed and remain visible to users.
17207      *
17208      * @param outRect Filled in with the visible display frame.  If the view
17209      * is not attached to a window, this is simply the raw display size.
17210      */
getWindowVisibleDisplayFrame(Rect outRect)17211     public void getWindowVisibleDisplayFrame(Rect outRect) {
17212         if (mAttachInfo != null) {
17213             mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
17214             return;
17215         }
17216         // TODO (b/327559224): Refine the behavior to better reflect the window environment with API
17217         //  doc updates.
17218         final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
17219         final WindowMetrics metrics = windowManager.getMaximumWindowMetrics();
17220         final Insets insets = metrics.getWindowInsets().getInsets(
17221                 WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
17222         outRect.set(metrics.getBounds());
17223         outRect.inset(insets);
17224         outRect.offsetTo(0, 0);
17225     }
17226 
17227     /**
17228      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
17229      * is currently in without any insets.
17230      *
17231      * @hide
17232      */
17233     @UnsupportedAppUsage
17234     @TestApi
getWindowDisplayFrame(@onNull Rect outRect)17235     public void getWindowDisplayFrame(@NonNull Rect outRect) {
17236         if (mAttachInfo != null) {
17237             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
17238             return;
17239         }
17240         // The view is not attached to a display so we don't have a context.
17241         // Make a best guess about the display size.
17242         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
17243         d.getRectSize(outRect);
17244     }
17245 
17246     /**
17247      * Dispatch a notification about a resource configuration change down
17248      * the view hierarchy.
17249      * ViewGroups should override to route to their children.
17250      *
17251      * @param newConfig The new resource configuration.
17252      *
17253      * @see #onConfigurationChanged(android.content.res.Configuration)
17254      */
dispatchConfigurationChanged(Configuration newConfig)17255     public void dispatchConfigurationChanged(Configuration newConfig) {
17256         onConfigurationChanged(newConfig);
17257     }
17258 
17259     /**
17260      * Called when the current configuration of the resources being used
17261      * by the application have changed.  You can use this to decide when
17262      * to reload resources that can changed based on orientation and other
17263      * configuration characteristics.  You only need to use this if you are
17264      * not relying on the normal {@link android.app.Activity} mechanism of
17265      * recreating the activity instance upon a configuration change.
17266      *
17267      * @param newConfig The new resource configuration.
17268      */
onConfigurationChanged(Configuration newConfig)17269     protected void onConfigurationChanged(Configuration newConfig) {
17270     }
17271 
17272     /**
17273      * Private function to aggregate all per-view attributes in to the view
17274      * root.
17275      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)17276     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
17277         performCollectViewAttributes(attachInfo, visibility);
17278     }
17279 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)17280     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
17281         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
17282             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
17283                 attachInfo.mKeepScreenOn = true;
17284             }
17285             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
17286             ListenerInfo li = mListenerInfo;
17287             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
17288                 attachInfo.mHasSystemUiListeners = true;
17289             }
17290         }
17291     }
17292 
needGlobalAttributesUpdate(boolean force)17293     void needGlobalAttributesUpdate(boolean force) {
17294         final AttachInfo ai = mAttachInfo;
17295         if (ai != null && !ai.mRecomputeGlobalAttributes) {
17296             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
17297                     || ai.mHasSystemUiListeners) {
17298                 ai.mRecomputeGlobalAttributes = true;
17299             }
17300         }
17301     }
17302 
17303     /**
17304      * Returns the touch mode state associated with this view.
17305      *
17306      * Attached views return the touch mode state from the associated window's display.
17307      * Detached views just return the default touch mode value defined in
17308      * {@code com.android.internal.R.bool.config_defaultInTouchMode}.
17309      *
17310      * Touch mode is entered once the user begins interacting with the device by touch, and
17311      * affects various things like whether focus highlight is always visible to the user.
17312      *
17313      * @return the touch mode state associated with this view
17314      */
17315     @ViewDebug.ExportedProperty
isInTouchMode()17316     public boolean isInTouchMode() {
17317         if (mAttachInfo != null) {
17318             return mAttachInfo.mInTouchMode;
17319         }
17320         return mResources.getBoolean(com.android.internal.R.bool.config_defaultInTouchMode);
17321     }
17322 
17323     /**
17324      * Returns the context the view is running in, through which it can
17325      * access the current theme, resources, etc.
17326      *
17327      * @return The view's Context.
17328      */
17329     @ViewDebug.CapturedViewProperty
17330     @UiContext
getContext()17331     public final Context getContext() {
17332         return mContext;
17333     }
17334 
17335     /**
17336      * Handle a key event before it is processed by any input method
17337      * associated with the view hierarchy. This can be used to intercept
17338      * key events in special situations before the IME consumes them; a
17339      * typical example would be handling the BACK key to update the application's
17340      * UI instead of allowing the IME to see it and close itself. Due to a bug,
17341      * this function is not called for BACK key events on Android T and U, when
17342      * the IME is shown.
17343      *
17344      * @param keyCode The value in event.getKeyCode().
17345      * @param event Description of the key event.
17346      * @return If you handled the event, return true. If you want to allow the
17347      *         event to be handled by the next receiver, return false.
17348      */
onKeyPreIme(int keyCode, KeyEvent event)17349     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
17350         return false;
17351     }
17352 
17353     /**
17354      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
17355      * KeyEvent.Callback.onKeyDown()}: perform press of the view
17356      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
17357      * is released, if the view is enabled and clickable.
17358      * <p>
17359      * Key presses in software keyboards will generally NOT trigger this
17360      * listener, although some may elect to do so in some situations. Do not
17361      * rely on this to catch software key presses.
17362      *
17363      * @param keyCode a key code that represents the button pressed, from
17364      *                {@link android.view.KeyEvent}
17365      * @param event the KeyEvent object that defines the button action
17366      */
onKeyDown(int keyCode, KeyEvent event)17367     public boolean onKeyDown(int keyCode, KeyEvent event) {
17368         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
17369             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
17370                 return true;
17371             }
17372 
17373             if (event.getRepeatCount() == 0) {
17374                 // Long clickable items don't necessarily have to be clickable.
17375                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
17376                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
17377                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
17378                     // For the purposes of menu anchoring and drawable hotspots,
17379                     // key events are considered to be at the center of the view.
17380                     final float x = getWidth() / 2f;
17381                     final float y = getHeight() / 2f;
17382                     if (clickable) {
17383                         setPressed(true, x, y);
17384                     }
17385                     checkForLongClick(
17386                             ViewConfiguration.getLongPressTimeout(),
17387                             x,
17388                             y,
17389                             // This is not a touch gesture -- do not classify it as one.
17390                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
17391                     return true;
17392                 }
17393             }
17394         }
17395 
17396         return false;
17397     }
17398 
17399     /**
17400      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
17401      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
17402      * the event).
17403      * <p>Key presses in software keyboards will generally NOT trigger this listener,
17404      * although some may elect to do so in some situations. Do not rely on this to
17405      * catch software key presses.
17406      */
onKeyLongPress(int keyCode, KeyEvent event)17407     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
17408         return false;
17409     }
17410 
17411     /**
17412      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
17413      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
17414      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
17415      * or {@link KeyEvent#KEYCODE_SPACE} is released.
17416      * <p>Key presses in software keyboards will generally NOT trigger this listener,
17417      * although some may elect to do so in some situations. Do not rely on this to
17418      * catch software key presses.
17419      *
17420      * @param keyCode A key code that represents the button pressed, from
17421      *                {@link android.view.KeyEvent}.
17422      * @param event   The KeyEvent object that defines the button action.
17423      */
onKeyUp(int keyCode, KeyEvent event)17424     public boolean onKeyUp(int keyCode, KeyEvent event) {
17425         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
17426             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
17427                 return true;
17428             }
17429             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
17430                 setPressed(false);
17431 
17432                 if (!mHasPerformedLongPress) {
17433                     // This is a tap, so remove the longpress check
17434                     removeLongPressCallback();
17435                     if (!event.isCanceled()) {
17436                         return performClickInternal();
17437                     }
17438                 }
17439             }
17440         }
17441         return false;
17442     }
17443 
17444     /**
17445      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
17446      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
17447      * the event).
17448      * <p>Key presses in software keyboards will generally NOT trigger this listener,
17449      * although some may elect to do so in some situations. Do not rely on this to
17450      * catch software key presses.
17451      *
17452      * @param keyCode     A key code that represents the button pressed, from
17453      *                    {@link android.view.KeyEvent}.
17454      * @param repeatCount The number of times the action was made.
17455      * @param event       The KeyEvent object that defines the button action.
17456      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)17457     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
17458         return false;
17459     }
17460 
17461     /**
17462      * Called on the focused view when a key shortcut event is not handled.
17463      * Override this method to implement local key shortcuts for the View.
17464      * Key shortcuts can also be implemented by setting the
17465      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
17466      *
17467      * @param keyCode The value in event.getKeyCode().
17468      * @param event Description of the key event.
17469      * @return If you handled the event, return true. If you want to allow the
17470      *         event to be handled by the next receiver, return false.
17471      */
onKeyShortcut(int keyCode, KeyEvent event)17472     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
17473         return false;
17474     }
17475 
17476     /**
17477      * Check whether the called view is a text editor, in which case it
17478      * would make sense to automatically display a soft input window for
17479      * it.  Subclasses should override this if they implement
17480      * {@link #onCreateInputConnection(EditorInfo)} to return true if
17481      * a call on that method would return a non-null InputConnection, and
17482      * they are really a first-class editor that the user would normally
17483      * start typing on when the go into a window containing your view.
17484      *
17485      * <p>The default implementation always returns false.  This does
17486      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
17487      * will not be called or the user can not otherwise perform edits on your
17488      * view; it is just a hint to the system that this is not the primary
17489      * purpose of this view.
17490      *
17491      * @return Returns true if this view is a text editor, else false.
17492      */
onCheckIsTextEditor()17493     public boolean onCheckIsTextEditor() {
17494         return false;
17495     }
17496 
17497     /**
17498      * Create a new InputConnection for an InputMethod to interact
17499      * with the view.  The default implementation returns null, since it doesn't
17500      * support input methods.  You can override this to implement such support.
17501      * This is only needed for views that take focus and text input.
17502      *
17503      * <p>When implementing this, you probably also want to implement
17504      * {@link #onCheckIsTextEditor()} to indicate you will return a
17505      * non-null InputConnection.</p>
17506      *
17507      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
17508      * object correctly and in its entirety, so that the connected IME can rely
17509      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
17510      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
17511      * must be filled in with the correct cursor position for IMEs to work correctly
17512      * with your application.</p>
17513      *
17514      * @param outAttrs Fill in with attribute information about the connection.
17515      */
onCreateInputConnection(EditorInfo outAttrs)17516     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
17517         return null;
17518     }
17519 
17520     /**
17521      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
17522      * that the system has successfully initialized an {@link InputConnection} and it is ready for
17523      * use.
17524      *
17525      * <p>The default implementation does nothing, since a view doesn't support input methods by
17526      * default (see {@link #onCreateInputConnection}).
17527      *
17528      * @param inputConnection The {@link InputConnection} from {@link #onCreateInputConnection},
17529      * after it's been fully initialized by the system.
17530      * @param editorInfo The {@link EditorInfo} that was used to create the {@link InputConnection}.
17531      * @param handler The dedicated {@link Handler} on which IPC method calls from input methods
17532      * will be dispatched. This is the handler returned by {@link InputConnection#getHandler()}. If
17533      * that method returns null, this parameter will be null also.
17534      *
17535      * @hide
17536      */
onInputConnectionOpenedInternal(@onNull InputConnection inputConnection, @NonNull EditorInfo editorInfo, @Nullable Handler handler)17537     public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
17538             @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
17539 
17540     /**
17541      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
17542      * that the {@link InputConnection} has been closed.
17543      *
17544      * <p>The default implementation does nothing, since a view doesn't support input methods by
17545      * default (see {@link #onCreateInputConnection}).
17546      *
17547      * <p><strong>Note:</strong> This callback is not invoked if the view is already detached when
17548      * the {@link InputConnection} is closed or the connection is not valid and managed by
17549      * {@link com.android.server.inputmethod.InputMethodManagerService}.
17550      * TODO(b/170645312): Before un-hiding this API, handle the detached view scenario.
17551      *
17552      * @hide
17553      */
onInputConnectionClosedInternal()17554     public void onInputConnectionClosedInternal() {}
17555 
17556     /**
17557      * Called by the {@link android.view.inputmethod.InputMethodManager}
17558      * when a view who is not the current
17559      * input connection target is trying to make a call on the manager.  The
17560      * default implementation returns false; you can override this to return
17561      * true for certain views if you are performing InputConnection proxying
17562      * to them.
17563      * @param view The View that is making the InputMethodManager call.
17564      * @return Return true to allow the call, false to reject.
17565      */
checkInputConnectionProxy(View view)17566     public boolean checkInputConnectionProxy(View view) {
17567         return false;
17568     }
17569 
17570     /**
17571      * Show the context menu for this view. It is not safe to hold on to the
17572      * menu after returning from this method.
17573      *
17574      * You should normally not overload this method. Overload
17575      * {@link #onCreateContextMenu(ContextMenu)} or define an
17576      * {@link OnCreateContextMenuListener} to add items to the context menu.
17577      *
17578      * @param menu The context menu to populate
17579      */
createContextMenu(ContextMenu menu)17580     public void createContextMenu(ContextMenu menu) {
17581         ContextMenuInfo menuInfo = getContextMenuInfo();
17582 
17583         // Sets the current menu info so all items added to menu will have
17584         // my extra info set.
17585         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
17586 
17587         onCreateContextMenu(menu);
17588         ListenerInfo li = mListenerInfo;
17589         if (li != null && li.mOnCreateContextMenuListener != null) {
17590             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
17591         }
17592 
17593         // Clear the extra information so subsequent items that aren't mine don't
17594         // have my extra info.
17595         ((MenuBuilder)menu).setCurrentMenuInfo(null);
17596 
17597         if (mParent != null) {
17598             mParent.createContextMenu(menu);
17599         }
17600     }
17601 
17602     /**
17603      * Views should implement this if they have extra information to associate
17604      * with the context menu. The return result is supplied as a parameter to
17605      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
17606      * callback.
17607      *
17608      * @return Extra information about the item for which the context menu
17609      *         should be shown. This information will vary across different
17610      *         subclasses of View.
17611      */
getContextMenuInfo()17612     protected ContextMenuInfo getContextMenuInfo() {
17613         return null;
17614     }
17615 
17616     /**
17617      * Views should implement this if the view itself is going to add items to
17618      * the context menu.
17619      *
17620      * @param menu the context menu to populate
17621      */
onCreateContextMenu(ContextMenu menu)17622     protected void onCreateContextMenu(ContextMenu menu) {
17623     }
17624 
17625     /**
17626      * Implement this method to handle trackball motion events.
17627      * <p>
17628      * The <em>relative</em> movement of the trackball since the last event
17629      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
17630      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
17631      * that a movement of 1 corresponds to the user pressing one DPAD key (so
17632      * they will often be fractional values, representing the more fine-grained
17633      * movement information available from a trackball).
17634      * </p>
17635      *
17636      * @param event The motion event.
17637      * @return True if the event was handled, false otherwise.
17638      */
onTrackballEvent(MotionEvent event)17639     public boolean onTrackballEvent(MotionEvent event) {
17640         return false;
17641     }
17642 
17643     /**
17644      * Implement this method to handle generic motion events.
17645      * <p>
17646      * Generic motion events describe joystick movements, hover events from mouse or stylus
17647      * devices, trackpad touches, scroll wheel movements and other motion events not handled
17648      * by {@link #onTouchEvent(MotionEvent)} or {@link #onTrackballEvent(MotionEvent)}.
17649      * The {@link MotionEvent#getSource() source} of the motion event specifies
17650      * the class of input that was received.  Implementations of this method
17651      * must examine the bits in the source before processing the event.
17652      * The following code example shows how this is done.
17653      * </p><p>
17654      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
17655      * are delivered to the view under the pointer.  All other generic motion events are
17656      * delivered to the focused view.
17657      * </p>
17658      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
17659      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
17660      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
17661      *             // process the joystick movement...
17662      *             return true;
17663      *         }
17664      *     }
17665      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
17666      *         switch (event.getAction()) {
17667      *             case MotionEvent.ACTION_HOVER_MOVE:
17668      *                 // process the hover movement...
17669      *                 return true;
17670      *             case MotionEvent.ACTION_SCROLL:
17671      *                 // process the scroll wheel movement...
17672      *                 return true;
17673      *         }
17674      *     }
17675      *     return super.onGenericMotionEvent(event);
17676      * }</pre>
17677      *
17678      * @param event The generic motion event being processed.
17679      * @return True if the event was handled, false otherwise.
17680      */
onGenericMotionEvent(MotionEvent event)17681     public boolean onGenericMotionEvent(MotionEvent event) {
17682         return false;
17683     }
17684 
17685     /**
17686      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
17687      * <p>
17688      * This method is dispatching hover events to the delegate target to support explore by touch.
17689      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method sends proper hover events to
17690      * the delegate target according to the pointer and the touch area of the delegate while touch
17691      * exploration is enabled.
17692      * </p>
17693      *
17694      * @param event The motion event dispatch to the delegate target.
17695      * @return True if the event was handled, false otherwise.
17696      *
17697      * @see #onHoverEvent
17698      */
dispatchTouchExplorationHoverEvent(MotionEvent event)17699     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
17700         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
17701         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
17702             return false;
17703         }
17704 
17705         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
17706         final int action = event.getActionMasked();
17707         boolean pointInDelegateRegion = false;
17708         boolean handled = false;
17709 
17710         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
17711         for (int i = 0; i < info.getRegionCount(); i++) {
17712             Region r = info.getRegionAt(i);
17713             if (r.contains((int) event.getX(), (int) event.getY())) {
17714                 pointInDelegateRegion = true;
17715             }
17716         }
17717 
17718         // Explore by touch should dispatch events to children under the pointer first if any
17719         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
17720         // hover events but receive accessibility focus, it should also not delegate to these
17721         // views when hovered.
17722         if (!oldHoveringTouchDelegate) {
17723             if (removeChildHoverCheckForTouchExploration()) {
17724                 if ((action == MotionEvent.ACTION_HOVER_ENTER
17725                         || action == MotionEvent.ACTION_HOVER_MOVE) && pointInDelegateRegion) {
17726                     mHoveringTouchDelegate = true;
17727                 }
17728             } else {
17729                 if ((action == MotionEvent.ACTION_HOVER_ENTER
17730                         || action == MotionEvent.ACTION_HOVER_MOVE)
17731                         && !pointInHoveredChild(event)
17732                         && pointInDelegateRegion) {
17733                     mHoveringTouchDelegate = true;
17734                 }
17735             }
17736         } else {
17737             if (removeChildHoverCheckForTouchExploration()) {
17738                 if (action == MotionEvent.ACTION_HOVER_EXIT
17739                         || (action == MotionEvent.ACTION_HOVER_MOVE)) {
17740                     if (!pointInDelegateRegion) {
17741                         mHoveringTouchDelegate = false;
17742                     }
17743                 }
17744             } else {
17745                 if (action == MotionEvent.ACTION_HOVER_EXIT
17746                         || (action == MotionEvent.ACTION_HOVER_MOVE
17747                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
17748                     mHoveringTouchDelegate = false;
17749                 }
17750             }
17751         }
17752         switch (action) {
17753             case MotionEvent.ACTION_HOVER_MOVE:
17754                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
17755                     // Inside bounds, dispatch as is.
17756                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
17757                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
17758                     // Moving inbound, synthesize hover enter.
17759                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
17760                             ? event : MotionEvent.obtainNoHistory(event);
17761                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
17762                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
17763                     eventNoHistory.setAction(action);
17764                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
17765                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
17766                     // Moving outbound, synthesize hover exit.
17767                     final boolean hoverExitPending = event.isHoverExitPending();
17768                     event.setHoverExitPending(true);
17769                     mTouchDelegate.onTouchExplorationHoverEvent(event);
17770                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
17771                             ? event : MotionEvent.obtainNoHistory(event);
17772                     eventNoHistory.setHoverExitPending(hoverExitPending);
17773                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
17774                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
17775                 }  // else: outside bounds, do nothing.
17776                 break;
17777             case MotionEvent.ACTION_HOVER_ENTER:
17778                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
17779                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
17780                 }
17781                 break;
17782             case MotionEvent.ACTION_HOVER_EXIT:
17783                 if (oldHoveringTouchDelegate) {
17784                     mTouchDelegate.onTouchExplorationHoverEvent(event);
17785                 }
17786                 break;
17787         }
17788         return handled;
17789     }
17790 
17791     /**
17792      * Implement this method to handle hover events.
17793      * <p>
17794      * This method is called whenever a pointer is hovering into, over, or out of the
17795      * bounds of a view and the view is not currently being touched.
17796      * Hover events are represented as pointer events with action
17797      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
17798      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
17799      * </p>
17800      * <ul>
17801      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
17802      * when the pointer enters the bounds of the view.</li>
17803      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
17804      * when the pointer has already entered the bounds of the view and has moved.</li>
17805      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
17806      * when the pointer has exited the bounds of the view or when the pointer is
17807      * about to go down due to a button click, tap, or similar user action that
17808      * causes the view to be touched.</li>
17809      * </ul>
17810      * <p>
17811      * The view should implement this method to return true to indicate that it is
17812      * handling the hover event, such as by changing its drawable state.
17813      * </p><p>
17814      * The default implementation calls {@link #setHovered} to update the hovered state
17815      * of the view when a hover enter or hover exit event is received, if the view
17816      * is enabled and is clickable.  The default implementation also sends hover
17817      * accessibility events.
17818      * </p>
17819      *
17820      * @param event The motion event that describes the hover.
17821      * @return True if the view handled the hover event.
17822      *
17823      * @see #isHovered
17824      * @see #setHovered
17825      * @see #onHoverChanged
17826      */
onHoverEvent(MotionEvent event)17827     public boolean onHoverEvent(MotionEvent event) {
17828         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
17829             return true;
17830         }
17831 
17832         // The root view may receive hover (or touch) events that are outside the bounds of
17833         // the window.  This code ensures that we only send accessibility events for
17834         // hovers that are actually within the bounds of the root view.
17835         final int action = event.getActionMasked();
17836         if (!mSendingHoverAccessibilityEvents) {
17837             if ((action == MotionEvent.ACTION_HOVER_ENTER
17838                     || action == MotionEvent.ACTION_HOVER_MOVE)
17839                     && !hasHoveredChild()
17840                     && pointInView(event.getX(), event.getY())) {
17841                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
17842                 mSendingHoverAccessibilityEvents = true;
17843             }
17844         } else {
17845             if (action == MotionEvent.ACTION_HOVER_EXIT
17846                     || (action == MotionEvent.ACTION_HOVER_MOVE
17847                             && !pointInView(event.getX(), event.getY()))) {
17848                 mSendingHoverAccessibilityEvents = false;
17849                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
17850             }
17851         }
17852 
17853         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
17854                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
17855                 && isOnScrollbar(event.getX(), event.getY())) {
17856             awakenScrollBars();
17857         }
17858 
17859         // If we consider ourself hoverable, or if we we're already hovered,
17860         // handle changing state in response to ENTER and EXIT events.
17861         if (isHoverable() || isHovered()) {
17862             switch (action) {
17863                 case MotionEvent.ACTION_HOVER_ENTER:
17864                     setHovered(true);
17865                     break;
17866                 case MotionEvent.ACTION_HOVER_EXIT:
17867                     setHovered(false);
17868                     break;
17869             }
17870 
17871             // Dispatch the event to onGenericMotionEvent before returning true.
17872             // This is to provide compatibility with existing applications that
17873             // handled HOVER_MOVE events in onGenericMotionEvent and that would
17874             // break because of the new default handling for hoverable views
17875             // in onHoverEvent.
17876             // Note that onGenericMotionEvent will be called by default when
17877             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
17878             dispatchGenericMotionEventInternal(event);
17879             // The event was already handled by calling setHovered(), so always
17880             // return true.
17881             return true;
17882         }
17883 
17884         return false;
17885     }
17886 
17887     /**
17888      * Returns true if the view should handle {@link #onHoverEvent}
17889      * by calling {@link #setHovered} to change its hovered state.
17890      *
17891      * @return True if the view is hoverable.
17892      */
isHoverable()17893     private boolean isHoverable() {
17894         final int viewFlags = mViewFlags;
17895         if ((viewFlags & ENABLED_MASK) == DISABLED) {
17896             return false;
17897         }
17898 
17899         return (viewFlags & CLICKABLE) == CLICKABLE
17900                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
17901                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
17902     }
17903 
17904     /**
17905      * Returns true if the view is currently hovered.
17906      *
17907      * @return True if the view is currently hovered.
17908      *
17909      * @see #setHovered
17910      * @see #onHoverChanged
17911      */
17912     @ViewDebug.ExportedProperty
isHovered()17913     public boolean isHovered() {
17914         return (mPrivateFlags & PFLAG_HOVERED) != 0;
17915     }
17916 
17917     /**
17918      * Sets whether the view is currently hovered.
17919      * <p>
17920      * Calling this method also changes the drawable state of the view.  This
17921      * enables the view to react to hover by using different drawable resources
17922      * to change its appearance.
17923      * </p><p>
17924      * The {@link #onHoverChanged} method is called when the hovered state changes.
17925      * </p>
17926      *
17927      * @param hovered True if the view is hovered.
17928      *
17929      * @see #isHovered
17930      * @see #onHoverChanged
17931      */
setHovered(boolean hovered)17932     public void setHovered(boolean hovered) {
17933         if (hovered) {
17934             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
17935                 mPrivateFlags |= PFLAG_HOVERED;
17936                 refreshDrawableState();
17937                 onHoverChanged(true);
17938             }
17939         } else {
17940             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
17941                 mPrivateFlags &= ~PFLAG_HOVERED;
17942                 refreshDrawableState();
17943                 onHoverChanged(false);
17944             }
17945         }
17946     }
17947 
17948     /**
17949      * Implement this method to handle hover state changes.
17950      * <p>
17951      * This method is called whenever the hover state changes as a result of a
17952      * call to {@link #setHovered}.
17953      * </p>
17954      *
17955      * @param hovered The current hover state, as returned by {@link #isHovered}.
17956      *
17957      * @see #isHovered
17958      * @see #setHovered
17959      */
onHoverChanged(boolean hovered)17960     public void onHoverChanged(boolean hovered) {
17961     }
17962 
17963     /**
17964      * Handles scroll bar dragging by mouse input.
17965      *
17966      * @hide
17967      * @param event The motion event.
17968      *
17969      * @return true if the event was handled as a scroll bar dragging, false otherwise.
17970      */
handleScrollBarDragging(MotionEvent event)17971     protected boolean handleScrollBarDragging(MotionEvent event) {
17972         if (mScrollCache == null) {
17973             return false;
17974         }
17975         final float x = event.getX();
17976         final float y = event.getY();
17977         final int action = event.getAction();
17978         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
17979                 && action != MotionEvent.ACTION_DOWN)
17980                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
17981                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
17982             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
17983             return false;
17984         }
17985 
17986         switch (action) {
17987             case MotionEvent.ACTION_MOVE:
17988                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
17989                     return false;
17990                 }
17991                 if (mScrollCache.mScrollBarDraggingState
17992                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
17993                     final Rect bounds = mScrollCache.mScrollBarBounds;
17994                     getVerticalScrollBarBounds(bounds, null);
17995                     final int range = computeVerticalScrollRange();
17996                     final int offset = computeVerticalScrollOffset();
17997                     final int extent = computeVerticalScrollExtent();
17998 
17999                     final int thumbLength = ScrollBarUtils.getThumbLength(
18000                             bounds.height(), bounds.width(), extent, range);
18001                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
18002                             bounds.height(), thumbLength, extent, range, offset);
18003 
18004                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
18005                     final float maxThumbOffset = bounds.height() - thumbLength;
18006                     final float newThumbOffset =
18007                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
18008                     final int height = getHeight();
18009                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
18010                             && height > 0 && extent > 0) {
18011                         final int newY = Math.round((range - extent)
18012                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
18013                         if (newY != getScrollY()) {
18014                             mScrollCache.mScrollBarDraggingPos = y;
18015                             setScrollY(newY);
18016                         }
18017                     }
18018                     return true;
18019                 }
18020                 if (mScrollCache.mScrollBarDraggingState
18021                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
18022                     final Rect bounds = mScrollCache.mScrollBarBounds;
18023                     getHorizontalScrollBarBounds(bounds, null);
18024                     final int range = computeHorizontalScrollRange();
18025                     final int offset = computeHorizontalScrollOffset();
18026                     final int extent = computeHorizontalScrollExtent();
18027 
18028                     final int thumbLength = ScrollBarUtils.getThumbLength(
18029                             bounds.width(), bounds.height(), extent, range);
18030                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
18031                             bounds.width(), thumbLength, extent, range, offset);
18032 
18033                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
18034                     final float maxThumbOffset = bounds.width() - thumbLength;
18035                     final float newThumbOffset =
18036                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
18037                     final int width = getWidth();
18038                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
18039                             && width > 0 && extent > 0) {
18040                         final int newX = Math.round((range - extent)
18041                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
18042                         if (newX != getScrollX()) {
18043                             mScrollCache.mScrollBarDraggingPos = x;
18044                             setScrollX(newX);
18045                         }
18046                     }
18047                     return true;
18048                 }
18049             case MotionEvent.ACTION_DOWN:
18050                 if (mScrollCache.state == ScrollabilityCache.OFF) {
18051                     return false;
18052                 }
18053                 if (isOnVerticalScrollbarThumb(x, y)) {
18054                     mScrollCache.mScrollBarDraggingState =
18055                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
18056                     mScrollCache.mScrollBarDraggingPos = y;
18057                     return true;
18058                 }
18059                 if (isOnHorizontalScrollbarThumb(x, y)) {
18060                     mScrollCache.mScrollBarDraggingState =
18061                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
18062                     mScrollCache.mScrollBarDraggingPos = x;
18063                     return true;
18064                 }
18065         }
18066         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
18067         return false;
18068     }
18069 
18070     /**
18071      * Implement this method to handle pointer events.
18072      * <p>
18073      * This method is called to handle motion events where pointers are down on
18074      * the view. For example, this could include touchscreen touches, stylus
18075      * touches, or click-and-drag events from a mouse. However, it is not called
18076      * for motion events that do not involve pointers being down, such as hover
18077      * events or mouse scroll wheel movements.
18078      * <p>
18079      * If this method is used to detect click actions, it is recommended that
18080      * the actions be performed by implementing and calling
18081      * {@link #performClick()}. This will ensure consistent system behavior,
18082      * including:
18083      * <ul>
18084      * <li>obeying click sound preferences
18085      * <li>dispatching OnClickListener calls
18086      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
18087      * accessibility features are enabled
18088      * </ul>
18089      *
18090      * @param event The motion event.
18091      * @return True if the event was handled, false otherwise.
18092      */
onTouchEvent(MotionEvent event)18093     public boolean onTouchEvent(MotionEvent event) {
18094         final float x = event.getX();
18095         final float y = event.getY();
18096         final int viewFlags = mViewFlags;
18097         final int action = event.getAction();
18098 
18099         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
18100                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
18101                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
18102 
18103         if ((viewFlags & ENABLED_MASK) == DISABLED
18104                 && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
18105             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
18106                 setPressed(false);
18107             }
18108             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
18109             // A disabled view that is clickable still consumes the touch
18110             // events, it just doesn't respond to them.
18111             return clickable;
18112         }
18113         if (mTouchDelegate != null) {
18114             if (mTouchDelegate.onTouchEvent(event)) {
18115                 return true;
18116             }
18117         }
18118 
18119         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
18120             switch (action) {
18121                 case MotionEvent.ACTION_UP:
18122                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
18123                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
18124                         handleTooltipUp();
18125                     }
18126                     if (!clickable) {
18127                         removeTapCallback();
18128                         removeLongPressCallback();
18129                         mInContextButtonPress = false;
18130                         mHasPerformedLongPress = false;
18131                         mIgnoreNextUpEvent = false;
18132                         break;
18133                     }
18134                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
18135                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
18136                         // take focus if we don't have it already and we should in
18137                         // touch mode.
18138                         boolean focusTaken = false;
18139                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
18140                             focusTaken = requestFocus();
18141                         }
18142 
18143                         if (prepressed) {
18144                             // The button is being released before we actually
18145                             // showed it as pressed.  Make it show the pressed
18146                             // state now (before scheduling the click) to ensure
18147                             // the user sees it.
18148                             setPressed(true, x, y);
18149                         }
18150 
18151                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
18152                             // This is a tap, so remove the longpress check
18153                             removeLongPressCallback();
18154 
18155                             // Only perform take click actions if we were in the pressed state
18156                             if (!focusTaken) {
18157                                 // Use a Runnable and post this rather than calling
18158                                 // performClick directly. This lets other visual state
18159                                 // of the view update before click actions start.
18160                                 if (mPerformClick == null) {
18161                                     mPerformClick = new PerformClick();
18162                                 }
18163                                 if (!post(mPerformClick)) {
18164                                     performClickInternal();
18165                                 }
18166                             }
18167                         }
18168 
18169                         if (mUnsetPressedState == null) {
18170                             mUnsetPressedState = new UnsetPressedState();
18171                         }
18172 
18173                         if (prepressed) {
18174                             postDelayed(mUnsetPressedState,
18175                                     ViewConfiguration.getPressedStateDuration());
18176                         } else if (!post(mUnsetPressedState)) {
18177                             // If the post failed, unpress right now
18178                             mUnsetPressedState.run();
18179                         }
18180 
18181                         removeTapCallback();
18182                     }
18183                     mIgnoreNextUpEvent = false;
18184                     break;
18185 
18186                 case MotionEvent.ACTION_DOWN:
18187                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
18188                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
18189                     }
18190                     mHasPerformedLongPress = false;
18191 
18192                     if (!clickable) {
18193                         checkForLongClick(
18194                                 ViewConfiguration.getLongPressTimeout(),
18195                                 x,
18196                                 y,
18197                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
18198                         break;
18199                     }
18200 
18201                     if (performButtonActionOnTouchDown(event)) {
18202                         break;
18203                     }
18204 
18205                     // Walk up the hierarchy to determine if we're inside a scrolling container.
18206                     boolean isInScrollingContainer = isInScrollingContainer();
18207 
18208                     // For views inside a scrolling container, delay the pressed feedback for
18209                     // a short period in case this is a scroll.
18210                     if (isInScrollingContainer) {
18211                         mPrivateFlags |= PFLAG_PREPRESSED;
18212                         if (mPendingCheckForTap == null) {
18213                             mPendingCheckForTap = new CheckForTap();
18214                         }
18215                         mPendingCheckForTap.x = event.getX();
18216                         mPendingCheckForTap.y = event.getY();
18217                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
18218                     } else {
18219                         // Not inside a scrolling container, so show the feedback right away
18220                         setPressed(true, x, y);
18221                         checkForLongClick(
18222                                 ViewConfiguration.getLongPressTimeout(),
18223                                 x,
18224                                 y,
18225                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
18226                     }
18227                     break;
18228 
18229                 case MotionEvent.ACTION_CANCEL:
18230                     if (clickable) {
18231                         setPressed(false);
18232                     }
18233                     removeTapCallback();
18234                     removeLongPressCallback();
18235                     mInContextButtonPress = false;
18236                     mHasPerformedLongPress = false;
18237                     mIgnoreNextUpEvent = false;
18238                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
18239                     break;
18240 
18241                 case MotionEvent.ACTION_MOVE:
18242                     if (clickable) {
18243                         drawableHotspotChanged(x, y);
18244                     }
18245 
18246                     final int motionClassification = event.getClassification();
18247                     final boolean ambiguousGesture =
18248                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
18249                     int touchSlop = mTouchSlop;
18250                     if (ambiguousGesture && hasPendingLongPressCallback()) {
18251                         if (!pointInView(x, y, touchSlop)) {
18252                             // The default action here is to cancel long press. But instead, we
18253                             // just extend the timeout here, in case the classification
18254                             // stays ambiguous.
18255                             removeLongPressCallback();
18256                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
18257                                     * mAmbiguousGestureMultiplier);
18258                             // Subtract the time already spent
18259                             delay -= event.getEventTime() - event.getDownTime();
18260                             checkForLongClick(
18261                                     delay,
18262                                     x,
18263                                     y,
18264                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
18265                         }
18266                         touchSlop *= mAmbiguousGestureMultiplier;
18267                     }
18268 
18269                     // Be lenient about moving outside of buttons
18270                     if (!pointInView(x, y, touchSlop)) {
18271                         // Outside button
18272                         // Remove any future long press/tap checks
18273                         removeTapCallback();
18274                         removeLongPressCallback();
18275                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
18276                             setPressed(false);
18277                         }
18278                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
18279                     }
18280 
18281                     final boolean deepPress =
18282                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
18283                     if (deepPress && hasPendingLongPressCallback()) {
18284                         // process the long click action immediately
18285                         removeLongPressCallback();
18286                         checkForLongClick(
18287                                 0 /* send immediately */,
18288                                 x,
18289                                 y,
18290                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
18291                     }
18292 
18293                     break;
18294             }
18295 
18296             return true;
18297         }
18298 
18299         return false;
18300     }
18301 
18302     /**
18303      * Called by {@link #measure(int, int)} to check if the current frame presentation got
18304      * delayed by an expensive view mesures during the input event dispatching. (e.g. scrolling)
18305      */
hasExpensiveMeasuresDuringInputEvent()18306     private boolean hasExpensiveMeasuresDuringInputEvent() {
18307         final AttachInfo attachInfo = mAttachInfo;
18308         if (attachInfo == null || attachInfo.mRootView == null) {
18309             return false;
18310         }
18311         if (!attachInfo.mHandlingPointerEvent) {
18312             return false;
18313         }
18314         final ViewFrameInfo info = attachInfo.mViewRootImpl.mViewFrameInfo;
18315         final long durationFromVsyncTimeMs = (System.nanoTime()
18316                 - Choreographer.getInstance().getLastFrameTimeNanos()) / TimeUtils.NANOS_PER_MS;
18317         return durationFromVsyncTimeMs > 3L || info.getAndIncreaseViewMeasuredCount() > 10;
18318     }
18319 
18320     /**
18321      * @hide
18322      */
18323     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInScrollingContainer()18324     public boolean isInScrollingContainer() {
18325         ViewParent p = getParent();
18326         while (p != null && p instanceof ViewGroup) {
18327             if (((ViewGroup) p).shouldDelayChildPressedState()) {
18328                 return true;
18329             }
18330             p = p.getParent();
18331         }
18332         return false;
18333     }
18334 
18335     /**
18336      * Remove the longpress detection timer.
18337      */
removeLongPressCallback()18338     private void removeLongPressCallback() {
18339         if (mPendingCheckForLongPress != null) {
18340             removeCallbacks(mPendingCheckForLongPress);
18341         }
18342     }
18343 
18344     /**
18345      * Return true if the long press callback is scheduled to run sometime in the future.
18346      * Return false if there is no scheduled long press callback at the moment.
18347      */
hasPendingLongPressCallback()18348     private boolean hasPendingLongPressCallback() {
18349         if (mPendingCheckForLongPress == null) {
18350             return false;
18351         }
18352         final AttachInfo attachInfo = mAttachInfo;
18353         if (attachInfo == null) {
18354             return false;
18355         }
18356         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
18357     }
18358 
18359     /**
18360      * Remove the pending click action
18361      */
18362     @UnsupportedAppUsage
removePerformClickCallback()18363     private void removePerformClickCallback() {
18364         if (mPerformClick != null) {
18365             removeCallbacks(mPerformClick);
18366         }
18367     }
18368 
18369     /**
18370      * Remove the prepress detection timer.
18371      */
removeUnsetPressCallback()18372     private void removeUnsetPressCallback() {
18373         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
18374             setPressed(false);
18375             removeCallbacks(mUnsetPressedState);
18376         }
18377     }
18378 
18379     /**
18380      * Remove the tap detection timer.
18381      */
removeTapCallback()18382     private void removeTapCallback() {
18383         if (mPendingCheckForTap != null) {
18384             mPrivateFlags &= ~PFLAG_PREPRESSED;
18385             removeCallbacks(mPendingCheckForTap);
18386         }
18387     }
18388 
18389     /**
18390      * Cancels a pending long press.  Your subclass can use this if you
18391      * want the context menu to come up if the user presses and holds
18392      * at the same place, but you don't want it to come up if they press
18393      * and then move around enough to cause scrolling.
18394      */
cancelLongPress()18395     public void cancelLongPress() {
18396         removeLongPressCallback();
18397 
18398         /*
18399          * The prepressed state handled by the tap callback is a display
18400          * construct, but the tap callback will post a long press callback
18401          * less its own timeout. Remove it here.
18402          */
18403         removeTapCallback();
18404     }
18405 
18406     /**
18407      * Sets the TouchDelegate for this View.
18408      */
setTouchDelegate(TouchDelegate delegate)18409     public void setTouchDelegate(TouchDelegate delegate) {
18410         mTouchDelegate = delegate;
18411     }
18412 
18413     /**
18414      * Gets the TouchDelegate for this View.
18415      */
getTouchDelegate()18416     public TouchDelegate getTouchDelegate() {
18417         return mTouchDelegate;
18418     }
18419 
18420     /**
18421      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
18422      *
18423      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
18424      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
18425      * available. This method should only be called for touch events.
18426      *
18427      * <p class="note">This API is not intended for most applications. Buffered dispatch
18428      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
18429      * streams will not improve your input latency. Side effects include: increased latency,
18430      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
18431      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
18432      * you.</p>
18433      *
18434      * To receive unbuffered events for arbitrary input device source classes, use
18435      * {@link #requestUnbufferedDispatch(int)},
18436      *
18437      * @see View#requestUnbufferedDispatch(int)
18438      */
requestUnbufferedDispatch(MotionEvent event)18439     public final void requestUnbufferedDispatch(MotionEvent event) {
18440         final int action = event.getAction();
18441         if (mAttachInfo == null
18442                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
18443                 || !event.isTouchEvent()) {
18444             return;
18445         }
18446         mAttachInfo.mUnbufferedDispatchRequested = true;
18447     }
18448 
18449     /**
18450      * Request unbuffered dispatch of the given event source class to this view.
18451      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
18452      * automatically terminate, and allows the specification of arbitrary input source classes.
18453      *
18454      * <p>Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, calling this method
18455      * will not result in any behavioral changes when this View is not attached to a window.
18456      *
18457      * @param source The combined input source class to request unbuffered dispatch for. All
18458      *               events coming from these source classes will not be buffered. Set to
18459      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
18460      *
18461      * @see View#requestUnbufferedDispatch(MotionEvent)
18462      */
requestUnbufferedDispatch(@nputSourceClass int source)18463     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
18464         if (mUnbufferedInputSource == source) {
18465             return;
18466         }
18467         mUnbufferedInputSource = source;
18468         if (mParent != null) {
18469             mParent.onDescendantUnbufferedRequested();
18470         }
18471     }
18472 
hasSize()18473     private boolean hasSize() {
18474         return (mBottom > mTop) && (mRight > mLeft);
18475     }
18476 
canTakeFocus()18477     private boolean canTakeFocus() {
18478         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
18479                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
18480                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
18481                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
18482     }
18483 
18484     /**
18485      * Set flags controlling behavior of this view.
18486      *
18487      * @param flags Constant indicating the value which should be set
18488      * @param mask Constant indicating the bit range that should be changed
18489      */
18490     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)18491     void setFlags(int flags, int mask) {
18492         final boolean accessibilityEnabled =
18493                 AccessibilityManager.getInstance(mContext).isEnabled();
18494         final boolean oldIncludeForAccessibility =
18495                 accessibilityEnabled && includeForAccessibility(false);
18496 
18497         int old = mViewFlags;
18498         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
18499 
18500         int changed = mViewFlags ^ old;
18501         if (changed == 0) {
18502             return;
18503         }
18504         int privateFlags = mPrivateFlags;
18505         boolean shouldNotifyFocusableAvailable = false;
18506 
18507         // If focusable is auto, update the FOCUSABLE bit.
18508         int focusableChangedByAuto = 0;
18509         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
18510                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
18511             // Heuristic only takes into account whether view is clickable.
18512             final int newFocus;
18513             if ((mViewFlags & CLICKABLE) != 0) {
18514                 newFocus = FOCUSABLE;
18515             } else {
18516                 newFocus = NOT_FOCUSABLE;
18517             }
18518             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
18519             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
18520             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
18521         }
18522 
18523         /* Check if the FOCUSABLE bit has changed */
18524         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
18525             if (((old & FOCUSABLE) == FOCUSABLE)
18526                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
18527                 /* Give up focus if we are no longer focusable */
18528                 clearFocus();
18529                 if (mParent instanceof ViewGroup) {
18530                     ((ViewGroup) mParent).clearFocusedInCluster();
18531                 }
18532             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
18533                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
18534                 /*
18535                  * Tell the view system that we are now available to take focus
18536                  * if no one else already has it.
18537                  */
18538                 if (mParent != null) {
18539                     ViewRootImpl viewRootImpl = getViewRootImpl();
18540                     if (!sAutoFocusableOffUIThreadWontNotifyParents
18541                             || focusableChangedByAuto == 0
18542                             || viewRootImpl == null
18543                             || viewRootImpl.mThread == Thread.currentThread()) {
18544                         shouldNotifyFocusableAvailable = canTakeFocus();
18545                     }
18546                 }
18547             }
18548         }
18549 
18550         final int newVisibility = flags & VISIBILITY_MASK;
18551         if (newVisibility == VISIBLE) {
18552             if ((changed & VISIBILITY_MASK) != 0) {
18553                 /*
18554                  * If this view is becoming visible, invalidate it in case it changed while
18555                  * it was not visible. Marking it drawn ensures that the invalidation will
18556                  * go through.
18557                  */
18558                 mPrivateFlags |= PFLAG_DRAWN;
18559                 invalidate(true);
18560 
18561                 needGlobalAttributesUpdate(true);
18562 
18563                 // a view becoming visible is worth notifying the parent about in case nothing has
18564                 // focus. Even if this specific view isn't focusable, it may contain something that
18565                 // is, so let the root view try to give this focus if nothing else does.
18566                 shouldNotifyFocusableAvailable = hasSize();
18567             }
18568         }
18569 
18570         if ((changed & ENABLED_MASK) != 0) {
18571             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
18572                 // a view becoming enabled should notify the parent as long as the view is also
18573                 // visible and the parent wasn't already notified by becoming visible during this
18574                 // setFlags invocation.
18575                 shouldNotifyFocusableAvailable = canTakeFocus();
18576             } else {
18577                 if (isFocused()) clearFocus();
18578             }
18579         }
18580 
18581         if (shouldNotifyFocusableAvailable && mParent != null) {
18582             mParent.focusableViewAvailable(this);
18583         }
18584 
18585         /* Check if the GONE bit has changed */
18586         if ((changed & GONE) != 0) {
18587             needGlobalAttributesUpdate(false);
18588             requestLayout();
18589 
18590             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
18591                 if (hasFocus()) {
18592                     clearFocus();
18593                     if (mParent instanceof ViewGroup) {
18594                         ((ViewGroup) mParent).clearFocusedInCluster();
18595                     }
18596                 }
18597                 clearAccessibilityFocus();
18598                 destroyDrawingCache();
18599                 if (mParent instanceof View) {
18600                     // GONE views noop invalidation, so invalidate the parent
18601                     ((View) mParent).invalidate(true);
18602                 }
18603                 // Mark the view drawn to ensure that it gets invalidated properly the next
18604                 // time it is visible and gets invalidated
18605                 mPrivateFlags |= PFLAG_DRAWN;
18606             }
18607             if (mAttachInfo != null) {
18608                 mAttachInfo.mViewVisibilityChanged = true;
18609             }
18610         }
18611 
18612         /* Check if the VISIBLE bit has changed */
18613         if ((changed & INVISIBLE) != 0) {
18614             needGlobalAttributesUpdate(false);
18615             /*
18616              * If this view is becoming invisible, set the DRAWN flag so that
18617              * the next invalidate() will not be skipped.
18618              */
18619             mPrivateFlags |= PFLAG_DRAWN;
18620 
18621             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
18622                 // root view becoming invisible shouldn't clear focus and accessibility focus
18623                 if (getRootView() != this) {
18624                     if (hasFocus()) {
18625                         clearFocus();
18626                         if (mParent instanceof ViewGroup) {
18627                             ((ViewGroup) mParent).clearFocusedInCluster();
18628                         }
18629                     }
18630                     clearAccessibilityFocus();
18631                 }
18632             }
18633             if (mAttachInfo != null) {
18634                 mAttachInfo.mViewVisibilityChanged = true;
18635             }
18636         }
18637 
18638         if ((changed & VISIBILITY_MASK) != 0) {
18639             // If the view is invisible, cleanup its display list to free up resources
18640             if (newVisibility != VISIBLE && mAttachInfo != null) {
18641                 cleanupDraw();
18642             }
18643 
18644             if (mParent instanceof ViewGroup) {
18645                 ViewGroup parent = (ViewGroup) mParent;
18646                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
18647                         newVisibility);
18648                 parent.invalidate(true);
18649             } else if (mParent != null) {
18650                 mParent.invalidateChild(this, null);
18651             }
18652 
18653             if (mAttachInfo != null) {
18654                 dispatchVisibilityChanged(this, newVisibility);
18655 
18656                 // Aggregated visibility changes are dispatched to attached views
18657                 // in visible windows where the parent is currently shown/drawn
18658                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
18659                 // discounting clipping or overlapping. This makes it a good place
18660                 // to change animation states.
18661                 if (mParent != null && getWindowVisibility() == VISIBLE &&
18662                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
18663                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
18664                 }
18665                 // If this view is invisible from visible, then sending the A11y event by its
18666                 // parent which is shown and has the accessibility important.
18667                 if ((old & VISIBILITY_MASK) == VISIBLE) {
18668                     notifySubtreeAccessibilityStateChangedByParentIfNeeded();
18669                 } else {
18670                     notifySubtreeAccessibilityStateChangedIfNeeded();
18671                 }
18672             }
18673         }
18674 
18675         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
18676             destroyDrawingCache();
18677         }
18678 
18679         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
18680             destroyDrawingCache();
18681             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18682             invalidateParentCaches();
18683         }
18684 
18685         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
18686             destroyDrawingCache();
18687             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18688         }
18689 
18690         if ((changed & DRAW_MASK) != 0) {
18691             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
18692                 if (mBackground != null
18693                         || mDefaultFocusHighlight != null
18694                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
18695                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18696                 } else {
18697                     mPrivateFlags |= PFLAG_SKIP_DRAW;
18698                 }
18699             } else {
18700                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18701             }
18702             requestLayout();
18703             invalidate(true);
18704         }
18705 
18706         if ((changed & KEEP_SCREEN_ON) != 0) {
18707             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18708                 mParent.recomputeViewAttributes(this);
18709             }
18710         }
18711 
18712         if (accessibilityEnabled) {
18713             // If we're an accessibility pane and the visibility changed, we already have sent
18714             // a state change, so we really don't need to report other changes.
18715             if (isAccessibilityPane()) {
18716                 changed &= ~VISIBILITY_MASK;
18717             }
18718             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
18719                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
18720                     || (changed & CONTEXT_CLICKABLE) != 0) {
18721                 if (oldIncludeForAccessibility != includeForAccessibility(false)) {
18722                     notifySubtreeAccessibilityStateChangedIfNeeded();
18723                 } else {
18724                     notifyViewAccessibilityStateChangedIfNeeded(
18725                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18726                 }
18727             } else if ((changed & ENABLED_MASK) != 0) {
18728                 notifyViewAccessibilityStateChangedIfNeeded(
18729                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18730             }
18731         }
18732     }
18733 
18734     /**
18735      * Change the view's z order in the tree, so it's on top of other sibling
18736      * views. This ordering change may affect layout, if the parent container
18737      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
18738      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
18739      * method should be followed by calls to {@link #requestLayout()} and
18740      * {@link View#invalidate()} on the view's parent to force the parent to redraw
18741      * with the new child ordering.
18742      *
18743      * @see ViewGroup#bringChildToFront(View)
18744      */
bringToFront()18745     public void bringToFront() {
18746         if (mParent != null) {
18747             mParent.bringChildToFront(this);
18748         }
18749     }
18750 
getScrollFeedbackProvider()18751     private HapticScrollFeedbackProvider getScrollFeedbackProvider() {
18752         if (mScrollFeedbackProvider == null) {
18753             mScrollFeedbackProvider = new HapticScrollFeedbackProvider(this,
18754                     ViewConfiguration.get(mContext), /* isFromView= */ true);
18755         }
18756         return mScrollFeedbackProvider;
18757     }
18758 
doRotaryProgressForScrollHaptics(MotionEvent rotaryEvent)18759     private void doRotaryProgressForScrollHaptics(MotionEvent rotaryEvent) {
18760         final float axisScrollValue = rotaryEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
18761         final float verticalScrollFactor =
18762                 ViewConfiguration.get(mContext).getScaledVerticalScrollFactor();
18763         final int scrollAmount = -Math.round(axisScrollValue * verticalScrollFactor);
18764         getScrollFeedbackProvider().onScrollProgress(
18765                 rotaryEvent.getDeviceId(), InputDevice.SOURCE_ROTARY_ENCODER,
18766                 MotionEvent.AXIS_SCROLL, scrollAmount);
18767     }
18768 
doRotaryLimitForScrollHaptics(MotionEvent rotaryEvent)18769     private void doRotaryLimitForScrollHaptics(MotionEvent rotaryEvent) {
18770         final boolean isStart = rotaryEvent.getAxisValue(MotionEvent.AXIS_SCROLL) > 0;
18771         getScrollFeedbackProvider().onScrollLimit(
18772                 rotaryEvent.getDeviceId(), InputDevice.SOURCE_ROTARY_ENCODER,
18773                 MotionEvent.AXIS_SCROLL, isStart);
18774     }
18775 
processScrollEventForRotaryEncoderHaptics()18776     private void processScrollEventForRotaryEncoderHaptics() {
18777         if ((mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT) != 0) {
18778             mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
18779             mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
18780         }
18781     }
18782 
18783     /**
18784      * Disables the rotary scroll feedback implementation of the View class.
18785      *
18786      * <p>Note that this does NOT disable all rotary scroll feedback; it just disables the logic
18787      * implemented within the View class. The child implementation of the View may implement its own
18788      * rotary scroll feedback logic or use {@link ScrollFeedbackProvider} to generate rotary scroll
18789      * feedback.
18790      */
disableRotaryScrollFeedback()18791     void disableRotaryScrollFeedback() {
18792         // Force set PFLAG4_ROTARY_HAPTICS_DETERMINED to avoid recalculating
18793         // PFLAG4_ROTARY_HAPTICS_ENABLED under any circumstance.
18794         mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_DETERMINED;
18795         mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_ENABLED;
18796     }
18797 
18798     /**
18799      * This is called in response to an internal scroll in this view (i.e., the
18800      * view scrolled its own contents). This is typically as a result of
18801      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
18802      * called.
18803      *
18804      * @param l Current horizontal scroll origin.
18805      * @param t Current vertical scroll origin.
18806      * @param oldl Previous horizontal scroll origin.
18807      * @param oldt Previous vertical scroll origin.
18808      */
onScrollChanged(int l, int t, int oldl, int oldt)18809     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
18810         notifySubtreeAccessibilityStateChangedIfNeeded();
18811         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
18812 
18813         processScrollEventForRotaryEncoderHaptics();
18814 
18815         mBackgroundSizeChanged = true;
18816         mDefaultFocusHighlightSizeChanged = true;
18817         if (mForegroundInfo != null) {
18818             mForegroundInfo.mBoundsChanged = true;
18819         }
18820 
18821         final AttachInfo ai = mAttachInfo;
18822         if (ai != null) {
18823             ai.mViewScrollChanged = true;
18824         }
18825 
18826         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
18827             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
18828         }
18829     }
18830 
18831     /**
18832      * Interface definition for a callback to be invoked when the scroll
18833      * X or Y positions of a view change.
18834      * <p>
18835      * <b>Note:</b> Some views handle scrolling independently from View and may
18836      * have their own separate listeners for scroll-type events. For example,
18837      * {@link android.widget.ListView ListView} allows clients to register an
18838      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
18839      * to listen for changes in list scroll position.
18840      *
18841      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
18842      */
18843     public interface OnScrollChangeListener {
18844         /**
18845          * Called when the scroll position of a view changes.
18846          *
18847          * @param v The view whose scroll position has changed.
18848          * @param scrollX Current horizontal scroll origin.
18849          * @param scrollY Current vertical scroll origin.
18850          * @param oldScrollX Previous horizontal scroll origin.
18851          * @param oldScrollY Previous vertical scroll origin.
18852          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)18853         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
18854     }
18855 
18856     /**
18857      * Interface definition for a callback to be invoked when the layout bounds of a view
18858      * changes due to layout processing.
18859      */
18860     public interface OnLayoutChangeListener {
18861         /**
18862          * Called when the layout bounds of a view changes due to layout processing.
18863          *
18864          * @param v The view whose bounds have changed.
18865          * @param left The new value of the view's left property.
18866          * @param top The new value of the view's top property.
18867          * @param right The new value of the view's right property.
18868          * @param bottom The new value of the view's bottom property.
18869          * @param oldLeft The previous value of the view's left property.
18870          * @param oldTop The previous value of the view's top property.
18871          * @param oldRight The previous value of the view's right property.
18872          * @param oldBottom The previous value of the view's bottom property.
18873          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)18874         void onLayoutChange(View v, int left, int top, int right, int bottom,
18875             int oldLeft, int oldTop, int oldRight, int oldBottom);
18876     }
18877 
18878     /**
18879      * This is called during layout when the size of this view has changed. If
18880      * you were just added to the view hierarchy, you're called with the old
18881      * values of 0.
18882      *
18883      * @param w Current width of this view.
18884      * @param h Current height of this view.
18885      * @param oldw Old width of this view.
18886      * @param oldh Old height of this view.
18887      */
onSizeChanged(int w, int h, int oldw, int oldh)18888     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
18889     }
18890 
18891     /**
18892      * Called by draw to draw the child views. This may be overridden
18893      * by derived classes to gain control just before its children are drawn
18894      * (but after its own view has been drawn).
18895      * @param canvas the canvas on which to draw the view
18896      */
dispatchDraw(@onNull Canvas canvas)18897     protected void dispatchDraw(@NonNull Canvas canvas) {
18898 
18899     }
18900 
18901     /**
18902      * Gets the parent of this view. Note that the parent is a
18903      * ViewParent and not necessarily a View.
18904      *
18905      * @return Parent of this view.
18906      */
getParent()18907     public final ViewParent getParent() {
18908         return mParent;
18909     }
18910 
18911     /**
18912      * Set the horizontal scrolled position of your view. This will cause a call to
18913      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18914      * invalidated.
18915      * @param value the x position to scroll to
18916      */
setScrollX(int value)18917     public void setScrollX(int value) {
18918         scrollTo(value, mScrollY);
18919     }
18920 
18921     /**
18922      * Set the vertical scrolled position of your view. This will cause a call to
18923      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18924      * invalidated.
18925      * @param value the y position to scroll to
18926      */
setScrollY(int value)18927     public void setScrollY(int value) {
18928         scrollTo(mScrollX, value);
18929     }
18930 
18931     /**
18932      * Return the scrolled left position of this view. This is the left edge of
18933      * the displayed part of your view. You do not need to draw any pixels
18934      * farther left, since those are outside of the frame of your view on
18935      * screen.
18936      *
18937      * @return The left edge of the displayed part of your view, in pixels.
18938      */
18939     @InspectableProperty
getScrollX()18940     public final int getScrollX() {
18941         return mScrollX;
18942     }
18943 
18944     /**
18945      * Return the scrolled top position of this view. This is the top edge of
18946      * the displayed part of your view. You do not need to draw any pixels above
18947      * it, since those are outside of the frame of your view on screen.
18948      *
18949      * @return The top edge of the displayed part of your view, in pixels.
18950      */
18951     @InspectableProperty
getScrollY()18952     public final int getScrollY() {
18953         return mScrollY;
18954     }
18955 
18956     /**
18957      * Return the width of your view.
18958      *
18959      * @return The width of your view, in pixels.
18960      */
18961     @ViewDebug.ExportedProperty(category = "layout")
getWidth()18962     public final int getWidth() {
18963         return mRight - mLeft;
18964     }
18965 
18966     /**
18967      * Return the height of your view.
18968      *
18969      * @return The height of your view, in pixels.
18970      */
18971     @ViewDebug.ExportedProperty(category = "layout")
getHeight()18972     public final int getHeight() {
18973         return mBottom - mTop;
18974     }
18975 
18976     /**
18977      * Return the visible drawing bounds of your view. Fills in the output
18978      * rectangle with the values from getScrollX(), getScrollY(),
18979      * getWidth(), and getHeight(). These bounds do not account for any
18980      * transformation properties currently set on the view, such as
18981      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
18982      *
18983      * @param outRect The (scrolled) drawing bounds of the view.
18984      */
getDrawingRect(Rect outRect)18985     public void getDrawingRect(Rect outRect) {
18986         outRect.left = mScrollX;
18987         outRect.top = mScrollY;
18988         outRect.right = mScrollX + (mRight - mLeft);
18989         outRect.bottom = mScrollY + (mBottom - mTop);
18990     }
18991 
18992     /**
18993      * Like {@link #getMeasuredWidthAndState()}, but only returns the
18994      * raw width component (that is the result is masked by
18995      * {@link #MEASURED_SIZE_MASK}).
18996      *
18997      * @return The raw measured width of this view.
18998      */
getMeasuredWidth()18999     public final int getMeasuredWidth() {
19000         return mMeasuredWidth & MEASURED_SIZE_MASK;
19001     }
19002 
19003     /**
19004      * Return the full width measurement information for this view as computed
19005      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
19006      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
19007      * This should be used during measurement and layout calculations only. Use
19008      * {@link #getWidth()} to see how wide a view is after layout.
19009      *
19010      * @return The measured width of this view as a bit mask.
19011      */
19012     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
19013             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
19014                     name = "MEASURED_STATE_TOO_SMALL"),
19015     })
getMeasuredWidthAndState()19016     public final int getMeasuredWidthAndState() {
19017         return mMeasuredWidth;
19018     }
19019 
19020     /**
19021      * Like {@link #getMeasuredHeightAndState()}, but only returns the
19022      * raw height component (that is the result is masked by
19023      * {@link #MEASURED_SIZE_MASK}).
19024      *
19025      * @return The raw measured height of this view.
19026      */
getMeasuredHeight()19027     public final int getMeasuredHeight() {
19028         return mMeasuredHeight & MEASURED_SIZE_MASK;
19029     }
19030 
19031     /**
19032      * Return the full height measurement information for this view as computed
19033      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
19034      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
19035      * This should be used during measurement and layout calculations only. Use
19036      * {@link #getHeight()} to see how high a view is after layout.
19037      *
19038      * @return The measured height of this view as a bit mask.
19039      */
19040     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
19041             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
19042                     name = "MEASURED_STATE_TOO_SMALL"),
19043     })
getMeasuredHeightAndState()19044     public final int getMeasuredHeightAndState() {
19045         return mMeasuredHeight;
19046     }
19047 
19048     /**
19049      * Return only the state bits of {@link #getMeasuredWidthAndState()}
19050      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
19051      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
19052      * and the height component is at the shifted bits
19053      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
19054      */
getMeasuredState()19055     public final int getMeasuredState() {
19056         return (mMeasuredWidth&MEASURED_STATE_MASK)
19057                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
19058                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
19059     }
19060 
19061     /**
19062      * The transform matrix of this view, which is calculated based on the current
19063      * rotation, scale, and pivot properties.
19064      *
19065      * @see #getRotation()
19066      * @see #getScaleX()
19067      * @see #getScaleY()
19068      * @see #getPivotX()
19069      * @see #getPivotY()
19070      * @return The current transform matrix for the view
19071      */
getMatrix()19072     public Matrix getMatrix() {
19073         ensureTransformationInfo();
19074         final Matrix matrix = mTransformationInfo.mMatrix;
19075         mRenderNode.getMatrix(matrix);
19076         return matrix;
19077     }
19078 
19079     /**
19080      * Returns true if the transform matrix is the identity matrix.
19081      * Recomputes the matrix if necessary.
19082      *
19083      * @return True if the transform matrix is the identity matrix, false otherwise.
19084      * @hide
19085      */
19086     @UnsupportedAppUsage
hasIdentityMatrix()19087     public final boolean hasIdentityMatrix() {
19088         return mRenderNode.hasIdentityMatrix();
19089     }
19090 
19091     @UnsupportedAppUsage
ensureTransformationInfo()19092     void ensureTransformationInfo() {
19093         if (mTransformationInfo == null) {
19094             mTransformationInfo = new TransformationInfo();
19095         }
19096     }
19097 
19098     /**
19099      * Utility method to retrieve the inverse of the current mMatrix property.
19100      * We cache the matrix to avoid recalculating it when transform properties
19101      * have not changed.
19102      *
19103      * @return The inverse of the current matrix of this view.
19104      * @hide
19105      */
19106     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getInverseMatrix()19107     public final Matrix getInverseMatrix() {
19108         ensureTransformationInfo();
19109         if (mTransformationInfo.mInverseMatrix == null) {
19110             mTransformationInfo.mInverseMatrix = new Matrix();
19111         }
19112         final Matrix matrix = mTransformationInfo.mInverseMatrix;
19113         mRenderNode.getInverseMatrix(matrix);
19114         return matrix;
19115     }
19116 
19117     /**
19118      * Gets the distance along the Z axis from the camera to this view.
19119      *
19120      * @see #setCameraDistance(float)
19121      *
19122      * @return The distance along the Z axis.
19123      */
getCameraDistance()19124     public float getCameraDistance() {
19125         final float dpi = mResources.getDisplayMetrics().densityDpi;
19126         return mRenderNode.getCameraDistance() * dpi;
19127     }
19128 
19129     /**
19130      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
19131      * views are drawn) from the camera to this view. The camera's distance
19132      * affects 3D transformations, for instance rotations around the X and Y
19133      * axis. If the rotationX or rotationY properties are changed and this view is
19134      * large (more than half the size of the screen), it is recommended to always
19135      * use a camera distance that's greater than the height (X axis rotation) or
19136      * the width (Y axis rotation) of this view.</p>
19137      *
19138      * <p>The distance of the camera from the view plane can have an affect on the
19139      * perspective distortion of the view when it is rotated around the x or y axis.
19140      * For example, a large distance will result in a large viewing angle, and there
19141      * will not be much perspective distortion of the view as it rotates. A short
19142      * distance may cause much more perspective distortion upon rotation, and can
19143      * also result in some drawing artifacts if the rotated view ends up partially
19144      * behind the camera (which is why the recommendation is to use a distance at
19145      * least as far as the size of the view, if the view is to be rotated.)</p>
19146      *
19147      * <p>The distance is expressed in "depth pixels." The default distance depends
19148      * on the screen density. For instance, on a medium density display, the
19149      * default distance is 1280. On a high density display, the default distance
19150      * is 1920.</p>
19151      *
19152      * <p>If you want to specify a distance that leads to visually consistent
19153      * results across various densities, use the following formula:</p>
19154      * <pre>
19155      * float scale = context.getResources().getDisplayMetrics().density;
19156      * view.setCameraDistance(distance * scale);
19157      * </pre>
19158      *
19159      * <p>The density scale factor of a high density display is 1.5,
19160      * and 1920 = 1280 * 1.5.</p>
19161      *
19162      * @param distance The distance in "depth pixels", if negative the opposite
19163      *        value is used
19164      *
19165      * @see #setRotationX(float)
19166      * @see #setRotationY(float)
19167      */
setCameraDistance(float distance)19168     public void setCameraDistance(float distance) {
19169         final float dpi = mResources.getDisplayMetrics().densityDpi;
19170 
19171         invalidateViewProperty(true, false);
19172         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
19173         invalidateViewProperty(false, false);
19174 
19175         invalidateParentIfNeededAndWasQuickRejected();
19176     }
19177 
19178     /**
19179      * The degrees that the view is rotated around the pivot point.
19180      *
19181      * @see #setRotation(float)
19182      * @see #getPivotX()
19183      * @see #getPivotY()
19184      *
19185      * @return The degrees of rotation.
19186      */
19187     @ViewDebug.ExportedProperty(category = "drawing")
19188     @InspectableProperty
getRotation()19189     public float getRotation() {
19190         return mRenderNode.getRotationZ();
19191     }
19192 
19193     /**
19194      * Sets the degrees that the view is rotated around the pivot point. Increasing values
19195      * result in clockwise rotation.
19196      *
19197      * @param rotation The degrees of rotation.
19198      *
19199      * @see #getRotation()
19200      * @see #getPivotX()
19201      * @see #getPivotY()
19202      * @see #setRotationX(float)
19203      * @see #setRotationY(float)
19204      *
19205      * @attr ref android.R.styleable#View_rotation
19206      */
19207     @RemotableViewMethod
setRotation(float rotation)19208     public void setRotation(float rotation) {
19209         if (rotation != getRotation()) {
19210             // Double-invalidation is necessary to capture view's old and new areas
19211             invalidateViewProperty(true, false);
19212             mRenderNode.setRotationZ(rotation);
19213             invalidateViewProperty(false, true);
19214 
19215             invalidateParentIfNeededAndWasQuickRejected();
19216             notifySubtreeAccessibilityStateChangedIfNeeded();
19217         }
19218     }
19219 
19220     /**
19221      * The degrees that the view is rotated around the vertical axis through the pivot point.
19222      *
19223      * @see #getPivotX()
19224      * @see #getPivotY()
19225      * @see #setRotationY(float)
19226      *
19227      * @return The degrees of Y rotation.
19228      */
19229     @ViewDebug.ExportedProperty(category = "drawing")
19230     @InspectableProperty
getRotationY()19231     public float getRotationY() {
19232         return mRenderNode.getRotationY();
19233     }
19234 
19235     /**
19236      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
19237      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
19238      * down the y axis.
19239      *
19240      * When rotating large views, it is recommended to adjust the camera distance
19241      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
19242      *
19243      * @param rotationY The degrees of Y rotation.
19244      *
19245      * @see #getRotationY()
19246      * @see #getPivotX()
19247      * @see #getPivotY()
19248      * @see #setRotation(float)
19249      * @see #setRotationX(float)
19250      * @see #setCameraDistance(float)
19251      *
19252      * @attr ref android.R.styleable#View_rotationY
19253      */
19254     @RemotableViewMethod
setRotationY(float rotationY)19255     public void setRotationY(float rotationY) {
19256         if (rotationY != getRotationY()) {
19257             invalidateViewProperty(true, false);
19258             mRenderNode.setRotationY(rotationY);
19259             invalidateViewProperty(false, true);
19260 
19261             invalidateParentIfNeededAndWasQuickRejected();
19262             notifySubtreeAccessibilityStateChangedIfNeeded();
19263         }
19264     }
19265 
19266     /**
19267      * The degrees that the view is rotated around the horizontal axis through the pivot point.
19268      *
19269      * @see #getPivotX()
19270      * @see #getPivotY()
19271      * @see #setRotationX(float)
19272      *
19273      * @return The degrees of X rotation.
19274      */
19275     @ViewDebug.ExportedProperty(category = "drawing")
19276     @InspectableProperty
getRotationX()19277     public float getRotationX() {
19278         return mRenderNode.getRotationX();
19279     }
19280 
19281     /**
19282      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
19283      * Increasing values result in clockwise rotation from the viewpoint of looking down the
19284      * x axis.
19285      *
19286      * When rotating large views, it is recommended to adjust the camera distance
19287      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
19288      *
19289      * @param rotationX The degrees of X rotation.
19290      *
19291      * @see #getRotationX()
19292      * @see #getPivotX()
19293      * @see #getPivotY()
19294      * @see #setRotation(float)
19295      * @see #setRotationY(float)
19296      * @see #setCameraDistance(float)
19297      *
19298      * @attr ref android.R.styleable#View_rotationX
19299      */
19300     @RemotableViewMethod
setRotationX(float rotationX)19301     public void setRotationX(float rotationX) {
19302         if (rotationX != getRotationX()) {
19303             invalidateViewProperty(true, false);
19304             mRenderNode.setRotationX(rotationX);
19305             invalidateViewProperty(false, true);
19306 
19307             invalidateParentIfNeededAndWasQuickRejected();
19308             notifySubtreeAccessibilityStateChangedIfNeeded();
19309         }
19310     }
19311 
19312     /**
19313      * The amount that the view is scaled in x around the pivot point, as a proportion of
19314      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
19315      *
19316      * <p>By default, this is 1.0f.
19317      *
19318      * @see #getPivotX()
19319      * @see #getPivotY()
19320      * @return The scaling factor.
19321      */
19322     @ViewDebug.ExportedProperty(category = "drawing")
19323     @InspectableProperty
getScaleX()19324     public float getScaleX() {
19325         return mRenderNode.getScaleX();
19326     }
19327 
19328     /**
19329      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
19330      * the view's unscaled width. A value of 1 means that no scaling is applied.
19331      *
19332      * @param scaleX The scaling factor.
19333      * @see #getPivotX()
19334      * @see #getPivotY()
19335      *
19336      * @attr ref android.R.styleable#View_scaleX
19337      */
19338     @RemotableViewMethod
setScaleX(float scaleX)19339     public void setScaleX(float scaleX) {
19340         if (scaleX != getScaleX()) {
19341             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
19342             invalidateViewProperty(true, false);
19343             mRenderNode.setScaleX(scaleX);
19344             invalidateViewProperty(false, true);
19345 
19346             invalidateParentIfNeededAndWasQuickRejected();
19347             notifySubtreeAccessibilityStateChangedIfNeeded();
19348         }
19349     }
19350 
19351     /**
19352      * The amount that the view is scaled in y around the pivot point, as a proportion of
19353      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
19354      *
19355      * <p>By default, this is 1.0f.
19356      *
19357      * @see #getPivotX()
19358      * @see #getPivotY()
19359      * @return The scaling factor.
19360      */
19361     @ViewDebug.ExportedProperty(category = "drawing")
19362     @InspectableProperty
getScaleY()19363     public float getScaleY() {
19364         return mRenderNode.getScaleY();
19365     }
19366 
19367     /**
19368      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
19369      * the view's unscaled width. A value of 1 means that no scaling is applied.
19370      *
19371      * @param scaleY The scaling factor.
19372      * @see #getPivotX()
19373      * @see #getPivotY()
19374      *
19375      * @attr ref android.R.styleable#View_scaleY
19376      */
19377     @RemotableViewMethod
setScaleY(float scaleY)19378     public void setScaleY(float scaleY) {
19379         if (scaleY != getScaleY()) {
19380             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
19381             invalidateViewProperty(true, false);
19382             mRenderNode.setScaleY(scaleY);
19383             invalidateViewProperty(false, true);
19384 
19385             invalidateParentIfNeededAndWasQuickRejected();
19386             notifySubtreeAccessibilityStateChangedIfNeeded();
19387         }
19388     }
19389 
19390     /**
19391      * The x location of the point around which the view is {@link #setRotation(float) rotated}
19392      * and {@link #setScaleX(float) scaled}.
19393      *
19394      * @see #getRotation()
19395      * @see #getScaleX()
19396      * @see #getScaleY()
19397      * @see #getPivotY()
19398      * @return The x location of the pivot point.
19399      *
19400      * @attr ref android.R.styleable#View_transformPivotX
19401      */
19402     @ViewDebug.ExportedProperty(category = "drawing")
19403     @InspectableProperty(name = "transformPivotX")
getPivotX()19404     public float getPivotX() {
19405         return mRenderNode.getPivotX();
19406     }
19407 
19408     /**
19409      * Sets the x location of the point around which the view is
19410      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
19411      * By default, the pivot point is centered on the object.
19412      * Setting this property disables this behavior and causes the view to use only the
19413      * explicitly set pivotX and pivotY values.
19414      *
19415      * @param pivotX The x location of the pivot point.
19416      * @see #getRotation()
19417      * @see #getScaleX()
19418      * @see #getScaleY()
19419      * @see #getPivotY()
19420      *
19421      * @attr ref android.R.styleable#View_transformPivotX
19422      */
19423     @RemotableViewMethod
setPivotX(float pivotX)19424     public void setPivotX(float pivotX) {
19425         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
19426             invalidateViewProperty(true, false);
19427             mRenderNode.setPivotX(pivotX);
19428             invalidateViewProperty(false, true);
19429 
19430             invalidateParentIfNeededAndWasQuickRejected();
19431         }
19432     }
19433 
19434     /**
19435      * The y location of the point around which the view is {@link #setRotation(float) rotated}
19436      * and {@link #setScaleY(float) scaled}.
19437      *
19438      * @see #getRotation()
19439      * @see #getScaleX()
19440      * @see #getScaleY()
19441      * @see #getPivotY()
19442      * @return The y location of the pivot point.
19443      *
19444      * @attr ref android.R.styleable#View_transformPivotY
19445      */
19446     @ViewDebug.ExportedProperty(category = "drawing")
19447     @InspectableProperty(name = "transformPivotY")
getPivotY()19448     public float getPivotY() {
19449         return mRenderNode.getPivotY();
19450     }
19451 
19452     /**
19453      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
19454      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
19455      * Setting this property disables this behavior and causes the view to use only the
19456      * explicitly set pivotX and pivotY values.
19457      *
19458      * @param pivotY The y location of the pivot point.
19459      * @see #getRotation()
19460      * @see #getScaleX()
19461      * @see #getScaleY()
19462      * @see #getPivotY()
19463      *
19464      * @attr ref android.R.styleable#View_transformPivotY
19465      */
19466     @RemotableViewMethod
setPivotY(float pivotY)19467     public void setPivotY(float pivotY) {
19468         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
19469             invalidateViewProperty(true, false);
19470             mRenderNode.setPivotY(pivotY);
19471             invalidateViewProperty(false, true);
19472 
19473             invalidateParentIfNeededAndWasQuickRejected();
19474         }
19475     }
19476 
19477     /**
19478      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
19479      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
19480      * of the view.
19481      *
19482      * @return True if a pivot has been set, false if the default pivot is being used
19483      */
isPivotSet()19484     public boolean isPivotSet() {
19485         return mRenderNode.isPivotExplicitlySet();
19486     }
19487 
19488     /**
19489      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
19490      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
19491      * and the pivot used for rotation will return to default of being centered on the view.
19492      */
resetPivot()19493     public void resetPivot() {
19494         if (mRenderNode.resetPivot()) {
19495             invalidateViewProperty(false, false);
19496         }
19497     }
19498 
19499     /**
19500      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
19501      * completely transparent and 1 means the view is completely opaque.
19502      *
19503      * <p>By default this is 1.0f.
19504      * @return The opacity of the view.
19505      */
19506     @ViewDebug.ExportedProperty(category = "drawing")
19507     @InspectableProperty
getAlpha()19508     public float getAlpha() {
19509         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
19510     }
19511 
19512     /**
19513      * Sets the behavior for overlapping rendering for this view (see {@link
19514      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
19515      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
19516      * providing the value which is then used internally. That is, when {@link
19517      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
19518      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
19519      * instead.
19520      *
19521      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
19522      * instead of that returned by {@link #hasOverlappingRendering()}.
19523      *
19524      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
19525      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)19526     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
19527         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
19528         if (hasOverlappingRendering) {
19529             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
19530         } else {
19531             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
19532         }
19533     }
19534 
19535     /**
19536      * Returns the value for overlapping rendering that is used internally. This is either
19537      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
19538      * the return value of {@link #hasOverlappingRendering()}, otherwise.
19539      *
19540      * @return The value for overlapping rendering being used internally.
19541      */
getHasOverlappingRendering()19542     public final boolean getHasOverlappingRendering() {
19543         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
19544                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
19545                 hasOverlappingRendering();
19546     }
19547 
19548     /**
19549      * Returns whether this View has content which overlaps.
19550      *
19551      * <p>This function, intended to be overridden by specific View types, is an optimization when
19552      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
19553      * an offscreen buffer and then composited into place, which can be expensive. If the view has
19554      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
19555      * directly. An example of overlapping rendering is a TextView with a background image, such as
19556      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
19557      * ImageView with only the foreground image. The default implementation returns true; subclasses
19558      * should override if they have cases which can be optimized.</p>
19559      *
19560      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
19561      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
19562      *
19563      * @return true if the content in this view might overlap, false otherwise.
19564      */
19565     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()19566     public boolean hasOverlappingRendering() {
19567         return true;
19568     }
19569 
19570     /**
19571      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
19572      * completely transparent and 1 means the view is completely opaque.
19573      *
19574      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
19575      * can have significant performance implications, especially for large views. It is best to use
19576      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
19577      *
19578      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
19579      * strongly recommended for performance reasons to either override
19580      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
19581      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
19582      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
19583      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
19584      * of rendering cost, even for simple or small views. Starting with
19585      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
19586      * applied to the view at the rendering level.</p>
19587      *
19588      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
19589      * responsible for applying the opacity itself.</p>
19590      *
19591      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
19592      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
19593      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
19594      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
19595      *
19596      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
19597      * value will clip a View to its bounds, unless the View returns <code>false</code> from
19598      * {@link #hasOverlappingRendering}.</p>
19599      *
19600      * @param alpha The opacity of the view.
19601      *
19602      * @see #hasOverlappingRendering()
19603      * @see #setLayerType(int, android.graphics.Paint)
19604      *
19605      * @attr ref android.R.styleable#View_alpha
19606      */
19607     @RemotableViewMethod
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)19608     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
19609         ensureTransformationInfo();
19610         if (mTransformationInfo.mAlpha != alpha) {
19611             setAlphaInternal(alpha);
19612             if (onSetAlpha((int) (alpha * 255))) {
19613                 mPrivateFlags |= PFLAG_ALPHA_SET;
19614                 // subclass is handling alpha - don't optimize rendering cache invalidation
19615                 invalidateParentCaches();
19616                 invalidate(true);
19617             } else {
19618                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
19619                 invalidateViewProperty(true, false);
19620                 mRenderNode.setAlpha(getFinalAlpha());
19621             }
19622         }
19623     }
19624 
19625     /**
19626      * Faster version of setAlpha() which performs the same steps except there are
19627      * no calls to invalidate(). The caller of this function should perform proper invalidation
19628      * on the parent and this object. The return value indicates whether the subclass handles
19629      * alpha (the return value for onSetAlpha()).
19630      *
19631      * @param alpha The new value for the alpha property
19632      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
19633      *         the new value for the alpha property is different from the old value
19634      */
19635     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)19636     boolean setAlphaNoInvalidation(float alpha) {
19637         ensureTransformationInfo();
19638         if (mTransformationInfo.mAlpha != alpha) {
19639             setAlphaInternal(alpha);
19640             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
19641             if (subclassHandlesAlpha) {
19642                 mPrivateFlags |= PFLAG_ALPHA_SET;
19643                 return true;
19644             } else {
19645                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
19646                 mRenderNode.setAlpha(getFinalAlpha());
19647             }
19648         }
19649         return false;
19650     }
19651 
setAlphaInternal(float alpha)19652     void setAlphaInternal(float alpha) {
19653         float oldAlpha = mTransformationInfo.mAlpha;
19654         mTransformationInfo.mAlpha = alpha;
19655         // Report visibility changes, which can affect children, to accessibility
19656         if ((alpha == 0) ^ (oldAlpha == 0)) {
19657             notifySubtreeAccessibilityStateChangedIfNeeded();
19658         }
19659     }
19660 
19661     /**
19662      * This property is intended only for use by the Fade transition, which animates it
19663      * to produce a visual translucency that does not side-effect (or get affected by)
19664      * the real alpha property. This value is composited with the other alpha value
19665      * (and the AlphaAnimation value, when that is present) to produce a final visual
19666      * translucency result, which is what is passed into the DisplayList.
19667      */
setTransitionAlpha(float alpha)19668     public void setTransitionAlpha(float alpha) {
19669         ensureTransformationInfo();
19670         if (mTransformationInfo.mTransitionAlpha != alpha) {
19671             mTransformationInfo.mTransitionAlpha = alpha;
19672             mPrivateFlags &= ~PFLAG_ALPHA_SET;
19673             invalidateViewProperty(true, false);
19674             mRenderNode.setAlpha(getFinalAlpha());
19675         }
19676     }
19677 
19678     /**
19679      * Calculates the visual alpha of this view, which is a combination of the actual
19680      * alpha value and the transitionAlpha value (if set).
19681      */
getFinalAlpha()19682     private float getFinalAlpha() {
19683         if (mTransformationInfo != null) {
19684             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
19685         }
19686         return 1;
19687     }
19688 
19689     /**
19690      * This property is intended only for use by the Fade transition, which animates
19691      * it to produce a visual translucency that does not side-effect (or get affected
19692      * by) the real alpha property. This value is composited with the other alpha
19693      * value (and the AlphaAnimation value, when that is present) to produce a final
19694      * visual translucency result, which is what is passed into the DisplayList.
19695      */
19696     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()19697     public float getTransitionAlpha() {
19698         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
19699     }
19700 
19701     /**
19702      * Sets whether or not to allow force dark to apply to this view.
19703      *
19704      * Setting this to false will disable the auto-dark feature on everything this view
19705      * draws, including any descendants.
19706      *
19707      * Setting this to true will allow this view to be automatically made dark, however
19708      * a value of 'true' will not override any 'false' value in its parent chain nor will
19709      * it prevent any 'false' in any of its children.
19710      *
19711      * The default behavior of force dark is also influenced by the Theme's
19712      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
19713      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
19714      *
19715      * @param allow Whether or not to allow force dark.
19716      */
setForceDarkAllowed(boolean allow)19717     public void setForceDarkAllowed(boolean allow) {
19718         if (mRenderNode.setForceDarkAllowed(allow)) {
19719             // Currently toggling force-dark requires a new display list push to apply
19720             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
19721             invalidate();
19722         }
19723     }
19724 
19725     /**
19726      * See {@link #setForceDarkAllowed(boolean)}
19727      *
19728      * @return true if force dark is allowed (default), false if it is disabled
19729      */
19730     @ViewDebug.ExportedProperty(category = "drawing")
19731     @InspectableProperty
isForceDarkAllowed()19732     public boolean isForceDarkAllowed() {
19733         return mRenderNode.isForceDarkAllowed();
19734     }
19735 
19736     /**
19737      * Top position of this view relative to its parent.
19738      *
19739      * @return The top of this view, in pixels.
19740      */
19741     @ViewDebug.CapturedViewProperty
getTop()19742     public final int getTop() {
19743         return mTop;
19744     }
19745 
19746     /**
19747      * Sets the top position of this view relative to its parent. This method is meant to be called
19748      * by the layout system and should not generally be called otherwise, because the property
19749      * may be changed at any time by the layout.
19750      *
19751      * @param top The top of this view, in pixels.
19752      */
setTop(int top)19753     public final void setTop(int top) {
19754         if (top != mTop) {
19755             final boolean matrixIsIdentity = hasIdentityMatrix();
19756             if (matrixIsIdentity) {
19757                 if (mAttachInfo != null) {
19758                     int minTop;
19759                     int yLoc;
19760                     if (top < mTop) {
19761                         minTop = top;
19762                         yLoc = top - mTop;
19763                     } else {
19764                         minTop = mTop;
19765                         yLoc = 0;
19766                     }
19767                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
19768                 }
19769             } else {
19770                 // Double-invalidation is necessary to capture view's old and new areas
19771                 invalidate(true);
19772             }
19773 
19774             int width = mRight - mLeft;
19775             int oldHeight = mBottom - mTop;
19776 
19777             mTop = top;
19778             mRenderNode.setTop(mTop);
19779 
19780             sizeChange(width, mBottom - mTop, width, oldHeight);
19781 
19782             if (!matrixIsIdentity) {
19783                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19784                 invalidate(true);
19785             }
19786             mBackgroundSizeChanged = true;
19787             mDefaultFocusHighlightSizeChanged = true;
19788             if (mForegroundInfo != null) {
19789                 mForegroundInfo.mBoundsChanged = true;
19790             }
19791             invalidateParentIfNeeded();
19792         }
19793     }
19794 
19795     /**
19796      * Bottom position of this view relative to its parent.
19797      *
19798      * @return The bottom of this view, in pixels.
19799      */
19800     @ViewDebug.CapturedViewProperty
getBottom()19801     public final int getBottom() {
19802         return mBottom;
19803     }
19804 
19805     /**
19806      * True if this view has changed since the last time being drawn.
19807      *
19808      * @return The dirty state of this view.
19809      */
isDirty()19810     public boolean isDirty() {
19811         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
19812     }
19813 
19814     /**
19815      * Sets the bottom position of this view relative to its parent. This method is meant to be
19816      * called by the layout system and should not generally be called otherwise, because the
19817      * property may be changed at any time by the layout.
19818      *
19819      * @param bottom The bottom of this view, in pixels.
19820      */
setBottom(int bottom)19821     public final void setBottom(int bottom) {
19822         if (bottom != mBottom) {
19823             final boolean matrixIsIdentity = hasIdentityMatrix();
19824             if (matrixIsIdentity) {
19825                 if (mAttachInfo != null) {
19826                     int maxBottom;
19827                     if (bottom < mBottom) {
19828                         maxBottom = mBottom;
19829                     } else {
19830                         maxBottom = bottom;
19831                     }
19832                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
19833                 }
19834             } else {
19835                 // Double-invalidation is necessary to capture view's old and new areas
19836                 invalidate(true);
19837             }
19838 
19839             int width = mRight - mLeft;
19840             int oldHeight = mBottom - mTop;
19841 
19842             mBottom = bottom;
19843             mRenderNode.setBottom(mBottom);
19844 
19845             sizeChange(width, mBottom - mTop, width, oldHeight);
19846 
19847             if (!matrixIsIdentity) {
19848                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19849                 invalidate(true);
19850             }
19851             mBackgroundSizeChanged = true;
19852             mDefaultFocusHighlightSizeChanged = true;
19853             if (mForegroundInfo != null) {
19854                 mForegroundInfo.mBoundsChanged = true;
19855             }
19856             invalidateParentIfNeeded();
19857         }
19858     }
19859 
19860     /**
19861      * Left position of this view relative to its parent.
19862      *
19863      * @return The left edge of this view, in pixels.
19864      */
19865     @ViewDebug.CapturedViewProperty
getLeft()19866     public final int getLeft() {
19867         return mLeft;
19868     }
19869 
19870     /**
19871      * Sets the left position of this view relative to its parent. This method is meant to be called
19872      * by the layout system and should not generally be called otherwise, because the property
19873      * may be changed at any time by the layout.
19874      *
19875      * @param left The left of this view, in pixels.
19876      */
setLeft(int left)19877     public final void setLeft(int left) {
19878         if (left != mLeft) {
19879             final boolean matrixIsIdentity = hasIdentityMatrix();
19880             if (matrixIsIdentity) {
19881                 if (mAttachInfo != null) {
19882                     int minLeft;
19883                     int xLoc;
19884                     if (left < mLeft) {
19885                         minLeft = left;
19886                         xLoc = left - mLeft;
19887                     } else {
19888                         minLeft = mLeft;
19889                         xLoc = 0;
19890                     }
19891                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
19892                 }
19893             } else {
19894                 // Double-invalidation is necessary to capture view's old and new areas
19895                 invalidate(true);
19896             }
19897 
19898             int oldWidth = mRight - mLeft;
19899             int height = mBottom - mTop;
19900 
19901             mLeft = left;
19902             mRenderNode.setLeft(left);
19903 
19904             sizeChange(mRight - mLeft, height, oldWidth, height);
19905 
19906             if (!matrixIsIdentity) {
19907                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19908                 invalidate(true);
19909             }
19910             mBackgroundSizeChanged = true;
19911             mDefaultFocusHighlightSizeChanged = true;
19912             if (mForegroundInfo != null) {
19913                 mForegroundInfo.mBoundsChanged = true;
19914             }
19915             invalidateParentIfNeeded();
19916         }
19917     }
19918 
19919     /**
19920      * Right position of this view relative to its parent.
19921      *
19922      * @return The right edge of this view, in pixels.
19923      */
19924     @ViewDebug.CapturedViewProperty
getRight()19925     public final int getRight() {
19926         return mRight;
19927     }
19928 
19929     /**
19930      * Sets the right position of this view relative to its parent. This method is meant to be called
19931      * by the layout system and should not generally be called otherwise, because the property
19932      * may be changed at any time by the layout.
19933      *
19934      * @param right The right of this view, in pixels.
19935      */
setRight(int right)19936     public final void setRight(int right) {
19937         if (right != mRight) {
19938             final boolean matrixIsIdentity = hasIdentityMatrix();
19939             if (matrixIsIdentity) {
19940                 if (mAttachInfo != null) {
19941                     int maxRight;
19942                     if (right < mRight) {
19943                         maxRight = mRight;
19944                     } else {
19945                         maxRight = right;
19946                     }
19947                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
19948                 }
19949             } else {
19950                 // Double-invalidation is necessary to capture view's old and new areas
19951                 invalidate(true);
19952             }
19953 
19954             int oldWidth = mRight - mLeft;
19955             int height = mBottom - mTop;
19956 
19957             mRight = right;
19958             mRenderNode.setRight(mRight);
19959 
19960             sizeChange(mRight - mLeft, height, oldWidth, height);
19961 
19962             if (!matrixIsIdentity) {
19963                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
19964                 invalidate(true);
19965             }
19966             mBackgroundSizeChanged = true;
19967             mDefaultFocusHighlightSizeChanged = true;
19968             if (mForegroundInfo != null) {
19969                 mForegroundInfo.mBoundsChanged = true;
19970             }
19971             invalidateParentIfNeeded();
19972         }
19973     }
19974 
sanitizeFloatPropertyValue(float value, String propertyName)19975     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
19976         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
19977     }
19978 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)19979     private static float sanitizeFloatPropertyValue(float value, String propertyName,
19980             float min, float max) {
19981         // The expected "nothing bad happened" path
19982         if (value >= min && value <= max) return value;
19983 
19984         if (value < min || value == Float.NEGATIVE_INFINITY) {
19985             if (sThrowOnInvalidFloatProperties) {
19986                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
19987                         + value + ", the value must be >= " + min);
19988             }
19989             return min;
19990         }
19991 
19992         if (value > max || value == Float.POSITIVE_INFINITY) {
19993             if (sThrowOnInvalidFloatProperties) {
19994                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
19995                         + value + ", the value must be <= " + max);
19996             }
19997             return max;
19998         }
19999 
20000         if (Float.isNaN(value)) {
20001             if (sThrowOnInvalidFloatProperties) {
20002                 throw new IllegalArgumentException(
20003                         "Cannot set '" + propertyName + "' to Float.NaN");
20004             }
20005             return 0; // Unclear which direction this NaN went so... 0?
20006         }
20007 
20008         // Shouldn't be possible to reach this.
20009         throw new IllegalStateException("How do you get here?? " + value);
20010     }
20011 
20012     /**
20013      * The visual x position of this view, in pixels. This is equivalent to the
20014      * {@link #setTranslationX(float) translationX} property plus the current
20015      * {@link #getLeft() left} property.
20016      *
20017      * @return The visual x position of this view, in pixels.
20018      */
20019     @ViewDebug.ExportedProperty(category = "drawing")
getX()20020     public float getX() {
20021         return mLeft + getTranslationX();
20022     }
20023 
20024     /**
20025      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
20026      * {@link #setTranslationX(float) translationX} property to be the difference between
20027      * the x value passed in and the current {@link #getLeft() left} property.
20028      *
20029      * @param x The visual x position of this view, in pixels.
20030      */
setX(float x)20031     public void setX(float x) {
20032         setTranslationX(x - mLeft);
20033     }
20034 
20035     /**
20036      * The visual y position of this view, in pixels. This is equivalent to the
20037      * {@link #setTranslationY(float) translationY} property plus the current
20038      * {@link #getTop() top} property.
20039      *
20040      * @return The visual y position of this view, in pixels.
20041      */
20042     @ViewDebug.ExportedProperty(category = "drawing")
getY()20043     public float getY() {
20044         return mTop + getTranslationY();
20045     }
20046 
20047     /**
20048      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
20049      * {@link #setTranslationY(float) translationY} property to be the difference between
20050      * the y value passed in and the current {@link #getTop() top} property.
20051      *
20052      * @param y The visual y position of this view, in pixels.
20053      */
setY(float y)20054     public void setY(float y) {
20055         setTranslationY(y - mTop);
20056     }
20057 
20058     /**
20059      * The visual z position of this view, in pixels. This is equivalent to the
20060      * {@link #setTranslationZ(float) translationZ} property plus the current
20061      * {@link #getElevation() elevation} property.
20062      *
20063      * @return The visual z position of this view, in pixels.
20064      */
20065     @ViewDebug.ExportedProperty(category = "drawing")
getZ()20066     public float getZ() {
20067         return getElevation() + getTranslationZ();
20068     }
20069 
20070     /**
20071      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
20072      * {@link #setTranslationZ(float) translationZ} property to be the difference between
20073      * the z value passed in and the current {@link #getElevation() elevation} property.
20074      *
20075      * @param z The visual z position of this view, in pixels.
20076      */
setZ(float z)20077     public void setZ(float z) {
20078         setTranslationZ(z - getElevation());
20079     }
20080 
20081     /**
20082      * The base elevation of this view relative to its parent, in pixels.
20083      *
20084      * @return The base depth position of the view, in pixels.
20085      */
20086     @ViewDebug.ExportedProperty(category = "drawing")
20087     @InspectableProperty
getElevation()20088     public float getElevation() {
20089         return mRenderNode.getElevation();
20090     }
20091 
20092     /**
20093      * Sets the base elevation of this view, in pixels.
20094      *
20095      * @attr ref android.R.styleable#View_elevation
20096      */
20097     @RemotableViewMethod
setElevation(float elevation)20098     public void setElevation(float elevation) {
20099         if (elevation != getElevation()) {
20100             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
20101             invalidateViewProperty(true, false);
20102             mRenderNode.setElevation(elevation);
20103             invalidateViewProperty(false, true);
20104 
20105             invalidateParentIfNeededAndWasQuickRejected();
20106         }
20107     }
20108 
20109     /**
20110      * The horizontal location of this view relative to its {@link #getLeft() left} position.
20111      * This position is post-layout, in addition to wherever the object's
20112      * layout placed it.
20113      *
20114      * @return The horizontal position of this view relative to its left position, in pixels.
20115      */
20116     @ViewDebug.ExportedProperty(category = "drawing")
20117     @InspectableProperty
getTranslationX()20118     public float getTranslationX() {
20119         return mRenderNode.getTranslationX();
20120     }
20121 
20122     /**
20123      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
20124      * This effectively positions the object post-layout, in addition to wherever the object's
20125      * layout placed it.
20126      *
20127      * @param translationX The horizontal position of this view relative to its left position,
20128      * in pixels.
20129      *
20130      * @attr ref android.R.styleable#View_translationX
20131      */
20132     @RemotableViewMethod
setTranslationX(float translationX)20133     public void setTranslationX(float translationX) {
20134         if (translationX != getTranslationX()) {
20135             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
20136             invalidateViewProperty(true, false);
20137             mRenderNode.setTranslationX(translationX);
20138             invalidateViewProperty(false, true);
20139 
20140             invalidateParentIfNeededAndWasQuickRejected();
20141             notifySubtreeAccessibilityStateChangedIfNeeded();
20142         }
20143     }
20144 
20145     /**
20146      * The vertical location of this view relative to its {@link #getTop() top} position.
20147      * This position is post-layout, in addition to wherever the object's
20148      * layout placed it.
20149      *
20150      * @return The vertical position of this view relative to its top position,
20151      * in pixels.
20152      */
20153     @ViewDebug.ExportedProperty(category = "drawing")
20154     @InspectableProperty
getTranslationY()20155     public float getTranslationY() {
20156         return mRenderNode.getTranslationY();
20157     }
20158 
20159     /**
20160      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
20161      * This effectively positions the object post-layout, in addition to wherever the object's
20162      * layout placed it.
20163      *
20164      * @param translationY The vertical position of this view relative to its top position,
20165      * in pixels.
20166      *
20167      * @attr ref android.R.styleable#View_translationY
20168      */
20169     @RemotableViewMethod
setTranslationY(float translationY)20170     public void setTranslationY(float translationY) {
20171         if (translationY != getTranslationY()) {
20172             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
20173             invalidateViewProperty(true, false);
20174             mRenderNode.setTranslationY(translationY);
20175             invalidateViewProperty(false, true);
20176 
20177             invalidateParentIfNeededAndWasQuickRejected();
20178             notifySubtreeAccessibilityStateChangedIfNeeded();
20179         }
20180     }
20181 
20182     /**
20183      * The depth location of this view relative to its {@link #getElevation() elevation}.
20184      *
20185      * @return The depth of this view relative to its elevation.
20186      */
20187     @ViewDebug.ExportedProperty(category = "drawing")
20188     @InspectableProperty
getTranslationZ()20189     public float getTranslationZ() {
20190         return mRenderNode.getTranslationZ();
20191     }
20192 
20193     /**
20194      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
20195      *
20196      * @attr ref android.R.styleable#View_translationZ
20197      */
20198     @RemotableViewMethod
setTranslationZ(float translationZ)20199     public void setTranslationZ(float translationZ) {
20200         if (translationZ != getTranslationZ()) {
20201             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
20202             invalidateViewProperty(true, false);
20203             mRenderNode.setTranslationZ(translationZ);
20204             invalidateViewProperty(false, true);
20205 
20206             invalidateParentIfNeededAndWasQuickRejected();
20207         }
20208     }
20209 
20210     /**
20211      * Changes the transformation matrix on the view. This is used in animation frameworks,
20212      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
20213      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
20214      * Application developers should use transformation methods like {@link #setRotation(float)},
20215      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
20216      * and {@link #setTranslationY(float)} (float)}} instead.
20217      *
20218      * @param matrix The matrix, null indicates that the matrix should be cleared.
20219      * @see #getAnimationMatrix()
20220      */
setAnimationMatrix(@ullable Matrix matrix)20221     public void setAnimationMatrix(@Nullable Matrix matrix) {
20222         invalidateViewProperty(true, false);
20223         mRenderNode.setAnimationMatrix(matrix);
20224         invalidateViewProperty(false, true);
20225 
20226         invalidateParentIfNeededAndWasQuickRejected();
20227     }
20228 
20229     /**
20230      * Return the current transformation matrix of the view. This is used in animation frameworks,
20231      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
20232      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
20233      * Application developers should use transformation methods like {@link #setRotation(float)},
20234      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
20235      * and {@link #setTranslationY(float)} (float)}} instead.
20236      *
20237      * @return the Matrix, null indicates there is no transformation
20238      * @see #setAnimationMatrix(Matrix)
20239      */
20240     @Nullable
getAnimationMatrix()20241     public Matrix getAnimationMatrix() {
20242         return mRenderNode.getAnimationMatrix();
20243     }
20244 
20245     /**
20246      * Returns the current StateListAnimator if exists.
20247      *
20248      * @return StateListAnimator or null if it does not exists
20249      * @see    #setStateListAnimator(android.animation.StateListAnimator)
20250      */
20251     @InspectableProperty
getStateListAnimator()20252     public StateListAnimator getStateListAnimator() {
20253         return mStateListAnimator;
20254     }
20255 
20256     /**
20257      * Attaches the provided StateListAnimator to this View.
20258      * <p>
20259      * Any previously attached StateListAnimator will be detached.
20260      *
20261      * @param stateListAnimator The StateListAnimator to update the view
20262      * @see android.animation.StateListAnimator
20263      */
setStateListAnimator(StateListAnimator stateListAnimator)20264     public void setStateListAnimator(StateListAnimator stateListAnimator) {
20265         if (mStateListAnimator == stateListAnimator) {
20266             return;
20267         }
20268         if (mStateListAnimator != null) {
20269             mStateListAnimator.setTarget(null);
20270         }
20271         mStateListAnimator = stateListAnimator;
20272         if (stateListAnimator != null) {
20273             stateListAnimator.setTarget(this);
20274             if (isAttachedToWindow()) {
20275                 stateListAnimator.setState(getDrawableState());
20276             }
20277         }
20278     }
20279 
20280     /**
20281      * Returns whether the Outline should be used to clip the contents of the View.
20282      * <p>
20283      * Note that this flag will only be respected if the View's Outline returns true from
20284      * {@link Outline#canClip()}.
20285      *
20286      * @see #setOutlineProvider(ViewOutlineProvider)
20287      * @see #setClipToOutline(boolean)
20288      */
getClipToOutline()20289     public final boolean getClipToOutline() {
20290         return mRenderNode.getClipToOutline();
20291     }
20292 
20293     /**
20294      * Sets whether the View's Outline should be used to clip the contents of the View.
20295      * <p>
20296      * Only a single non-rectangular clip can be applied on a View at any time.
20297      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
20298      * circular reveal} animation take priority over Outline clipping, and
20299      * child Outline clipping takes priority over Outline clipping done by a
20300      * parent.
20301      * <p>
20302      * Note that this flag will only be respected if the View's Outline returns true from
20303      * {@link Outline#canClip()}.
20304      *
20305      * @see #setOutlineProvider(ViewOutlineProvider)
20306      * @see #getClipToOutline()
20307      *
20308      * @attr ref android.R.styleable#View_clipToOutline
20309      */
20310     @RemotableViewMethod
setClipToOutline(boolean clipToOutline)20311     public void setClipToOutline(boolean clipToOutline) {
20312         damageInParent();
20313         if (getClipToOutline() != clipToOutline) {
20314             mRenderNode.setClipToOutline(clipToOutline);
20315         }
20316     }
20317 
20318     // correspond to the enum values of View_outlineProvider
20319     private static final int PROVIDER_BACKGROUND = 0;
20320     private static final int PROVIDER_NONE = 1;
20321     private static final int PROVIDER_BOUNDS = 2;
20322     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)20323     private void setOutlineProviderFromAttribute(int providerInt) {
20324         switch (providerInt) {
20325             case PROVIDER_BACKGROUND:
20326                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
20327                 break;
20328             case PROVIDER_NONE:
20329                 setOutlineProvider(null);
20330                 break;
20331             case PROVIDER_BOUNDS:
20332                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
20333                 break;
20334             case PROVIDER_PADDED_BOUNDS:
20335                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
20336                 break;
20337         }
20338     }
20339 
20340     /**
20341      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
20342      * the shape of the shadow it casts, and enables outline clipping.
20343      * <p>
20344      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
20345      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
20346      * outline provider with this method allows this behavior to be overridden.
20347      * <p>
20348      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
20349      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
20350      * <p>
20351      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
20352      *
20353      * @see #setClipToOutline(boolean)
20354      * @see #getClipToOutline()
20355      * @see #getOutlineProvider()
20356      */
setOutlineProvider(ViewOutlineProvider provider)20357     public void setOutlineProvider(ViewOutlineProvider provider) {
20358         if (mOutlineProvider != provider) {
20359             mOutlineProvider = provider;
20360             invalidateOutline();
20361         }
20362     }
20363 
20364     /**
20365      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
20366      * that defines the shape of the shadow it casts, and enables outline clipping.
20367      *
20368      * @see #setOutlineProvider(ViewOutlineProvider)
20369      */
20370     @InspectableProperty
getOutlineProvider()20371     public ViewOutlineProvider getOutlineProvider() {
20372         return mOutlineProvider;
20373     }
20374 
20375     /**
20376      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
20377      *
20378      * @see #setOutlineProvider(ViewOutlineProvider)
20379      */
invalidateOutline()20380     public void invalidateOutline() {
20381         rebuildOutline();
20382 
20383         notifySubtreeAccessibilityStateChangedIfNeeded();
20384         invalidateViewProperty(false, false);
20385     }
20386 
20387     /**
20388      * Internal version of {@link #invalidateOutline()} which invalidates the
20389      * outline without invalidating the view itself. This is intended to be called from
20390      * within methods in the View class itself which are the result of the view being
20391      * invalidated already. For example, when we are drawing the background of a View,
20392      * we invalidate the outline in case it changed in the meantime, but we do not
20393      * need to invalidate the view because we're already drawing the background as part
20394      * of drawing the view in response to an earlier invalidation of the view.
20395      */
rebuildOutline()20396     private void rebuildOutline() {
20397         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
20398         if (mAttachInfo == null) return;
20399 
20400         if (mOutlineProvider == null) {
20401             // no provider, remove outline
20402             mRenderNode.setOutline(null);
20403         } else {
20404             final Outline outline = mAttachInfo.mTmpOutline;
20405             outline.setEmpty();
20406             outline.setAlpha(1.0f);
20407 
20408             mOutlineProvider.getOutline(this, outline);
20409             mRenderNode.setOutline(outline);
20410         }
20411     }
20412 
20413     /**
20414      * HierarchyViewer only
20415      *
20416      * @hide
20417      */
20418     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()20419     public boolean hasShadow() {
20420         return mRenderNode.hasShadow();
20421     }
20422 
20423     /**
20424      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
20425      * elevation value.
20426      * <p>
20427      * By default the shadow color is black. Generally, this color will be opaque so the intensity
20428      * of the shadow is consistent between different views with different colors.
20429      * <p>
20430      * The opacity of the final spot shadow is a function of the shadow caster height, the
20431      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
20432      * {@link android.R.attr#spotShadowAlpha} theme attribute.
20433      *
20434      * @attr ref android.R.styleable#View_outlineSpotShadowColor
20435      * @param color The color this View will cast for its elevation spot shadow.
20436      */
setOutlineSpotShadowColor(@olorInt int color)20437     public void setOutlineSpotShadowColor(@ColorInt int color) {
20438         if (mRenderNode.setSpotShadowColor(color)) {
20439             invalidateViewProperty(true, true);
20440         }
20441     }
20442 
20443     /**
20444      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
20445      * was set
20446      */
20447     @InspectableProperty
getOutlineSpotShadowColor()20448     public @ColorInt int getOutlineSpotShadowColor() {
20449         return mRenderNode.getSpotShadowColor();
20450     }
20451 
20452     /**
20453      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
20454      * elevation value.
20455      * <p>
20456      * By default the shadow color is black. Generally, this color will be opaque so the intensity
20457      * of the shadow is consistent between different views with different colors.
20458      * <p>
20459      * The opacity of the final ambient shadow is a function of the shadow caster height, the
20460      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
20461      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
20462      *
20463      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
20464      * @param color The color this View will cast for its elevation shadow.
20465      */
setOutlineAmbientShadowColor(@olorInt int color)20466     public void setOutlineAmbientShadowColor(@ColorInt int color) {
20467         if (mRenderNode.setAmbientShadowColor(color)) {
20468             invalidateViewProperty(true, true);
20469         }
20470     }
20471 
20472     /**
20473      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
20474      * nothing was set
20475      */
20476     @InspectableProperty
getOutlineAmbientShadowColor()20477     public @ColorInt int getOutlineAmbientShadowColor() {
20478         return mRenderNode.getAmbientShadowColor();
20479     }
20480 
20481 
20482     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)20483     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
20484         mRenderNode.setRevealClip(shouldClip, x, y, radius);
20485         invalidateViewProperty(false, false);
20486     }
20487 
20488     /**
20489      * Hit rectangle in parent's coordinates
20490      *
20491      * @param outRect The hit rectangle of the view.
20492      */
getHitRect(Rect outRect)20493     public void getHitRect(Rect outRect) {
20494         if (hasIdentityMatrix() || mAttachInfo == null) {
20495             outRect.set(mLeft, mTop, mRight, mBottom);
20496         } else {
20497             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
20498             tmpRect.set(0, 0, getWidth(), getHeight());
20499             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
20500             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
20501                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
20502         }
20503     }
20504 
20505     /**
20506      * Determines whether the given point, in local coordinates is inside the view.
20507      */
pointInView(float localX, float localY)20508     /*package*/ final boolean pointInView(float localX, float localY) {
20509         return pointInView(localX, localY, 0);
20510     }
20511 
20512     /**
20513      * Utility method to determine whether the given point, in local coordinates,
20514      * is inside the view, where the area of the view is expanded by the slop factor.
20515      * This method is called while processing touch-move events to determine if the event
20516      * is still within the view.
20517      *
20518      * @hide
20519      */
20520     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)20521     public boolean pointInView(float localX, float localY, float slop) {
20522         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
20523                 localY < ((mBottom - mTop) + slop);
20524     }
20525 
20526     /**
20527      * When a view has focus and the user navigates away from it, the next view is searched for
20528      * starting from the rectangle filled in by this method.
20529      *
20530      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
20531      * of the view.  However, if your view maintains some idea of internal selection,
20532      * such as a cursor, or a selected row or column, you should override this method and
20533      * fill in a more specific rectangle.
20534      *
20535      * @param r The rectangle to fill in, in this view's coordinates.
20536      */
getFocusedRect(Rect r)20537     public void getFocusedRect(Rect r) {
20538         getDrawingRect(r);
20539     }
20540 
20541     /**
20542      * Sets {@code r} to the coordinates of the non-clipped area of this view in
20543      * the coordinate space of the view's root view. Sets {@code globalOffset}
20544      * to the offset of the view's x and y coordinates from the coordinate space
20545      * origin, which is the top left corner of the root view irrespective of
20546      * screen decorations and system UI elements.
20547      *
20548      * <p>To convert {@code r} to coordinates relative to the top left corner of
20549      * this view (without taking view rotations into account), offset {@code r}
20550      * by the inverse values of
20551      * {@code globalOffset}&mdash;{@code r.offset(-globalOffset.x,
20552      * -globalOffset.y)}&mdash;which is equivalent to calling
20553      * {@link #getLocalVisibleRect(Rect) getLocalVisibleRect(Rect)}.
20554      *
20555      * <p><b>Note:</b> Do not use this method to determine the size of a window
20556      * in multi-window mode; use
20557      * {@link WindowManager#getCurrentWindowMetrics()}.
20558      *
20559      * @param r If the method returns true, contains the coordinates of the
20560      *      visible portion of this view in the coordinate space of the view's
20561      *      root view. If the method returns false, the contents of {@code r}
20562      *      are undefined.
20563      * @param globalOffset If the method returns true, contains the offset of
20564      *      the x and y coordinates of this view from the top left corner of the
20565      *      view's root view. If the method returns false, the contents of
20566      *      {@code globalOffset} are undefined. The argument can be null (see
20567      *      {@link #getGlobalVisibleRect(Rect) getGlobalVisibleRect(Rect)}.
20568      * @return true if at least part of the view is visible within the root
20569      *      view; false if the view is completely clipped or translated out of
20570      *      the visible area of the root view.
20571      *
20572      * @see #getLocalVisibleRect(Rect)
20573      */
getGlobalVisibleRect(Rect r, Point globalOffset)20574     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
20575         int width = mRight - mLeft;
20576         int height = mBottom - mTop;
20577         if (width > 0 && height > 0) {
20578             r.set(0, 0, width, height);
20579             if (globalOffset != null) {
20580                 globalOffset.set(-mScrollX, -mScrollY);
20581             }
20582             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
20583         }
20584         return false;
20585     }
20586 
20587     /**
20588      * Sets {@code r} to the coordinates of the non-clipped area of this view in
20589      * the coordinate space of the view's root view.
20590      *
20591      * <p>See {@link #getGlobalVisibleRect(Rect, Point)
20592      * getGlobalVisibleRect(Rect, Point)} for more information.
20593      *
20594      * @param r If the method returns true, contains the coordinates of the
20595      *      visible portion of this view in the coordinate space of the view's
20596      *      root view. If the method returns false, the contents of {@code r}
20597      *      are undefined.
20598      * @return true if at least part of the view is visible within the root
20599      *      view; otherwise false.
20600      */
getGlobalVisibleRect(Rect r)20601     public final boolean getGlobalVisibleRect(Rect r) {
20602         return getGlobalVisibleRect(r, null);
20603     }
20604 
20605     /**
20606      * Sets {@code r} to the coordinates of the non-clipped area of this view
20607      * relative to the top left corner of the view.
20608      *
20609      * <p>If the view is clipped on the left or top, the left and top
20610      * coordinates are offset from 0 by the clipped amount. For example, if the
20611      * view is off screen 50px on the left and 30px at the top, the left and top
20612      * coordinates are 50 and 30 respectively.
20613      *
20614      * <p>If the view is clipped on the right or bottom, the right and bottom
20615      * coordinates are reduced by the clipped amount. For example, if the view
20616      * is off screen 40px on the right and 20px at the bottom, the right
20617      * coordinate is the view width - 40, and the bottom coordinate is the view
20618      * height - 20.
20619      *
20620      * @param r If the method returns true, contains the coordinates of the
20621      *      visible portion of this view relative to the top left corner of the
20622      *      view. If the method returns false, the contents of {@code r} are
20623      *      undefined.
20624      * @return true if at least part of the view is visible; false if the view
20625      *      is completely clipped or translated out of the visible area.
20626      *
20627      * @see #getGlobalVisibleRect(Rect, Point)
20628      */
getLocalVisibleRect(Rect r)20629     public final boolean getLocalVisibleRect(Rect r) {
20630         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
20631         if (getGlobalVisibleRect(r, offset)) {
20632             r.offset(-offset.x, -offset.y); // make r local
20633             return true;
20634         }
20635         return false;
20636     }
20637 
20638     /**
20639      * Offset this view's vertical location by the specified number of pixels.
20640      *
20641      * @param offset the number of pixels to offset the view by
20642      */
offsetTopAndBottom(int offset)20643     public void offsetTopAndBottom(int offset) {
20644         if (offset != 0) {
20645             final boolean matrixIsIdentity = hasIdentityMatrix();
20646             if (matrixIsIdentity) {
20647                 if (isHardwareAccelerated()) {
20648                     invalidateViewProperty(false, false);
20649                 } else {
20650                     final ViewParent p = mParent;
20651                     if (p != null && mAttachInfo != null) {
20652                         final Rect r = mAttachInfo.mTmpInvalRect;
20653                         int minTop;
20654                         int maxBottom;
20655                         int yLoc;
20656                         if (offset < 0) {
20657                             minTop = mTop + offset;
20658                             maxBottom = mBottom;
20659                             yLoc = offset;
20660                         } else {
20661                             minTop = mTop;
20662                             maxBottom = mBottom + offset;
20663                             yLoc = 0;
20664                         }
20665                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
20666                         p.invalidateChild(this, r);
20667                     }
20668                 }
20669             } else {
20670                 invalidateViewProperty(false, false);
20671             }
20672 
20673             mTop += offset;
20674             mBottom += offset;
20675             mRenderNode.offsetTopAndBottom(offset);
20676             if (isHardwareAccelerated()) {
20677                 invalidateViewProperty(false, false);
20678                 invalidateParentIfNeededAndWasQuickRejected();
20679             } else {
20680                 if (!matrixIsIdentity) {
20681                     invalidateViewProperty(false, true);
20682                 }
20683                 invalidateParentIfNeeded();
20684             }
20685             notifySubtreeAccessibilityStateChangedIfNeeded();
20686         }
20687     }
20688 
20689     /**
20690      * Offset this view's horizontal location by the specified amount of pixels.
20691      *
20692      * @param offset the number of pixels to offset the view by
20693      */
offsetLeftAndRight(int offset)20694     public void offsetLeftAndRight(int offset) {
20695         if (offset != 0) {
20696             final boolean matrixIsIdentity = hasIdentityMatrix();
20697             if (matrixIsIdentity) {
20698                 if (isHardwareAccelerated()) {
20699                     invalidateViewProperty(false, false);
20700                 } else {
20701                     final ViewParent p = mParent;
20702                     if (p != null && mAttachInfo != null) {
20703                         final Rect r = mAttachInfo.mTmpInvalRect;
20704                         int minLeft;
20705                         int maxRight;
20706                         if (offset < 0) {
20707                             minLeft = mLeft + offset;
20708                             maxRight = mRight;
20709                         } else {
20710                             minLeft = mLeft;
20711                             maxRight = mRight + offset;
20712                         }
20713                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
20714                         p.invalidateChild(this, r);
20715                     }
20716                 }
20717             } else {
20718                 invalidateViewProperty(false, false);
20719             }
20720 
20721             mLeft += offset;
20722             mRight += offset;
20723             mRenderNode.offsetLeftAndRight(offset);
20724             if (isHardwareAccelerated()) {
20725                 invalidateViewProperty(false, false);
20726                 invalidateParentIfNeededAndWasQuickRejected();
20727             } else {
20728                 if (!matrixIsIdentity) {
20729                     invalidateViewProperty(false, true);
20730                 }
20731                 invalidateParentIfNeeded();
20732             }
20733             notifySubtreeAccessibilityStateChangedIfNeeded();
20734         }
20735     }
20736 
20737     /**
20738      * Get the LayoutParams associated with this view. All views should have
20739      * layout parameters. These supply parameters to the <i>parent</i> of this
20740      * view specifying how it should be arranged. There are many subclasses of
20741      * ViewGroup.LayoutParams, and these correspond to the different subclasses
20742      * of ViewGroup that are responsible for arranging their children.
20743      *
20744      * This method may return null if this View is not attached to a parent
20745      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
20746      * was not invoked successfully. When a View is attached to a parent
20747      * ViewGroup, this method must not return null.
20748      *
20749      * @return The LayoutParams associated with this view, or null if no
20750      *         parameters have been set yet
20751      */
20752     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()20753     public ViewGroup.LayoutParams getLayoutParams() {
20754         return mLayoutParams;
20755     }
20756 
20757     /**
20758      * Set the layout parameters associated with this view. These supply
20759      * parameters to the <i>parent</i> of this view specifying how it should be
20760      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
20761      * correspond to the different subclasses of ViewGroup that are responsible
20762      * for arranging their children.
20763      *
20764      * @param params The layout parameters for this view, cannot be null
20765      */
setLayoutParams(ViewGroup.LayoutParams params)20766     public void setLayoutParams(ViewGroup.LayoutParams params) {
20767         if (params == null) {
20768             throw new NullPointerException("Layout parameters cannot be null");
20769         }
20770         mLayoutParams = params;
20771         resolveLayoutParams();
20772         if (mParent instanceof ViewGroup) {
20773             ((ViewGroup) mParent).onSetLayoutParams(this, params);
20774         }
20775         requestLayout();
20776     }
20777 
20778     /**
20779      * Resolve the layout parameters depending on the resolved layout direction
20780      *
20781      * @hide
20782      */
resolveLayoutParams()20783     public void resolveLayoutParams() {
20784         if (mLayoutParams != null) {
20785             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
20786         }
20787     }
20788 
20789     /**
20790      * Set the scrolled position of your view. This will cause a call to
20791      * {@link #onScrollChanged(int, int, int, int)} and the view will be
20792      * invalidated.
20793      * @param x the x position to scroll to
20794      * @param y the y position to scroll to
20795      */
scrollTo(int x, int y)20796     public void scrollTo(int x, int y) {
20797         if (mScrollX != x || mScrollY != y) {
20798             int oldX = mScrollX;
20799             int oldY = mScrollY;
20800             mScrollX = x;
20801             mScrollY = y;
20802             invalidateParentCaches();
20803             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
20804             if (!awakenScrollBars()) {
20805                 postInvalidateOnAnimation();
20806             }
20807         }
20808     }
20809 
20810     /**
20811      * Move the scrolled position of your view. This will cause a call to
20812      * {@link #onScrollChanged(int, int, int, int)} and the view will be
20813      * invalidated.
20814      * @param x the amount of pixels to scroll by horizontally
20815      * @param y the amount of pixels to scroll by vertically
20816      */
scrollBy(int x, int y)20817     public void scrollBy(int x, int y) {
20818         scrollTo(mScrollX + x, mScrollY + y);
20819     }
20820 
20821     /**
20822      * <p>Trigger the scrollbars to draw. When invoked this method starts an
20823      * animation to fade the scrollbars out after a default delay. If a subclass
20824      * provides animated scrolling, the start delay should equal the duration
20825      * of the scrolling animation.</p>
20826      *
20827      * <p>The animation starts only if at least one of the scrollbars is
20828      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
20829      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
20830      * this method returns true, and false otherwise. If the animation is
20831      * started, this method calls {@link #invalidate()}; in that case the
20832      * caller should not call {@link #invalidate()}.</p>
20833      *
20834      * <p>This method should be invoked every time a subclass directly updates
20835      * the scroll parameters.</p>
20836      *
20837      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
20838      * and {@link #scrollTo(int, int)}.</p>
20839      *
20840      * @return true if the animation is played, false otherwise
20841      *
20842      * @see #awakenScrollBars(int)
20843      * @see #scrollBy(int, int)
20844      * @see #scrollTo(int, int)
20845      * @see #isHorizontalScrollBarEnabled()
20846      * @see #isVerticalScrollBarEnabled()
20847      * @see #setHorizontalScrollBarEnabled(boolean)
20848      * @see #setVerticalScrollBarEnabled(boolean)
20849      */
awakenScrollBars()20850     protected boolean awakenScrollBars() {
20851         return mScrollCache != null &&
20852                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
20853     }
20854 
20855     /**
20856      * Trigger the scrollbars to draw.
20857      * This method differs from awakenScrollBars() only in its default duration.
20858      * initialAwakenScrollBars() will show the scroll bars for longer than
20859      * usual to give the user more of a chance to notice them.
20860      *
20861      * @return true if the animation is played, false otherwise.
20862      */
initialAwakenScrollBars()20863     private boolean initialAwakenScrollBars() {
20864         return mScrollCache != null &&
20865                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
20866     }
20867 
20868     /**
20869      * <p>
20870      * Trigger the scrollbars to draw. When invoked this method starts an
20871      * animation to fade the scrollbars out after a fixed delay. If a subclass
20872      * provides animated scrolling, the start delay should equal the duration of
20873      * the scrolling animation.
20874      * </p>
20875      *
20876      * <p>
20877      * The animation starts only if at least one of the scrollbars is enabled,
20878      * as specified by {@link #isHorizontalScrollBarEnabled()} and
20879      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
20880      * this method returns true, and false otherwise. If the animation is
20881      * started, this method calls {@link #invalidate()}; in that case the caller
20882      * should not call {@link #invalidate()}.
20883      * </p>
20884      *
20885      * <p>
20886      * This method should be invoked every time a subclass directly updates the
20887      * scroll parameters.
20888      * </p>
20889      *
20890      * @param startDelay the delay, in milliseconds, after which the animation
20891      *        should start; when the delay is 0, the animation starts
20892      *        immediately
20893      * @return true if the animation is played, false otherwise
20894      *
20895      * @see #scrollBy(int, int)
20896      * @see #scrollTo(int, int)
20897      * @see #isHorizontalScrollBarEnabled()
20898      * @see #isVerticalScrollBarEnabled()
20899      * @see #setHorizontalScrollBarEnabled(boolean)
20900      * @see #setVerticalScrollBarEnabled(boolean)
20901      */
awakenScrollBars(int startDelay)20902     protected boolean awakenScrollBars(int startDelay) {
20903         return awakenScrollBars(startDelay, true);
20904     }
20905 
20906     /**
20907      * <p>
20908      * Trigger the scrollbars to draw. When invoked this method starts an
20909      * animation to fade the scrollbars out after a fixed delay. If a subclass
20910      * provides animated scrolling, the start delay should equal the duration of
20911      * the scrolling animation.
20912      * </p>
20913      *
20914      * <p>
20915      * The animation starts only if at least one of the scrollbars is enabled,
20916      * as specified by {@link #isHorizontalScrollBarEnabled()} and
20917      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
20918      * this method returns true, and false otherwise. If the animation is
20919      * started, this method calls {@link #invalidate()} if the invalidate parameter
20920      * is set to true; in that case the caller
20921      * should not call {@link #invalidate()}.
20922      * </p>
20923      *
20924      * <p>
20925      * This method should be invoked every time a subclass directly updates the
20926      * scroll parameters.
20927      * </p>
20928      *
20929      * @param startDelay the delay, in milliseconds, after which the animation
20930      *        should start; when the delay is 0, the animation starts
20931      *        immediately
20932      *
20933      * @param invalidate Whether this method should call invalidate
20934      *
20935      * @return true if the animation is played, false otherwise
20936      *
20937      * @see #scrollBy(int, int)
20938      * @see #scrollTo(int, int)
20939      * @see #isHorizontalScrollBarEnabled()
20940      * @see #isVerticalScrollBarEnabled()
20941      * @see #setHorizontalScrollBarEnabled(boolean)
20942      * @see #setVerticalScrollBarEnabled(boolean)
20943      */
awakenScrollBars(int startDelay, boolean invalidate)20944     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
20945         final ScrollabilityCache scrollCache = mScrollCache;
20946 
20947         if (scrollCache == null || !scrollCache.fadeScrollBars) {
20948             return false;
20949         }
20950 
20951         if (scrollCache.scrollBar == null) {
20952             scrollCache.scrollBar = new ScrollBarDrawable();
20953             scrollCache.scrollBar.setState(getDrawableState());
20954             scrollCache.scrollBar.setCallback(this);
20955         }
20956 
20957         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
20958 
20959             if (invalidate) {
20960                 // Invalidate to show the scrollbars
20961                 postInvalidateOnAnimation();
20962             }
20963 
20964             if (scrollCache.state == ScrollabilityCache.OFF) {
20965                 // FIXME: this is copied from WindowManagerService.
20966                 // We should get this value from the system when it
20967                 // is possible to do so.
20968                 final int KEY_REPEAT_FIRST_DELAY = 750;
20969                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
20970             }
20971 
20972             // Tell mScrollCache when we should start fading. This may
20973             // extend the fade start time if one was already scheduled
20974             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
20975             scrollCache.fadeStartTime = fadeStartTime;
20976             scrollCache.state = ScrollabilityCache.ON;
20977 
20978             // Schedule our fader to run, unscheduling any old ones first
20979             if (mAttachInfo != null) {
20980                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
20981                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
20982             }
20983 
20984             return true;
20985         }
20986 
20987         return false;
20988     }
20989 
20990     /**
20991      * Do not invalidate views which are not visible and which are not running an animation. They
20992      * will not get drawn and they should not set dirty flags as if they will be drawn
20993      */
skipInvalidate()20994     private boolean skipInvalidate() {
20995         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
20996                 (!(mParent instanceof ViewGroup) ||
20997                         !((ViewGroup) mParent).isViewTransitioning(this));
20998     }
20999 
21000     /**
21001      * Mark the area defined by dirty as needing to be drawn. If the view is
21002      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
21003      * point in the future.
21004      * <p>
21005      * This must be called from a UI thread. To call from a non-UI thread, call
21006      * {@link #postInvalidate()}.
21007      * <p>
21008      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
21009      * {@code dirty}.
21010      *
21011      * @param dirty the rectangle representing the bounds of the dirty region
21012      *
21013      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
21014      * the importance of the dirty rectangle. In API 21 the given rectangle is
21015      * ignored entirely in favor of an internally-calculated area instead.
21016      * Because of this, clients are encouraged to just call {@link #invalidate()}.
21017      */
21018     @Deprecated
invalidate(Rect dirty)21019     public void invalidate(Rect dirty) {
21020         final int scrollX = mScrollX;
21021         final int scrollY = mScrollY;
21022         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
21023                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
21024     }
21025 
21026     /**
21027      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
21028      * coordinates of the dirty rect are relative to the view. If the view is
21029      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
21030      * point in the future.
21031      * <p>
21032      * This must be called from a UI thread. To call from a non-UI thread, call
21033      * {@link #postInvalidate()}.
21034      *
21035      * @param l the left position of the dirty region
21036      * @param t the top position of the dirty region
21037      * @param r the right position of the dirty region
21038      * @param b the bottom position of the dirty region
21039      *
21040      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
21041      * the importance of the dirty rectangle. In API 21 the given rectangle is
21042      * ignored entirely in favor of an internally-calculated area instead.
21043      * Because of this, clients are encouraged to just call {@link #invalidate()}.
21044      */
21045     @Deprecated
invalidate(int l, int t, int r, int b)21046     public void invalidate(int l, int t, int r, int b) {
21047         final int scrollX = mScrollX;
21048         final int scrollY = mScrollY;
21049         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
21050     }
21051 
21052     /**
21053      * Invalidate the whole view. If the view is visible,
21054      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
21055      * the future.
21056      * <p>
21057      * This must be called from a UI thread. To call from a non-UI thread, call
21058      * {@link #postInvalidate()}.
21059      */
invalidate()21060     public void invalidate() {
21061         invalidate(true);
21062     }
21063 
21064     /**
21065      * This is where the invalidate() work actually happens. A full invalidate()
21066      * causes the drawing cache to be invalidated, but this function can be
21067      * called with invalidateCache set to false to skip that invalidation step
21068      * for cases that do not need it (for example, a component that remains at
21069      * the same dimensions with the same content).
21070      *
21071      * @param invalidateCache Whether the drawing cache for this view should be
21072      *            invalidated as well. This is usually true for a full
21073      *            invalidate, but may be set to false if the View's contents or
21074      *            dimensions have not changed.
21075      * @hide
21076      */
21077     @UnsupportedAppUsage
invalidate(boolean invalidateCache)21078     public void invalidate(boolean invalidateCache) {
21079         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
21080     }
21081 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)21082     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
21083             boolean fullInvalidate) {
21084         if (mGhostView != null) {
21085             mGhostView.invalidate(true);
21086             return;
21087         }
21088 
21089         if (skipInvalidate()) {
21090             return;
21091         }
21092 
21093         // Reset content capture caches
21094         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
21095         mContentCaptureSessionCached = false;
21096 
21097         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
21098                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
21099                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
21100                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
21101             if (fullInvalidate) {
21102                 mLastIsOpaque = isOpaque();
21103                 mPrivateFlags &= ~PFLAG_DRAWN;
21104             }
21105 
21106             mPrivateFlags |= PFLAG_DIRTY;
21107 
21108             if (invalidateCache) {
21109                 mPrivateFlags |= PFLAG_INVALIDATED;
21110                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
21111             }
21112 
21113             // Propagate the damage rectangle to the parent view.
21114             final AttachInfo ai = mAttachInfo;
21115             final ViewParent p = mParent;
21116             if (p != null && ai != null && l < r && t < b) {
21117                 final Rect damage = ai.mTmpInvalRect;
21118                 damage.set(l, t, r, b);
21119                 p.invalidateChild(this, damage);
21120             }
21121 
21122             // Damage the entire projection receiver, if necessary.
21123             if (mBackground != null && mBackground.isProjected()) {
21124                 final View receiver = getProjectionReceiver();
21125                 if (receiver != null) {
21126                     receiver.damageInParent();
21127                 }
21128             }
21129         }
21130     }
21131 
21132     /**
21133      * @return this view's projection receiver, or {@code null} if none exists
21134      */
getProjectionReceiver()21135     private View getProjectionReceiver() {
21136         ViewParent p = getParent();
21137         while (p != null && p instanceof View) {
21138             final View v = (View) p;
21139             if (v.isProjectionReceiver()) {
21140                 return v;
21141             }
21142             p = p.getParent();
21143         }
21144 
21145         return null;
21146     }
21147 
21148     /**
21149      * @return whether the view is a projection receiver
21150      */
isProjectionReceiver()21151     private boolean isProjectionReceiver() {
21152         return mBackground != null;
21153     }
21154 
21155     /**
21156      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
21157      * set any flags or handle all of the cases handled by the default invalidation methods.
21158      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
21159      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
21160      * walk up the hierarchy, transforming the dirty rect as necessary.
21161      *
21162      * The method also handles normal invalidation logic if display list properties are not
21163      * being used in this view. The invalidateParent and forceRedraw flags are used by that
21164      * backup approach, to handle these cases used in the various property-setting methods.
21165      *
21166      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
21167      * are not being used in this view
21168      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
21169      * list properties are not being used in this view
21170      */
21171     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)21172     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
21173         if (!isHardwareAccelerated()
21174                 || !mRenderNode.hasDisplayList()
21175                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
21176             if (invalidateParent) {
21177                 invalidateParentCaches();
21178             }
21179             if (forceRedraw) {
21180                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
21181             }
21182             invalidate(false);
21183         } else {
21184             damageInParent();
21185         }
21186         mPrivateFlags4 |= PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
21187     }
21188 
21189     /**
21190      * Tells the parent view to damage this view's bounds.
21191      *
21192      * @hide
21193      */
damageInParent()21194     protected void damageInParent() {
21195         if (mParent != null && mAttachInfo != null) {
21196             mParent.onDescendantInvalidated(this, this);
21197         }
21198     }
21199 
21200     /**
21201      * Used to indicate that the parent of this view should clear its caches. This functionality
21202      * is used to force the parent to rebuild its display list (when hardware-accelerated),
21203      * which is necessary when various parent-managed properties of the view change, such as
21204      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
21205      * clears the parent caches and does not causes an invalidate event.
21206      *
21207      * @hide
21208      */
21209     @UnsupportedAppUsage
invalidateParentCaches()21210     protected void invalidateParentCaches() {
21211         if (mParent instanceof View) {
21212             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
21213         }
21214     }
21215 
21216     /**
21217      * Used to indicate that the parent of this view should be invalidated. This functionality
21218      * is used to force the parent to rebuild its display list (when hardware-accelerated),
21219      * which is necessary when various parent-managed properties of the view change, such as
21220      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
21221      * an invalidation event to the parent.
21222      *
21223      * @hide
21224      */
21225     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
invalidateParentIfNeeded()21226     protected void invalidateParentIfNeeded() {
21227         if (isHardwareAccelerated() && mParent instanceof View) {
21228             ((View) mParent).invalidate(true);
21229         }
21230     }
21231 
21232     /**
21233      * @hide
21234      */
invalidateParentIfNeededAndWasQuickRejected()21235     protected void invalidateParentIfNeededAndWasQuickRejected() {
21236         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
21237             // View was rejected last time it was drawn by its parent; this may have changed
21238             invalidateParentIfNeeded();
21239         }
21240     }
21241 
21242     /**
21243      * Indicates whether this View is opaque. An opaque View guarantees that it will
21244      * draw all the pixels overlapping its bounds using a fully opaque color.
21245      *
21246      * Subclasses of View should override this method whenever possible to indicate
21247      * whether an instance is opaque. Opaque Views are treated in a special way by
21248      * the View hierarchy, possibly allowing it to perform optimizations during
21249      * invalidate/draw passes.
21250      *
21251      * @return True if this View is guaranteed to be fully opaque, false otherwise.
21252      */
21253     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()21254     public boolean isOpaque() {
21255         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
21256                 getFinalAlpha() >= 1.0f;
21257     }
21258 
21259     /**
21260      * @hide
21261      */
21262     @UnsupportedAppUsage
computeOpaqueFlags()21263     protected void computeOpaqueFlags() {
21264         // Opaque if:
21265         //   - Has a background
21266         //   - Background is opaque
21267         //   - Doesn't have scrollbars or scrollbars overlay
21268 
21269         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
21270             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
21271         } else {
21272             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
21273         }
21274 
21275         final int flags = mViewFlags;
21276         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
21277                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
21278                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
21279             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
21280         } else {
21281             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
21282         }
21283     }
21284 
21285     /**
21286      * @hide
21287      */
hasOpaqueScrollbars()21288     protected boolean hasOpaqueScrollbars() {
21289         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
21290     }
21291 
21292     /**
21293      * @return A handler associated with the thread running the View. This
21294      * handler can be used to pump events in the UI events queue.
21295      */
getHandler()21296     public Handler getHandler() {
21297         final AttachInfo attachInfo = mAttachInfo;
21298         if (attachInfo != null) {
21299             return attachInfo.mHandler;
21300         }
21301         return null;
21302     }
21303 
21304     /**
21305      * Returns the queue of runnable for this view.
21306      *
21307      * @return the queue of runnables for this view
21308      */
getRunQueue()21309     private HandlerActionQueue getRunQueue() {
21310         if (mRunQueue == null) {
21311             mRunQueue = new HandlerActionQueue();
21312         }
21313         return mRunQueue;
21314     }
21315 
21316     /**
21317      * Gets the view root associated with the View.
21318      * @return The view root, or null if none.
21319      * @hide
21320      */
21321     @UnsupportedAppUsage
getViewRootImpl()21322     public ViewRootImpl getViewRootImpl() {
21323         if (mAttachInfo != null) {
21324             return mAttachInfo.mViewRootImpl;
21325         }
21326         return null;
21327     }
21328 
21329     /**
21330      * @hide
21331      */
21332     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getThreadedRenderer()21333     public ThreadedRenderer getThreadedRenderer() {
21334         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
21335     }
21336 
21337     /**
21338      * <p>Causes the Runnable to be added to the message queue.
21339      * The runnable will be run on the user interface thread.</p>
21340      *
21341      * @param action The Runnable that will be executed.
21342      *
21343      * @return Returns true if the Runnable was successfully placed in to the
21344      *         message queue.  Returns false on failure, usually because the
21345      *         looper processing the message queue is exiting.
21346      *
21347      * @see #postDelayed
21348      * @see #removeCallbacks
21349      */
post(Runnable action)21350     public boolean post(Runnable action) {
21351         final AttachInfo attachInfo = mAttachInfo;
21352         if (attachInfo != null) {
21353             return attachInfo.mHandler.post(action);
21354         }
21355 
21356         // Postpone the runnable until we know on which thread it needs to run.
21357         // Assume that the runnable will be successfully placed after attach.
21358         getRunQueue().post(action);
21359         return true;
21360     }
21361 
21362     /**
21363      * <p>Causes the Runnable to be added to the message queue, to be run
21364      * after the specified amount of time elapses.
21365      * The runnable will be run on the user interface thread.</p>
21366      *
21367      * @param action The Runnable that will be executed.
21368      * @param delayMillis The delay (in milliseconds) until the Runnable
21369      *        will be executed.
21370      *
21371      * @return true if the Runnable was successfully placed in to the
21372      *         message queue.  Returns false on failure, usually because the
21373      *         looper processing the message queue is exiting.  Note that a
21374      *         result of true does not mean the Runnable will be processed --
21375      *         if the looper is quit before the delivery time of the message
21376      *         occurs then the message will be dropped.
21377      *
21378      * @see #post
21379      * @see #removeCallbacks
21380      */
postDelayed(Runnable action, long delayMillis)21381     public boolean postDelayed(Runnable action, long delayMillis) {
21382         final AttachInfo attachInfo = mAttachInfo;
21383         if (attachInfo != null) {
21384             return attachInfo.mHandler.postDelayed(action, delayMillis);
21385         }
21386 
21387         // Postpone the runnable until we know on which thread it needs to run.
21388         // Assume that the runnable will be successfully placed after attach.
21389         getRunQueue().postDelayed(action, delayMillis);
21390         return true;
21391     }
21392 
21393     /**
21394      * <p>Causes the Runnable to execute on the next animation time step.
21395      * The runnable will be run on the user interface thread.</p>
21396      *
21397      * @param action The Runnable that will be executed.
21398      *
21399      * @see #postOnAnimationDelayed
21400      * @see #removeCallbacks
21401      */
postOnAnimation(Runnable action)21402     public void postOnAnimation(Runnable action) {
21403         final AttachInfo attachInfo = mAttachInfo;
21404         if (attachInfo != null) {
21405             attachInfo.mViewRootImpl.mChoreographer.postCallback(
21406                     Choreographer.CALLBACK_ANIMATION, action, null);
21407         } else {
21408             // Postpone the runnable until we know
21409             // on which thread it needs to run.
21410             getRunQueue().post(action);
21411         }
21412     }
21413 
21414     /**
21415      * <p>Causes the Runnable to execute on the next animation time step,
21416      * after the specified amount of time elapses.
21417      * The runnable will be run on the user interface thread.</p>
21418      *
21419      * @param action The Runnable that will be executed.
21420      * @param delayMillis The delay (in milliseconds) until the Runnable
21421      *        will be executed.
21422      *
21423      * @see #postOnAnimation
21424      * @see #removeCallbacks
21425      */
postOnAnimationDelayed(Runnable action, long delayMillis)21426     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
21427         final AttachInfo attachInfo = mAttachInfo;
21428         if (attachInfo != null) {
21429             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
21430                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
21431         } else {
21432             // Postpone the runnable until we know
21433             // on which thread it needs to run.
21434             getRunQueue().postDelayed(action, delayMillis);
21435         }
21436     }
21437 
21438     /**
21439      * <p>Removes the specified Runnable from the message queue.</p>
21440      *
21441      * @param action The Runnable to remove from the message handling queue
21442      *
21443      * @return true if this view could ask the Handler to remove the Runnable,
21444      *         false otherwise. When the returned value is true, the Runnable
21445      *         may or may not have been actually removed from the message queue
21446      *         (for instance, if the Runnable was not in the queue already.)
21447      *
21448      * @see #post
21449      * @see #postDelayed
21450      * @see #postOnAnimation
21451      * @see #postOnAnimationDelayed
21452      */
removeCallbacks(Runnable action)21453     public boolean removeCallbacks(Runnable action) {
21454         if (action != null) {
21455             final AttachInfo attachInfo = mAttachInfo;
21456             if (attachInfo != null) {
21457                 attachInfo.mHandler.removeCallbacks(action);
21458                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
21459                         Choreographer.CALLBACK_ANIMATION, action, null);
21460             }
21461             getRunQueue().removeCallbacks(action);
21462         }
21463         return true;
21464     }
21465 
21466     /**
21467      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
21468      * Use this to invalidate the View from a non-UI thread.</p>
21469      *
21470      * <p>This method can be invoked from outside of the UI thread
21471      * only when this View is attached to a window.</p>
21472      *
21473      * @see #invalidate()
21474      * @see #postInvalidateDelayed(long)
21475      */
postInvalidate()21476     public void postInvalidate() {
21477         postInvalidateDelayed(0);
21478     }
21479 
21480     /**
21481      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
21482      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
21483      *
21484      * <p>This method can be invoked from outside of the UI thread
21485      * only when this View is attached to a window.</p>
21486      *
21487      * @param left The left coordinate of the rectangle to invalidate.
21488      * @param top The top coordinate of the rectangle to invalidate.
21489      * @param right The right coordinate of the rectangle to invalidate.
21490      * @param bottom The bottom coordinate of the rectangle to invalidate.
21491      *
21492      * @see #invalidate(int, int, int, int)
21493      * @see #invalidate(Rect)
21494      * @see #postInvalidateDelayed(long, int, int, int, int)
21495      */
postInvalidate(int left, int top, int right, int bottom)21496     public void postInvalidate(int left, int top, int right, int bottom) {
21497         postInvalidateDelayed(0, left, top, right, bottom);
21498     }
21499 
21500     /**
21501      * <p>Cause an invalidate to happen on a subsequent cycle through the event
21502      * loop. Waits for the specified amount of time.</p>
21503      *
21504      * <p>This method can be invoked from outside of the UI thread
21505      * only when this View is attached to a window.</p>
21506      *
21507      * @param delayMilliseconds the duration in milliseconds to delay the
21508      *         invalidation by
21509      *
21510      * @see #invalidate()
21511      * @see #postInvalidate()
21512      */
postInvalidateDelayed(long delayMilliseconds)21513     public void postInvalidateDelayed(long delayMilliseconds) {
21514         // We try only with the AttachInfo because there's no point in invalidating
21515         // if we are not attached to our window
21516         final AttachInfo attachInfo = mAttachInfo;
21517         if (attachInfo != null) {
21518             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
21519         }
21520     }
21521 
21522     /**
21523      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
21524      * through the event loop. Waits for the specified amount of time.</p>
21525      *
21526      * <p>This method can be invoked from outside of the UI thread
21527      * only when this View is attached to a window.</p>
21528      *
21529      * @param delayMilliseconds the duration in milliseconds to delay the
21530      *         invalidation by
21531      * @param left The left coordinate of the rectangle to invalidate.
21532      * @param top The top coordinate of the rectangle to invalidate.
21533      * @param right The right coordinate of the rectangle to invalidate.
21534      * @param bottom The bottom coordinate of the rectangle to invalidate.
21535      *
21536      * @see #invalidate(int, int, int, int)
21537      * @see #invalidate(Rect)
21538      * @see #postInvalidate(int, int, int, int)
21539      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)21540     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
21541             int right, int bottom) {
21542 
21543         // We try only with the AttachInfo because there's no point in invalidating
21544         // if we are not attached to our window
21545         final AttachInfo attachInfo = mAttachInfo;
21546         if (attachInfo != null) {
21547             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
21548             info.target = this;
21549             info.left = left;
21550             info.top = top;
21551             info.right = right;
21552             info.bottom = bottom;
21553 
21554             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
21555         }
21556     }
21557 
21558     /**
21559      * <p>Cause an invalidate to happen on the next animation time step, typically the
21560      * next display frame.</p>
21561      *
21562      * <p>This method can be invoked from outside of the UI thread
21563      * only when this View is attached to a window.</p>
21564      *
21565      * @see #invalidate()
21566      */
postInvalidateOnAnimation()21567     public void postInvalidateOnAnimation() {
21568         // We try only with the AttachInfo because there's no point in invalidating
21569         // if we are not attached to our window
21570         final AttachInfo attachInfo = mAttachInfo;
21571         if (attachInfo != null) {
21572             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
21573         }
21574     }
21575 
21576     /**
21577      * <p>Cause an invalidate of the specified area to happen on the next animation
21578      * time step, typically the next display frame.</p>
21579      *
21580      * <p>This method can be invoked from outside of the UI thread
21581      * only when this View is attached to a window.</p>
21582      *
21583      * @param left The left coordinate of the rectangle to invalidate.
21584      * @param top The top coordinate of the rectangle to invalidate.
21585      * @param right The right coordinate of the rectangle to invalidate.
21586      * @param bottom The bottom coordinate of the rectangle to invalidate.
21587      *
21588      * @see #invalidate(int, int, int, int)
21589      * @see #invalidate(Rect)
21590      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)21591     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
21592         // We try only with the AttachInfo because there's no point in invalidating
21593         // if we are not attached to our window
21594         final AttachInfo attachInfo = mAttachInfo;
21595         if (attachInfo != null) {
21596             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
21597             info.target = this;
21598             info.left = left;
21599             info.top = top;
21600             info.right = right;
21601             info.bottom = bottom;
21602 
21603             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
21604         }
21605     }
21606 
21607     /**
21608      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
21609      * This event is sent at most once every
21610      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
21611      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)21612     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
21613         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21614             AccessibilityEvent event =
21615                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
21616             event.setScrollDeltaX(dx);
21617             event.setScrollDeltaY(dy);
21618             sendAccessibilityEventUnchecked(event);
21619         }
21620     }
21621 
21622     /**
21623      * Called by a parent to request that a child update its values for mScrollX
21624      * and mScrollY if necessary. This will typically be done if the child is
21625      * animating a scroll using a {@link android.widget.Scroller Scroller}
21626      * object.
21627      */
computeScroll()21628     public void computeScroll() {
21629     }
21630 
21631     /**
21632      * <p>Indicate whether the horizontal edges are faded when the view is
21633      * scrolled horizontally.</p>
21634      *
21635      * @return true if the horizontal edges should are faded on scroll, false
21636      *         otherwise
21637      *
21638      * @see #setHorizontalFadingEdgeEnabled(boolean)
21639      *
21640      * @attr ref android.R.styleable#View_requiresFadingEdge
21641      */
isHorizontalFadingEdgeEnabled()21642     public boolean isHorizontalFadingEdgeEnabled() {
21643         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
21644     }
21645 
21646     /**
21647      * <p>Define whether the horizontal edges should be faded when this view
21648      * is scrolled horizontally.</p>
21649      *
21650      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
21651      *                                    be faded when the view is scrolled
21652      *                                    horizontally
21653      *
21654      * @see #isHorizontalFadingEdgeEnabled()
21655      *
21656      * @attr ref android.R.styleable#View_requiresFadingEdge
21657      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)21658     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
21659         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
21660             if (horizontalFadingEdgeEnabled) {
21661                 initScrollCache();
21662             }
21663 
21664             mViewFlags ^= FADING_EDGE_HORIZONTAL;
21665         }
21666     }
21667 
21668     /**
21669      * <p>Indicate whether the vertical edges are faded when the view is
21670      * scrolled horizontally.</p>
21671      *
21672      * @return true if the vertical edges should are faded on scroll, false
21673      *         otherwise
21674      *
21675      * @see #setVerticalFadingEdgeEnabled(boolean)
21676      *
21677      * @attr ref android.R.styleable#View_requiresFadingEdge
21678      */
isVerticalFadingEdgeEnabled()21679     public boolean isVerticalFadingEdgeEnabled() {
21680         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
21681     }
21682 
21683     /**
21684      * <p>Define whether the vertical edges should be faded when this view
21685      * is scrolled vertically.</p>
21686      *
21687      * @param verticalFadingEdgeEnabled true if the vertical edges should
21688      *                                  be faded when the view is scrolled
21689      *                                  vertically
21690      *
21691      * @see #isVerticalFadingEdgeEnabled()
21692      *
21693      * @attr ref android.R.styleable#View_requiresFadingEdge
21694      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)21695     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
21696         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
21697             if (verticalFadingEdgeEnabled) {
21698                 initScrollCache();
21699             }
21700 
21701             mViewFlags ^= FADING_EDGE_VERTICAL;
21702         }
21703     }
21704 
21705     /**
21706      * Get the fading edge flags, used for inspection.
21707      *
21708      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
21709      *         or {@link #FADING_EDGE_HORIZONTAL}
21710      * @hide
21711      */
21712     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
21713             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
21714             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
21715             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
21716     })
getFadingEdge()21717     public int getFadingEdge() {
21718         return mViewFlags & FADING_EDGE_MASK;
21719     }
21720 
21721     /**
21722      * Get the fading edge length, used for inspection
21723      *
21724      * @return The fading edge length or 0
21725      * @hide
21726      */
21727     @InspectableProperty
getFadingEdgeLength()21728     public int getFadingEdgeLength() {
21729         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
21730             return mScrollCache.fadingEdgeLength;
21731         }
21732         return 0;
21733     }
21734 
21735     /**
21736      * Returns the strength, or intensity, of the top faded edge. The strength is
21737      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21738      * returns 0.0 or 1.0 but no value in between.
21739      *
21740      * Subclasses should override this method to provide a smoother fade transition
21741      * when scrolling occurs.
21742      *
21743      * @return the intensity of the top fade as a float between 0.0f and 1.0f
21744      */
getTopFadingEdgeStrength()21745     protected float getTopFadingEdgeStrength() {
21746         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
21747     }
21748 
21749     /**
21750      * Returns the strength, or intensity, of the bottom faded edge. The strength is
21751      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21752      * returns 0.0 or 1.0 but no value in between.
21753      *
21754      * Subclasses should override this method to provide a smoother fade transition
21755      * when scrolling occurs.
21756      *
21757      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
21758      */
getBottomFadingEdgeStrength()21759     protected float getBottomFadingEdgeStrength() {
21760         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
21761                 computeVerticalScrollRange() ? 1.0f : 0.0f;
21762     }
21763 
21764     /**
21765      * Returns the strength, or intensity, of the left faded edge. The strength is
21766      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21767      * returns 0.0 or 1.0 but no value in between.
21768      *
21769      * Subclasses should override this method to provide a smoother fade transition
21770      * when scrolling occurs.
21771      *
21772      * @return the intensity of the left fade as a float between 0.0f and 1.0f
21773      */
getLeftFadingEdgeStrength()21774     protected float getLeftFadingEdgeStrength() {
21775         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
21776     }
21777 
21778     /**
21779      * Returns the strength, or intensity, of the right faded edge. The strength is
21780      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
21781      * returns 0.0 or 1.0 but no value in between.
21782      *
21783      * Subclasses should override this method to provide a smoother fade transition
21784      * when scrolling occurs.
21785      *
21786      * @return the intensity of the right fade as a float between 0.0f and 1.0f
21787      */
getRightFadingEdgeStrength()21788     protected float getRightFadingEdgeStrength() {
21789         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
21790                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
21791     }
21792 
21793     /**
21794      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
21795      * scrollbar is not drawn by default.</p>
21796      *
21797      * @return true if the horizontal scrollbar should be painted, false
21798      *         otherwise
21799      *
21800      * @see #setHorizontalScrollBarEnabled(boolean)
21801      */
isHorizontalScrollBarEnabled()21802     public boolean isHorizontalScrollBarEnabled() {
21803         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
21804     }
21805 
21806     /**
21807      * <p>Define whether the horizontal scrollbar should be drawn or not. The
21808      * scrollbar is not drawn by default.</p>
21809      *
21810      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
21811      *                                   be painted
21812      *
21813      * @see #isHorizontalScrollBarEnabled()
21814      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)21815     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
21816         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
21817             mViewFlags ^= SCROLLBARS_HORIZONTAL;
21818             computeOpaqueFlags();
21819             resolvePadding();
21820         }
21821     }
21822 
21823     /**
21824      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
21825      * scrollbar is not drawn by default.</p>
21826      *
21827      * @return true if the vertical scrollbar should be painted, false
21828      *         otherwise
21829      *
21830      * @see #setVerticalScrollBarEnabled(boolean)
21831      */
isVerticalScrollBarEnabled()21832     public boolean isVerticalScrollBarEnabled() {
21833         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
21834     }
21835 
21836     /**
21837      * <p>Define whether the vertical scrollbar should be drawn or not. The
21838      * scrollbar is not drawn by default.</p>
21839      *
21840      * @param verticalScrollBarEnabled true if the vertical scrollbar should
21841      *                                 be painted
21842      *
21843      * @see #isVerticalScrollBarEnabled()
21844      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)21845     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
21846         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
21847             mViewFlags ^= SCROLLBARS_VERTICAL;
21848             computeOpaqueFlags();
21849             resolvePadding();
21850         }
21851     }
21852 
21853     /**
21854      * @hide
21855      */
21856     @UnsupportedAppUsage
recomputePadding()21857     protected void recomputePadding() {
21858         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
21859     }
21860 
21861     /**
21862      * Define whether scrollbars will fade when the view is not scrolling.
21863      *
21864      * @param fadeScrollbars whether to enable fading
21865      *
21866      * @attr ref android.R.styleable#View_fadeScrollbars
21867      */
setScrollbarFadingEnabled(boolean fadeScrollbars)21868     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
21869         initScrollCache();
21870         final ScrollabilityCache scrollabilityCache = mScrollCache;
21871         scrollabilityCache.fadeScrollBars = fadeScrollbars;
21872         if (fadeScrollbars) {
21873             scrollabilityCache.state = ScrollabilityCache.OFF;
21874         } else {
21875             scrollabilityCache.state = ScrollabilityCache.ON;
21876         }
21877     }
21878 
21879     /**
21880      *
21881      * Returns true if scrollbars will fade when this view is not scrolling
21882      *
21883      * @return true if scrollbar fading is enabled
21884      *
21885      * @attr ref android.R.styleable#View_fadeScrollbars
21886      */
isScrollbarFadingEnabled()21887     public boolean isScrollbarFadingEnabled() {
21888         return mScrollCache != null && mScrollCache.fadeScrollBars;
21889     }
21890 
21891     /**
21892      *
21893      * Returns the delay before scrollbars fade.
21894      *
21895      * @return the delay before scrollbars fade
21896      *
21897      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
21898      */
21899     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()21900     public int getScrollBarDefaultDelayBeforeFade() {
21901         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
21902                 mScrollCache.scrollBarDefaultDelayBeforeFade;
21903     }
21904 
21905     /**
21906      * Define the delay before scrollbars fade.
21907      *
21908      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
21909      *
21910      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
21911      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)21912     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
21913         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
21914     }
21915 
21916     /**
21917      *
21918      * Returns the scrollbar fade duration.
21919      *
21920      * @return the scrollbar fade duration, in milliseconds
21921      *
21922      * @attr ref android.R.styleable#View_scrollbarFadeDuration
21923      */
21924     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()21925     public int getScrollBarFadeDuration() {
21926         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
21927                 mScrollCache.scrollBarFadeDuration;
21928     }
21929 
21930     /**
21931      * Define the scrollbar fade duration.
21932      *
21933      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
21934      *
21935      * @attr ref android.R.styleable#View_scrollbarFadeDuration
21936      */
setScrollBarFadeDuration(int scrollBarFadeDuration)21937     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
21938         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
21939     }
21940 
21941     /**
21942      *
21943      * Returns the scrollbar size.
21944      *
21945      * @return the scrollbar size
21946      *
21947      * @attr ref android.R.styleable#View_scrollbarSize
21948      */
21949     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()21950     public int getScrollBarSize() {
21951         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
21952                 mScrollCache.scrollBarSize;
21953     }
21954 
21955     /**
21956      * Define the scrollbar size.
21957      *
21958      * @param scrollBarSize - the scrollbar size
21959      *
21960      * @attr ref android.R.styleable#View_scrollbarSize
21961      */
setScrollBarSize(int scrollBarSize)21962     public void setScrollBarSize(int scrollBarSize) {
21963         getScrollCache().scrollBarSize = scrollBarSize;
21964     }
21965 
21966     /**
21967      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
21968      * inset. When inset, they add to the padding of the view. And the scrollbars
21969      * can be drawn inside the padding area or on the edge of the view. For example,
21970      * if a view has a background drawable and you want to draw the scrollbars
21971      * inside the padding specified by the drawable, you can use
21972      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
21973      * appear at the edge of the view, ignoring the padding, then you can use
21974      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
21975      * @param style the style of the scrollbars. Should be one of
21976      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
21977      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
21978      * @see #SCROLLBARS_INSIDE_OVERLAY
21979      * @see #SCROLLBARS_INSIDE_INSET
21980      * @see #SCROLLBARS_OUTSIDE_OVERLAY
21981      * @see #SCROLLBARS_OUTSIDE_INSET
21982      *
21983      * @attr ref android.R.styleable#View_scrollbarStyle
21984      */
setScrollBarStyle(@crollBarStyle int style)21985     public void setScrollBarStyle(@ScrollBarStyle int style) {
21986         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
21987             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
21988             computeOpaqueFlags();
21989             resolvePadding();
21990         }
21991     }
21992 
21993     /**
21994      * <p>Returns the current scrollbar style.</p>
21995      * @return the current scrollbar style
21996      * @see #SCROLLBARS_INSIDE_OVERLAY
21997      * @see #SCROLLBARS_INSIDE_INSET
21998      * @see #SCROLLBARS_OUTSIDE_OVERLAY
21999      * @see #SCROLLBARS_OUTSIDE_INSET
22000      *
22001      * @attr ref android.R.styleable#View_scrollbarStyle
22002      */
22003     @ViewDebug.ExportedProperty(mapping = {
22004             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
22005             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
22006             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
22007             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
22008     })
22009     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
22010             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
22011             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
22012             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
22013             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
22014     })
22015     @ScrollBarStyle
getScrollBarStyle()22016     public int getScrollBarStyle() {
22017         return mViewFlags & SCROLLBARS_STYLE_MASK;
22018     }
22019 
22020     /**
22021      * <p>Compute the horizontal range that the horizontal scrollbar
22022      * represents.</p>
22023      *
22024      * <p>The range is expressed in arbitrary units that must be the same as the
22025      * units used by {@link #computeHorizontalScrollExtent()} and
22026      * {@link #computeHorizontalScrollOffset()}.</p>
22027      *
22028      * <p>The default range is the drawing width of this view.</p>
22029      *
22030      * @return the total horizontal range represented by the horizontal
22031      *         scrollbar
22032      *
22033      * @see #computeHorizontalScrollExtent()
22034      * @see #computeHorizontalScrollOffset()
22035      */
computeHorizontalScrollRange()22036     protected int computeHorizontalScrollRange() {
22037         return getWidth();
22038     }
22039 
22040     /**
22041      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
22042      * within the horizontal range. This value is used to compute the position
22043      * of the thumb within the scrollbar's track.</p>
22044      *
22045      * <p>The range is expressed in arbitrary units that must be the same as the
22046      * units used by {@link #computeHorizontalScrollRange()} and
22047      * {@link #computeHorizontalScrollExtent()}.</p>
22048      *
22049      * <p>The default offset is the scroll offset of this view.</p>
22050      *
22051      * @return the horizontal offset of the scrollbar's thumb
22052      *
22053      * @see #computeHorizontalScrollRange()
22054      * @see #computeHorizontalScrollExtent()
22055      */
computeHorizontalScrollOffset()22056     protected int computeHorizontalScrollOffset() {
22057         return mScrollX;
22058     }
22059 
22060     /**
22061      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
22062      * within the horizontal range. This value is used to compute the length
22063      * of the thumb within the scrollbar's track.</p>
22064      *
22065      * <p>The range is expressed in arbitrary units that must be the same as the
22066      * units used by {@link #computeHorizontalScrollRange()} and
22067      * {@link #computeHorizontalScrollOffset()}.</p>
22068      *
22069      * <p>The default extent is the drawing width of this view.</p>
22070      *
22071      * @return the horizontal extent of the scrollbar's thumb
22072      *
22073      * @see #computeHorizontalScrollRange()
22074      * @see #computeHorizontalScrollOffset()
22075      */
computeHorizontalScrollExtent()22076     protected int computeHorizontalScrollExtent() {
22077         return getWidth();
22078     }
22079 
22080     /**
22081      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
22082      *
22083      * <p>The range is expressed in arbitrary units that must be the same as the
22084      * units used by {@link #computeVerticalScrollExtent()} and
22085      * {@link #computeVerticalScrollOffset()}.</p>
22086      *
22087      * @return the total vertical range represented by the vertical scrollbar
22088      *
22089      * <p>The default range is the drawing height of this view.</p>
22090      *
22091      * @see #computeVerticalScrollExtent()
22092      * @see #computeVerticalScrollOffset()
22093      */
computeVerticalScrollRange()22094     protected int computeVerticalScrollRange() {
22095         return getHeight();
22096     }
22097 
22098     /**
22099      * <p>Compute the vertical offset of the vertical scrollbar's thumb
22100      * within the horizontal range. This value is used to compute the position
22101      * of the thumb within the scrollbar's track.</p>
22102      *
22103      * <p>The range is expressed in arbitrary units that must be the same as the
22104      * units used by {@link #computeVerticalScrollRange()} and
22105      * {@link #computeVerticalScrollExtent()}.</p>
22106      *
22107      * <p>The default offset is the scroll offset of this view.</p>
22108      *
22109      * @return the vertical offset of the scrollbar's thumb
22110      *
22111      * @see #computeVerticalScrollRange()
22112      * @see #computeVerticalScrollExtent()
22113      */
computeVerticalScrollOffset()22114     protected int computeVerticalScrollOffset() {
22115         return mScrollY;
22116     }
22117 
22118     /**
22119      * <p>Compute the vertical extent of the vertical scrollbar's thumb
22120      * within the vertical range. This value is used to compute the length
22121      * of the thumb within the scrollbar's track.</p>
22122      *
22123      * <p>The range is expressed in arbitrary units that must be the same as the
22124      * units used by {@link #computeVerticalScrollRange()} and
22125      * {@link #computeVerticalScrollOffset()}.</p>
22126      *
22127      * <p>The default extent is the drawing height of this view.</p>
22128      *
22129      * @return the vertical extent of the scrollbar's thumb
22130      *
22131      * @see #computeVerticalScrollRange()
22132      * @see #computeVerticalScrollOffset()
22133      */
computeVerticalScrollExtent()22134     protected int computeVerticalScrollExtent() {
22135         return getHeight();
22136     }
22137 
22138     /**
22139      * Check if this view can be scrolled horizontally in a certain direction.
22140      *
22141      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
22142      * in response to user input or not.
22143      *
22144      * @param direction Negative to check scrolling left, positive to check scrolling right.
22145      * @return true if this view can be scrolled in the specified direction, false otherwise.
22146      */
canScrollHorizontally(int direction)22147     public boolean canScrollHorizontally(int direction) {
22148         final int offset = computeHorizontalScrollOffset();
22149         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
22150         if (range == 0) return false;
22151         if (direction < 0) {
22152             return offset > 0;
22153         } else {
22154             return offset < range - 1;
22155         }
22156     }
22157 
22158     /**
22159      * Check if this view can be scrolled vertically in a certain direction.
22160      *
22161      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
22162      * in response to user input or not.
22163      *
22164      * @param direction Negative to check scrolling up, positive to check scrolling down.
22165      * @return true if this view can be scrolled in the specified direction, false otherwise.
22166      */
canScrollVertically(int direction)22167     public boolean canScrollVertically(int direction) {
22168         final int offset = computeVerticalScrollOffset();
22169         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
22170         if (range == 0) return false;
22171         if (direction < 0) {
22172             return offset > 0;
22173         } else {
22174             return offset < range - 1;
22175         }
22176     }
22177 
getScrollIndicatorBounds(@onNull Rect out)22178     void getScrollIndicatorBounds(@NonNull Rect out) {
22179         out.left = mScrollX;
22180         out.right = mScrollX + mRight - mLeft;
22181         out.top = mScrollY;
22182         out.bottom = mScrollY + mBottom - mTop;
22183     }
22184 
onDrawScrollIndicators(@onNull Canvas c)22185     private void onDrawScrollIndicators(@NonNull Canvas c) {
22186         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
22187             // No scroll indicators enabled.
22188             return;
22189         }
22190 
22191         final Drawable dr = mScrollIndicatorDrawable;
22192         if (dr == null) {
22193             // Scroll indicators aren't supported here.
22194             return;
22195         }
22196 
22197         if (mAttachInfo == null) {
22198             // View is not attached.
22199             return;
22200         }
22201 
22202         final int h = dr.getIntrinsicHeight();
22203         final int w = dr.getIntrinsicWidth();
22204         final Rect rect = mAttachInfo.mTmpInvalRect;
22205         getScrollIndicatorBounds(rect);
22206 
22207         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
22208             final boolean canScrollUp = canScrollVertically(-1);
22209             if (canScrollUp) {
22210                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
22211                 dr.draw(c);
22212             }
22213         }
22214 
22215         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
22216             final boolean canScrollDown = canScrollVertically(1);
22217             if (canScrollDown) {
22218                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
22219                 dr.draw(c);
22220             }
22221         }
22222 
22223         final int leftRtl;
22224         final int rightRtl;
22225         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
22226             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
22227             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
22228         } else {
22229             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
22230             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
22231         }
22232 
22233         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
22234         if ((mPrivateFlags3 & leftMask) != 0) {
22235             final boolean canScrollLeft = canScrollHorizontally(-1);
22236             if (canScrollLeft) {
22237                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
22238                 dr.draw(c);
22239             }
22240         }
22241 
22242         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
22243         if ((mPrivateFlags3 & rightMask) != 0) {
22244             final boolean canScrollRight = canScrollHorizontally(1);
22245             if (canScrollRight) {
22246                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
22247                 dr.draw(c);
22248             }
22249         }
22250     }
22251 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)22252     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
22253             @Nullable Rect touchBounds) {
22254         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
22255         if (bounds == null) {
22256             return;
22257         }
22258         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
22259         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
22260                 && !isVerticalScrollBarHidden();
22261         final int size = getHorizontalScrollbarHeight();
22262         final int verticalScrollBarGap = drawVerticalScrollBar ?
22263                 getVerticalScrollbarWidth() : 0;
22264         final int width = mRight - mLeft;
22265         final int height = mBottom - mTop;
22266         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
22267         bounds.left = mScrollX + (mPaddingLeft & inside);
22268         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
22269         bounds.bottom = bounds.top + size;
22270 
22271         if (touchBounds == null) {
22272             return;
22273         }
22274         if (touchBounds != bounds) {
22275             touchBounds.set(bounds);
22276         }
22277         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
22278         if (touchBounds.height() < minTouchTarget) {
22279             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
22280             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
22281             touchBounds.top = touchBounds.bottom - minTouchTarget;
22282         }
22283         if (touchBounds.width() < minTouchTarget) {
22284             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
22285             touchBounds.left -= adjust;
22286             touchBounds.right = touchBounds.left + minTouchTarget;
22287         }
22288     }
22289 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)22290     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
22291         if (mRoundScrollbarRenderer == null) {
22292             getStraightVerticalScrollBarBounds(bounds, touchBounds);
22293         } else {
22294             mRoundScrollbarRenderer.getRoundVerticalScrollBarBounds(
22295                     bounds != null ? bounds : touchBounds);
22296         }
22297     }
22298 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)22299     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
22300             @Nullable Rect touchBounds) {
22301         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
22302         if (bounds == null) {
22303             return;
22304         }
22305         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
22306         final int size = getVerticalScrollbarWidth();
22307         int verticalScrollbarPosition = mVerticalScrollbarPosition;
22308         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
22309             verticalScrollbarPosition = isLayoutRtl() ?
22310                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
22311         }
22312         final int width = mRight - mLeft;
22313         final int height = mBottom - mTop;
22314         switch (verticalScrollbarPosition) {
22315             default:
22316             case SCROLLBAR_POSITION_RIGHT:
22317                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
22318                 break;
22319             case SCROLLBAR_POSITION_LEFT:
22320                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
22321                 break;
22322         }
22323         bounds.top = mScrollY + (mPaddingTop & inside);
22324         bounds.right = bounds.left + size;
22325         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
22326 
22327         if (touchBounds == null) {
22328             return;
22329         }
22330         if (touchBounds != bounds) {
22331             touchBounds.set(bounds);
22332         }
22333         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
22334         if (touchBounds.width() < minTouchTarget) {
22335             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
22336             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
22337                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
22338                 touchBounds.left = touchBounds.right - minTouchTarget;
22339             } else {
22340                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
22341                 touchBounds.right = touchBounds.left + minTouchTarget;
22342             }
22343         }
22344         if (touchBounds.height() < minTouchTarget) {
22345             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
22346             touchBounds.top -= adjust;
22347             touchBounds.bottom = touchBounds.top + minTouchTarget;
22348         }
22349     }
22350 
22351     /**
22352      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
22353      * scrollbars are painted only if they have been awakened first.</p>
22354      *
22355      * @param canvas the canvas on which to draw the scrollbars
22356      *
22357      * @see #awakenScrollBars(int)
22358      */
onDrawScrollBars(@onNull Canvas canvas)22359     protected final void onDrawScrollBars(@NonNull Canvas canvas) {
22360         // scrollbars are drawn only when the animation is running
22361         final ScrollabilityCache cache = mScrollCache;
22362 
22363         if (cache != null) {
22364 
22365             int state = cache.state;
22366 
22367             if (state == ScrollabilityCache.OFF) {
22368                 return;
22369             }
22370 
22371             boolean invalidate = false;
22372 
22373             if (state == ScrollabilityCache.FADING) {
22374                 // We're fading -- get our fade interpolation
22375                 if (cache.interpolatorValues == null) {
22376                     cache.interpolatorValues = new float[1];
22377                 }
22378 
22379                 float[] values = cache.interpolatorValues;
22380 
22381                 // Stops the animation if we're done
22382                 if (cache.scrollBarInterpolator.timeToValues(values) ==
22383                         Interpolator.Result.FREEZE_END) {
22384                     cache.state = ScrollabilityCache.OFF;
22385                 } else {
22386                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
22387                 }
22388 
22389                 // This will make the scroll bars inval themselves after
22390                 // drawing. We only want this when we're fading so that
22391                 // we prevent excessive redraws
22392                 invalidate = true;
22393             } else {
22394                 // We're just on -- but we may have been fading before so
22395                 // reset alpha
22396                 cache.scrollBar.mutate().setAlpha(255);
22397             }
22398 
22399             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
22400             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
22401                     && !isVerticalScrollBarHidden();
22402 
22403             // Fork out the scroll bar drawing for round wearable devices.
22404             if (mRoundScrollbarRenderer != null) {
22405                 if (drawVerticalScrollBar) {
22406                     final Rect bounds = cache.mScrollBarBounds;
22407                     getVerticalScrollBarBounds(bounds, null);
22408                     boolean shouldDrawScrollbarAtLeft =
22409                             (mVerticalScrollbarPosition == SCROLLBAR_POSITION_LEFT)
22410                                     || (mVerticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT
22411                                     && isLayoutRtl());
22412 
22413                     mRoundScrollbarRenderer.drawRoundScrollbars(
22414                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds,
22415                             shouldDrawScrollbarAtLeft);
22416                     if (invalidate) {
22417                         invalidate();
22418                     }
22419                 }
22420                 // Do not draw horizontal scroll bars for round wearable devices.
22421             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
22422                 final ScrollBarDrawable scrollBar = cache.scrollBar;
22423 
22424                 if (drawHorizontalScrollBar) {
22425                     scrollBar.setParameters(computeHorizontalScrollRange(),
22426                             computeHorizontalScrollOffset(),
22427                             computeHorizontalScrollExtent(), false);
22428                     final Rect bounds = cache.mScrollBarBounds;
22429                     getHorizontalScrollBarBounds(bounds, null);
22430                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
22431                             bounds.right, bounds.bottom);
22432                     if (invalidate) {
22433                         invalidate(bounds);
22434                     }
22435                 }
22436 
22437                 if (drawVerticalScrollBar) {
22438                     scrollBar.setParameters(computeVerticalScrollRange(),
22439                             computeVerticalScrollOffset(),
22440                             computeVerticalScrollExtent(), true);
22441                     final Rect bounds = cache.mScrollBarBounds;
22442                     getVerticalScrollBarBounds(bounds, null);
22443                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
22444                             bounds.right, bounds.bottom);
22445                     if (invalidate) {
22446                         invalidate(bounds);
22447                     }
22448                 }
22449             }
22450         }
22451     }
22452 
22453     /**
22454      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
22455      * FastScroller is visible.
22456      * @return whether to temporarily hide the vertical scrollbar
22457      * @hide
22458      */
isVerticalScrollBarHidden()22459     protected boolean isVerticalScrollBarHidden() {
22460         return false;
22461     }
22462 
22463     /**
22464      * <p>Draw the horizontal scrollbar if
22465      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
22466      *
22467      * @param canvas the canvas on which to draw the scrollbar
22468      * @param scrollBar the scrollbar's drawable
22469      *
22470      * @see #isHorizontalScrollBarEnabled()
22471      * @see #computeHorizontalScrollRange()
22472      * @see #computeHorizontalScrollExtent()
22473      * @see #computeHorizontalScrollOffset()
22474      * @hide
22475      */
22476     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDrawHorizontalScrollBar(@onNull Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)22477     protected void onDrawHorizontalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
22478             int l, int t, int r, int b) {
22479         scrollBar.setBounds(l, t, r, b);
22480         scrollBar.draw(canvas);
22481     }
22482 
22483     /**
22484      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
22485      * returns true.</p>
22486      *
22487      * @param canvas the canvas on which to draw the scrollbar
22488      * @param scrollBar the scrollbar's drawable
22489      *
22490      * @see #isVerticalScrollBarEnabled()
22491      * @see #computeVerticalScrollRange()
22492      * @see #computeVerticalScrollExtent()
22493      * @see #computeVerticalScrollOffset()
22494      * @hide
22495      */
22496     @UnsupportedAppUsage
onDrawVerticalScrollBar(@onNull Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)22497     protected void onDrawVerticalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
22498             int l, int t, int r, int b) {
22499         scrollBar.setBounds(l, t, r, b);
22500         scrollBar.draw(canvas);
22501     }
22502 
22503     /**
22504      * Implement this to do your drawing.
22505      *
22506      * @param canvas the canvas on which the background will be drawn
22507      */
onDraw(@onNull Canvas canvas)22508     protected void onDraw(@NonNull Canvas canvas) {
22509     }
22510 
22511     /*
22512      * Caller is responsible for calling requestLayout if necessary.
22513      * (This allows addViewInLayout to not request a new layout.)
22514      */
22515     @UnsupportedAppUsage
assignParent(ViewParent parent)22516     void assignParent(ViewParent parent) {
22517         if (mParent == null) {
22518             mParent = parent;
22519         } else if (parent == null) {
22520             mParent = null;
22521         } else {
22522             throw new RuntimeException("view " + this + " being added, but"
22523                     + " it already has a parent");
22524         }
22525     }
22526 
22527     /**
22528      * This is called when the view is attached to a window.  At this point it
22529      * has a Surface and will start drawing.  Note that this function is
22530      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
22531      * however it may be called any time before the first onDraw -- including
22532      * before or after {@link #onMeasure(int, int)}.
22533      *
22534      * @see #onDetachedFromWindow()
22535      */
22536     @CallSuper
onAttachedToWindow()22537     protected void onAttachedToWindow() {
22538         if (mParent != null && (mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
22539             mParent.requestTransparentRegion(this);
22540         }
22541 
22542         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
22543 
22544         jumpDrawablesToCurrentState();
22545 
22546         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
22547         resetSubtreeAccessibilityStateChanged();
22548 
22549         // rebuild, since Outline not maintained while View is detached
22550         rebuildOutline();
22551 
22552         if (isFocused()) {
22553             notifyFocusChangeToImeFocusController(true /* hasFocus */);
22554         }
22555 
22556         if (sTraceLayoutSteps) {
22557             setTraversalTracingEnabled(true);
22558         }
22559         if (sTraceRequestLayoutClass != null
22560                 && sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
22561             setRelayoutTracingEnabled(true);
22562         }
22563     }
22564 
22565     /**
22566      * Resolve all RTL related properties.
22567      *
22568      * @return true if resolution of RTL properties has been done
22569      *
22570      * @hide
22571      */
resolveRtlPropertiesIfNeeded()22572     public boolean resolveRtlPropertiesIfNeeded() {
22573         if (!needRtlPropertiesResolution()) return false;
22574 
22575         // Order is important here: LayoutDirection MUST be resolved first
22576         if (!isLayoutDirectionResolved()) {
22577             resolveLayoutDirection();
22578             resolveLayoutParams();
22579         }
22580         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
22581         if (!isTextDirectionResolved()) {
22582             resolveTextDirection();
22583         }
22584         if (!isTextAlignmentResolved()) {
22585             resolveTextAlignment();
22586         }
22587         // Should resolve Drawables before Padding because we need the layout direction of the
22588         // Drawable to correctly resolve Padding.
22589         if (!areDrawablesResolved()) {
22590             resolveDrawables();
22591         }
22592         if (!isPaddingResolved()) {
22593             resolvePadding();
22594         }
22595         onRtlPropertiesChanged(getLayoutDirection());
22596         return true;
22597     }
22598 
22599     /**
22600      * Reset resolution of all RTL related properties.
22601      *
22602      * @hide
22603      */
22604     @TestApi
resetRtlProperties()22605     public void resetRtlProperties() {
22606         resetResolvedLayoutDirection();
22607         resetResolvedTextDirection();
22608         resetResolvedTextAlignment();
22609         resetResolvedPadding();
22610         resetResolvedDrawables();
22611     }
22612 
22613     /**
22614      * @see #onScreenStateChanged(int)
22615      */
dispatchScreenStateChanged(int screenState)22616     void dispatchScreenStateChanged(int screenState) {
22617         onScreenStateChanged(screenState);
22618     }
22619 
22620     /**
22621      * This method is called whenever the state of the screen this view is
22622      * attached to changes. A state change will usually occurs when the screen
22623      * turns on or off (whether it happens automatically or the user does it
22624      * manually.)
22625      *
22626      * @param screenState The new state of the screen. Can be either
22627      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
22628      */
onScreenStateChanged(int screenState)22629     public void onScreenStateChanged(int screenState) {
22630     }
22631 
22632     /**
22633      * @see #onMovedToDisplay(int, Configuration)
22634      */
dispatchMovedToDisplay(Display display, Configuration config)22635     void dispatchMovedToDisplay(Display display, Configuration config) {
22636         mAttachInfo.mDisplay = display;
22637         mAttachInfo.mDisplayState = display.getState();
22638         onMovedToDisplay(display.getDisplayId(), config);
22639     }
22640 
22641     /**
22642      * Called by the system when the hosting activity is moved from one display to another without
22643      * recreation. This means that the activity is declared to handle all changes to configuration
22644      * that happened when it was switched to another display, so it wasn't destroyed and created
22645      * again.
22646      *
22647      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
22648      * applied configuration actually changed. It is up to app developer to choose whether to handle
22649      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
22650      * call.
22651      *
22652      * <p>Use this callback to track changes to the displays if some functionality relies on an
22653      * association with some display properties.
22654      *
22655      * @param displayId The id of the display to which the view was moved.
22656      * @param config Configuration of the resources on new display after move.
22657      *
22658      * @see #onConfigurationChanged(Configuration)
22659      * @hide
22660      */
onMovedToDisplay(int displayId, Configuration config)22661     public void onMovedToDisplay(int displayId, Configuration config) {
22662     }
22663 
22664     /**
22665      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
22666      */
22667     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hasRtlSupport()22668     private boolean hasRtlSupport() {
22669         return mContext.getApplicationInfo().hasRtlSupport();
22670     }
22671 
22672     /**
22673      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
22674      * RTL not supported)
22675      */
isRtlCompatibilityMode()22676     private boolean isRtlCompatibilityMode() {
22677         return !hasRtlSupport();
22678     }
22679 
22680     /**
22681      * @return true if RTL properties need resolution.
22682      *
22683      */
needRtlPropertiesResolution()22684     private boolean needRtlPropertiesResolution() {
22685         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
22686     }
22687 
22688     /**
22689      * Called when any RTL property (layout direction or text direction or text alignment) has
22690      * been changed.
22691      *
22692      * Subclasses need to override this method to take care of cached information that depends on the
22693      * resolved layout direction, or to inform child views that inherit their layout direction.
22694      *
22695      * The default implementation does nothing.
22696      *
22697      * @param layoutDirection the direction of the layout
22698      *
22699      * @see #LAYOUT_DIRECTION_LTR
22700      * @see #LAYOUT_DIRECTION_RTL
22701      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)22702     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
22703     }
22704 
22705     /**
22706      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
22707      * that the parent directionality can and will be resolved before its children.
22708      *
22709      * @return true if resolution has been done, false otherwise.
22710      *
22711      * @hide
22712      */
resolveLayoutDirection()22713     public boolean resolveLayoutDirection() {
22714         // Clear any previous layout direction resolution
22715         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
22716 
22717         if (hasRtlSupport()) {
22718             // Set resolved depending on layout direction
22719             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
22720                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
22721                 case LAYOUT_DIRECTION_INHERIT:
22722                     // We cannot resolve yet. LTR is by default and let the resolution happen again
22723                     // later to get the correct resolved value
22724                     if (!canResolveLayoutDirection()) return false;
22725 
22726                     // Parent has not yet resolved, LTR is still the default
22727                     try {
22728                         if (!mParent.isLayoutDirectionResolved()) return false;
22729 
22730                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
22731                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
22732                         }
22733                     } catch (AbstractMethodError e) {
22734                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22735                                 " does not fully implement ViewParent", e);
22736                     }
22737                     break;
22738                 case LAYOUT_DIRECTION_RTL:
22739                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
22740                     break;
22741                 case LAYOUT_DIRECTION_LOCALE:
22742                     if((LAYOUT_DIRECTION_RTL ==
22743                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
22744                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
22745                     }
22746                     break;
22747                 default:
22748                     // Nothing to do, LTR by default
22749             }
22750         }
22751 
22752         // Set to resolved
22753         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
22754         return true;
22755     }
22756 
22757     /**
22758      * Check if layout direction resolution can be done.
22759      *
22760      * @return true if layout direction resolution can be done otherwise return false.
22761      */
canResolveLayoutDirection()22762     public boolean canResolveLayoutDirection() {
22763         switch (getRawLayoutDirection()) {
22764             case LAYOUT_DIRECTION_INHERIT:
22765                 if (mParent != null) {
22766                     try {
22767                         return mParent.canResolveLayoutDirection();
22768                     } catch (AbstractMethodError e) {
22769                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22770                                 " does not fully implement ViewParent", e);
22771                     }
22772                 }
22773                 return false;
22774 
22775             default:
22776                 return true;
22777         }
22778     }
22779 
22780     /**
22781      * Reset the resolved layout direction. Layout direction will be resolved during a call to
22782      * {@link #onMeasure(int, int)}.
22783      *
22784      * @hide
22785      */
22786     @TestApi
resetResolvedLayoutDirection()22787     public void resetResolvedLayoutDirection() {
22788         // Reset the current resolved bits
22789         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
22790     }
22791 
22792     /**
22793      * @return true if the layout direction is inherited.
22794      *
22795      * @hide
22796      */
isLayoutDirectionInherited()22797     public boolean isLayoutDirectionInherited() {
22798         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
22799     }
22800 
22801     /**
22802      * @return true if layout direction has been resolved.
22803      */
isLayoutDirectionResolved()22804     public boolean isLayoutDirectionResolved() {
22805         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
22806     }
22807 
22808     /**
22809      * Return if padding has been resolved
22810      *
22811      * @hide
22812      */
22813     @UnsupportedAppUsage
isPaddingResolved()22814     boolean isPaddingResolved() {
22815         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
22816     }
22817 
22818     /**
22819      * Resolves padding depending on layout direction, if applicable, and
22820      * recomputes internal padding values to adjust for scroll bars.
22821      *
22822      * @hide
22823      */
22824     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resolvePadding()22825     public void resolvePadding() {
22826         final int resolvedLayoutDirection = getLayoutDirection();
22827 
22828         if (!isRtlCompatibilityMode()) {
22829             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
22830             // If start / end padding are defined, they will be resolved (hence overriding) to
22831             // left / right or right / left depending on the resolved layout direction.
22832             // If start / end padding are not defined, use the left / right ones.
22833             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
22834                 Rect padding = sThreadLocal.get();
22835                 if (padding == null) {
22836                     padding = new Rect();
22837                     sThreadLocal.set(padding);
22838                 }
22839                 mBackground.getPadding(padding);
22840                 if (!mLeftPaddingDefined) {
22841                     mUserPaddingLeftInitial = padding.left;
22842                 }
22843                 if (!mRightPaddingDefined) {
22844                     mUserPaddingRightInitial = padding.right;
22845                 }
22846             }
22847             switch (resolvedLayoutDirection) {
22848                 case LAYOUT_DIRECTION_RTL:
22849                     if (mUserPaddingStart != UNDEFINED_PADDING) {
22850                         mUserPaddingRight = mUserPaddingStart;
22851                     } else {
22852                         mUserPaddingRight = mUserPaddingRightInitial;
22853                     }
22854                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
22855                         mUserPaddingLeft = mUserPaddingEnd;
22856                     } else {
22857                         mUserPaddingLeft = mUserPaddingLeftInitial;
22858                     }
22859                     break;
22860                 case LAYOUT_DIRECTION_LTR:
22861                 default:
22862                     if (mUserPaddingStart != UNDEFINED_PADDING) {
22863                         mUserPaddingLeft = mUserPaddingStart;
22864                     } else {
22865                         mUserPaddingLeft = mUserPaddingLeftInitial;
22866                     }
22867                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
22868                         mUserPaddingRight = mUserPaddingEnd;
22869                     } else {
22870                         mUserPaddingRight = mUserPaddingRightInitial;
22871                     }
22872             }
22873 
22874             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
22875         }
22876 
22877         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
22878         onRtlPropertiesChanged(resolvedLayoutDirection);
22879 
22880         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
22881     }
22882 
22883     /**
22884      * Reset the resolved layout direction.
22885      *
22886      * @hide
22887      */
22888     @TestApi
resetResolvedPadding()22889     public void resetResolvedPadding() {
22890         resetResolvedPaddingInternal();
22891     }
22892 
22893     /**
22894      * Used when we only want to reset *this* view's padding and not trigger overrides
22895      * in ViewGroup that reset children too.
22896      */
resetResolvedPaddingInternal()22897     void resetResolvedPaddingInternal() {
22898         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
22899     }
22900 
22901     /**
22902      * This is called when the view is detached from a window.  At this point it
22903      * no longer has a surface for drawing.
22904      *
22905      * @see #onAttachedToWindow()
22906      */
22907     @CallSuper
onDetachedFromWindow()22908     protected void onDetachedFromWindow() {
22909     }
22910 
22911     /**
22912      * This is a framework-internal mirror of onDetachedFromWindow() that's called
22913      * after onDetachedFromWindow().
22914      *
22915      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
22916      * The super method should be called at the end of the overridden method to ensure
22917      * subclasses are destroyed first
22918      *
22919      * @hide
22920      */
22921     @CallSuper
22922     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDetachedFromWindowInternal()22923     protected void onDetachedFromWindowInternal() {
22924         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
22925         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
22926         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
22927 
22928         removeUnsetPressCallback();
22929         removeLongPressCallback();
22930         removePerformClickCallback();
22931         clearAccessibilityThrottles();
22932         stopNestedScroll();
22933 
22934         // Anything that started animating right before detach should already
22935         // be in its final state when re-attached.
22936         jumpDrawablesToCurrentState();
22937 
22938         destroyDrawingCache();
22939 
22940         cleanupDraw();
22941         mCurrentAnimation = null;
22942 
22943         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
22944             removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
22945             removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
22946             hideTooltip();
22947         }
22948 
22949         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
22950 
22951         if (mBackgroundRenderNode != null) {
22952             mBackgroundRenderNode.forceEndAnimators();
22953         }
22954         mRenderNode.forceEndAnimators();
22955     }
22956 
cleanupDraw()22957     private void cleanupDraw() {
22958         resetDisplayList();
22959         if (mAttachInfo != null) {
22960             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
22961         }
22962     }
22963 
invalidateInheritedLayoutMode(int layoutModeOfRoot)22964     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
22965     }
22966 
22967     /**
22968      * @return The number of times this view has been attached to a window
22969      */
getWindowAttachCount()22970     protected int getWindowAttachCount() {
22971         return mWindowAttachCount;
22972     }
22973 
22974     /**
22975      * Retrieve a unique token identifying the window this view is attached to.
22976      * @return Return the window's token for use in
22977      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
22978      * This token maybe null if this view is not attached to a window.
22979      * @see #isAttachedToWindow() for current window attach state
22980      * @see OnAttachStateChangeListener to listen to window attach/detach state changes
22981      */
getWindowToken()22982     public IBinder getWindowToken() {
22983         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
22984     }
22985 
22986     /**
22987      * Retrieve the {@link WindowId} for the window this view is
22988      * currently attached to.
22989      */
getWindowId()22990     public WindowId getWindowId() {
22991         AttachInfo ai = mAttachInfo;
22992         if (ai == null) {
22993             return null;
22994         }
22995         if (ai.mWindowId == null) {
22996             try {
22997                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
22998                 if (ai.mIWindowId != null) {
22999                     ai.mWindowId = new WindowId(ai.mIWindowId);
23000                 }
23001             } catch (RemoteException e) {
23002             }
23003         }
23004         return ai.mWindowId;
23005     }
23006 
23007     /**
23008      * Retrieve a unique token identifying the top-level "real" window of
23009      * the window that this view is attached to.  That is, this is like
23010      * {@link #getWindowToken}, except if the window this view in is a panel
23011      * window (attached to another containing window), then the token of
23012      * the containing window is returned instead.
23013      *
23014      * @return Returns the associated window token, either
23015      * {@link #getWindowToken()} or the containing window's token.
23016      */
getApplicationWindowToken()23017     public IBinder getApplicationWindowToken() {
23018         AttachInfo ai = mAttachInfo;
23019         if (ai != null) {
23020             IBinder appWindowToken = ai.mPanelParentWindowToken;
23021             if (appWindowToken == null) {
23022                 appWindowToken = ai.mWindowToken;
23023             }
23024             return appWindowToken;
23025         }
23026         return null;
23027     }
23028 
23029     /**
23030      * Gets the logical display to which the view's window has been attached.
23031      *
23032      * @return The logical display, or null if the view is not currently attached to a window.
23033      */
getDisplay()23034     public Display getDisplay() {
23035         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
23036     }
23037 
23038     /**
23039      * Retrieve private session object this view hierarchy is using to
23040      * communicate with the window manager.
23041      * @return the session object to communicate with the window manager
23042      */
23043     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()23044     /*package*/ IWindowSession getWindowSession() {
23045         return mAttachInfo != null ? mAttachInfo.mSession : null;
23046     }
23047 
23048     /**
23049      * Return the window this view is currently attached to.
23050      * @hide
23051      */
getWindow()23052     protected IWindow getWindow() {
23053         return mAttachInfo != null ? mAttachInfo.mWindow : null;
23054     }
23055 
23056     /**
23057      * Return the visibility value of the least visible component passed.
23058      */
combineVisibility(int vis1, int vis2)23059     int combineVisibility(int vis1, int vis2) {
23060         // This works because VISIBLE < INVISIBLE < GONE.
23061         return Math.max(vis1, vis2);
23062     }
23063 
23064     private boolean mShouldFakeFocus = false;
23065 
23066     /**
23067      * Fake send a focus event after attaching to window.
23068      * See {@link android.view.ViewRootImpl#dispatchCompatFakeFocus()} for details.
23069      * @hide
23070      */
fakeFocusAfterAttachingToWindow()23071     public void fakeFocusAfterAttachingToWindow() {
23072         mShouldFakeFocus = true;
23073     }
23074 
23075     /**
23076      * @param info the {@link android.view.View.AttachInfo} to associated with
23077      *        this view
23078      */
23079     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)23080     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
23081         mAttachInfo = info;
23082         if (mOverlay != null) {
23083             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
23084         }
23085         mWindowAttachCount++;
23086         // We will need to evaluate the drawable state at least once.
23087         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
23088         if (mFloatingTreeObserver != null) {
23089             info.mTreeObserver.merge(mFloatingTreeObserver);
23090             mFloatingTreeObserver = null;
23091         }
23092 
23093         registerPendingFrameMetricsObservers();
23094 
23095         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
23096             mAttachInfo.mScrollContainers.add(this);
23097             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
23098         }
23099         // Transfer all pending runnables.
23100         if (mRunQueue != null) {
23101             mRunQueue.executeActions(info.mHandler);
23102             mRunQueue = null;
23103         }
23104         performCollectViewAttributes(mAttachInfo, visibility);
23105         onAttachedToWindow();
23106 
23107         ListenerInfo li = mListenerInfo;
23108         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
23109                 li != null ? li.mOnAttachStateChangeListeners : null;
23110         if (listeners != null && listeners.size() > 0) {
23111             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
23112             // perform the dispatching. The iterator is a safe guard against listeners that
23113             // could mutate the list by calling the various add/remove methods. This prevents
23114             // the array from being modified while we iterate it.
23115             for (OnAttachStateChangeListener listener : listeners) {
23116                 listener.onViewAttachedToWindow(this);
23117             }
23118         }
23119 
23120         int vis = info.mWindowVisibility;
23121         if (vis != GONE) {
23122             onWindowVisibilityChanged(vis);
23123             if (isShown()) {
23124                 // Calling onVisibilityAggregated directly here since the subtree will also
23125                 // receive dispatchAttachedToWindow and this same call
23126                 onVisibilityAggregated(vis == VISIBLE);
23127             }
23128         }
23129 
23130         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
23131         // As all views in the subtree will already receive dispatchAttachedToWindow
23132         // traversing the subtree again here is not desired.
23133         onVisibilityChanged(this, visibility);
23134 
23135         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
23136             // If nobody has evaluated the drawable state yet, then do it now.
23137             refreshDrawableState();
23138         }
23139         needGlobalAttributesUpdate(false);
23140 
23141         notifyEnterOrExitForAutoFillIfNeeded(true);
23142         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
23143 
23144         if (mShouldFakeFocus) {
23145             getViewRootImpl().dispatchCompatFakeFocus();
23146             mShouldFakeFocus = false;
23147         }
23148     }
23149 
23150     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()23151     void dispatchDetachedFromWindow() {
23152         AttachInfo info = mAttachInfo;
23153         if (info != null) {
23154             int vis = info.mWindowVisibility;
23155             if (vis != GONE) {
23156                 onWindowVisibilityChanged(GONE);
23157                 if (isShown()) {
23158                     // Invoking onVisibilityAggregated directly here since the subtree
23159                     // will also receive detached from window
23160                     onVisibilityAggregated(false);
23161                 } else {
23162                     notifyAutofillManagerViewVisibilityChanged(false);
23163                 }
23164             }
23165         }
23166 
23167         onDetachedFromWindow();
23168         onDetachedFromWindowInternal();
23169 
23170         if (info != null) {
23171             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
23172         }
23173 
23174         ListenerInfo li = mListenerInfo;
23175         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
23176                 li != null ? li.mOnAttachStateChangeListeners : null;
23177         if (listeners != null && listeners.size() > 0) {
23178             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
23179             // perform the dispatching. The iterator is a safe guard against listeners that
23180             // could mutate the list by calling the various add/remove methods. This prevents
23181             // the array from being modified while we iterate it.
23182             for (OnAttachStateChangeListener listener : listeners) {
23183                 listener.onViewDetachedFromWindow(this);
23184             }
23185         }
23186 
23187         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
23188             mAttachInfo.mScrollContainers.remove(this);
23189             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
23190         }
23191 
23192         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
23193         updateSensitiveViewsCountIfNeeded(false);
23194 
23195         mAttachInfo = null;
23196         if (mOverlay != null) {
23197             mOverlay.getOverlayView().dispatchDetachedFromWindow();
23198         }
23199 
23200         notifyEnterOrExitForAutoFillIfNeeded(false);
23201 
23202         if (info != null && !collectPreferKeepClearRects().isEmpty()) {
23203             info.mViewRootImpl.updateKeepClearRectsForView(this);
23204         }
23205     }
23206 
23207     /**
23208      * Cancel any deferred high-level input events that were previously posted to the event queue.
23209      *
23210      * <p>Many views post high-level events such as click handlers to the event queue
23211      * to run deferred in order to preserve a desired user experience - clearing visible
23212      * pressed states before executing, etc. This method will abort any events of this nature
23213      * that are currently in flight.</p>
23214      *
23215      * <p>Custom views that generate their own high-level deferred input events should override
23216      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
23217      *
23218      * <p>This will also cancel pending input events for any child views.</p>
23219      *
23220      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
23221      * This will not impact newer events posted after this call that may occur as a result of
23222      * lower-level input events still waiting in the queue. If you are trying to prevent
23223      * double-submitted  events for the duration of some sort of asynchronous transaction
23224      * you should also take other steps to protect against unexpected double inputs e.g. calling
23225      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
23226      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
23227      */
cancelPendingInputEvents()23228     public final void cancelPendingInputEvents() {
23229         dispatchCancelPendingInputEvents();
23230     }
23231 
23232     /**
23233      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
23234      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
23235      */
dispatchCancelPendingInputEvents()23236     void dispatchCancelPendingInputEvents() {
23237         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
23238         onCancelPendingInputEvents();
23239         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
23240             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
23241                     " did not call through to super.onCancelPendingInputEvents()");
23242         }
23243     }
23244 
23245     /**
23246      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
23247      * a parent view.
23248      *
23249      * <p>This method is responsible for removing any pending high-level input events that were
23250      * posted to the event queue to run later. Custom view classes that post their own deferred
23251      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
23252      * {@link android.os.Handler} should override this method, call
23253      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
23254      * </p>
23255      */
onCancelPendingInputEvents()23256     public void onCancelPendingInputEvents() {
23257         removePerformClickCallback();
23258         cancelLongPress();
23259         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
23260     }
23261 
23262     /**
23263      * Store this view hierarchy's frozen state into the given container.
23264      *
23265      * @param container The SparseArray in which to save the view's state.
23266      *
23267      * @see #restoreHierarchyState(android.util.SparseArray)
23268      * @see #dispatchSaveInstanceState(android.util.SparseArray)
23269      * @see #onSaveInstanceState()
23270      */
saveHierarchyState(SparseArray<Parcelable> container)23271     public void saveHierarchyState(SparseArray<Parcelable> container) {
23272         dispatchSaveInstanceState(container);
23273     }
23274 
23275     /**
23276      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
23277      * this view and its children. May be overridden to modify how freezing happens to a
23278      * view's children; for example, some views may want to not store state for their children.
23279      *
23280      * @param container The SparseArray in which to save the view's state.
23281      *
23282      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
23283      * @see #saveHierarchyState(android.util.SparseArray)
23284      * @see #onSaveInstanceState()
23285      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)23286     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
23287         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
23288             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
23289             Parcelable state = onSaveInstanceState();
23290             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
23291                 throw new IllegalStateException(
23292                         "Derived class did not call super.onSaveInstanceState()");
23293             }
23294             if (state != null) {
23295                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
23296                 // + ": " + state);
23297                 container.put(mID, state);
23298             }
23299         }
23300     }
23301 
23302     /**
23303      * Hook allowing a view to generate a representation of its internal state
23304      * that can later be used to create a new instance with that same state.
23305      * This state should only contain information that is not persistent or can
23306      * not be reconstructed later. For example, you will never store your
23307      * current position on screen because that will be computed again when a
23308      * new instance of the view is placed in its view hierarchy.
23309      * <p>
23310      * Some examples of things you may store here: the current cursor position
23311      * in a text view (but usually not the text itself since that is stored in a
23312      * content provider or other persistent storage), the currently selected
23313      * item in a list view.
23314      *
23315      * @return Returns a Parcelable object containing the view's current dynamic
23316      *         state, or null if there is nothing interesting to save.
23317      * @see #onRestoreInstanceState(Parcelable)
23318      * @see #saveHierarchyState(SparseArray)
23319      * @see #dispatchSaveInstanceState(SparseArray)
23320      * @see #setSaveEnabled(boolean)
23321      */
23322     @CallSuper
onSaveInstanceState()23323     @Nullable protected Parcelable onSaveInstanceState() {
23324         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
23325         if (mStartActivityRequestWho != null || isAutofilled()
23326                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
23327             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
23328 
23329             if (mStartActivityRequestWho != null) {
23330                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
23331             }
23332 
23333             if (isAutofilled()) {
23334                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
23335             }
23336 
23337             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
23338                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
23339             }
23340 
23341             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
23342             state.mIsAutofilled = isAutofilled();
23343             state.mHideHighlight = hideAutofillHighlight();
23344             state.mAutofillViewId = mAutofillViewId;
23345             return state;
23346         }
23347         return BaseSavedState.EMPTY_STATE;
23348     }
23349 
23350     /**
23351      * Restore this view hierarchy's frozen state from the given container.
23352      *
23353      * @param container The SparseArray which holds previously frozen states.
23354      *
23355      * @see #saveHierarchyState(android.util.SparseArray)
23356      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
23357      * @see #onRestoreInstanceState(android.os.Parcelable)
23358      */
restoreHierarchyState(SparseArray<Parcelable> container)23359     public void restoreHierarchyState(SparseArray<Parcelable> container) {
23360         dispatchRestoreInstanceState(container);
23361     }
23362 
23363     /**
23364      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
23365      * state for this view and its children. May be overridden to modify how restoring
23366      * happens to a view's children; for example, some views may want to not store state
23367      * for their children.
23368      *
23369      * @param container The SparseArray which holds previously saved state.
23370      *
23371      * @see #dispatchSaveInstanceState(android.util.SparseArray)
23372      * @see #restoreHierarchyState(android.util.SparseArray)
23373      * @see #onRestoreInstanceState(android.os.Parcelable)
23374      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)23375     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
23376         if (mID != NO_ID) {
23377             Parcelable state = container.get(mID);
23378             if (state != null) {
23379                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
23380                 // + ": " + state);
23381                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
23382                 onRestoreInstanceState(state);
23383                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
23384                     throw new IllegalStateException(
23385                             "Derived class did not call super.onRestoreInstanceState()");
23386                 }
23387             }
23388         }
23389     }
23390 
23391     /**
23392      * Hook allowing a view to re-apply a representation of its internal state that had previously
23393      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
23394      * null state.
23395      *
23396      * @param state The frozen state that had previously been returned by
23397      *        {@link #onSaveInstanceState}.
23398      *
23399      * @see #onSaveInstanceState()
23400      * @see #restoreHierarchyState(android.util.SparseArray)
23401      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
23402      */
23403     @CallSuper
onRestoreInstanceState(Parcelable state)23404     protected void onRestoreInstanceState(Parcelable state) {
23405         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
23406         if (state != null && !(state instanceof AbsSavedState)) {
23407             throw new IllegalArgumentException("Wrong state class, expecting View State but "
23408                     + "received " + state.getClass().toString() + " instead. This usually happens "
23409                     + "when two views of different type have the same id in the same hierarchy. "
23410                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
23411                     + "other views do not use the same id.");
23412         }
23413         if (state != null && state instanceof BaseSavedState) {
23414             BaseSavedState baseState = (BaseSavedState) state;
23415 
23416             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
23417                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
23418             }
23419             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
23420                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
23421             }
23422             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
23423                 // It can happen that views have the same view id and the restoration path will not
23424                 // be able to distinguish between them. The autofill id needs to be unique though.
23425                 // Hence prevent the same autofill view id from being restored multiple times.
23426                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
23427 
23428                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
23429                     // Ignore when view already set it through setAutofillId();
23430                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
23431                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
23432                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
23433                                 + " it to " + mAutofillId);
23434                     }
23435                 } else {
23436                     mAutofillViewId = baseState.mAutofillViewId;
23437                     mAutofillId = null; // will be set on demand by getAutofillId()
23438                 }
23439             }
23440         }
23441     }
23442 
23443     /**
23444      * <p>Return the time at which the drawing of the view hierarchy started.</p>
23445      *
23446      * @return the drawing start time in milliseconds
23447      */
getDrawingTime()23448     public long getDrawingTime() {
23449         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
23450     }
23451 
23452     /**
23453      * <p>Enables or disables the duplication of the parent's state into this view. When
23454      * duplication is enabled, this view gets its drawable state from its parent rather
23455      * than from its own internal properties.</p>
23456      *
23457      * <p>Note: in the current implementation, setting this property to true after the
23458      * view was added to a ViewGroup might have no effect at all. This property should
23459      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
23460      *
23461      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
23462      * property is enabled, an exception will be thrown.</p>
23463      *
23464      * <p>Note: if the child view uses and updates additional states which are unknown to the
23465      * parent, these states should not be affected by this method.</p>
23466      *
23467      * @param enabled True to enable duplication of the parent's drawable state, false
23468      *                to disable it.
23469      *
23470      * @see #getDrawableState()
23471      * @see #isDuplicateParentStateEnabled()
23472      */
setDuplicateParentStateEnabled(boolean enabled)23473     public void setDuplicateParentStateEnabled(boolean enabled) {
23474         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
23475     }
23476 
23477     /**
23478      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
23479      *
23480      * @return True if this view's drawable state is duplicated from the parent,
23481      *         false otherwise
23482      *
23483      * @see #getDrawableState()
23484      * @see #setDuplicateParentStateEnabled(boolean)
23485      */
23486     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()23487     public boolean isDuplicateParentStateEnabled() {
23488         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
23489     }
23490 
23491     /**
23492      * <p>Specifies the type of layer backing this view. The layer can be
23493      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
23494      * {@link #LAYER_TYPE_HARDWARE}.</p>
23495      *
23496      * <p>A layer is associated with an optional {@link android.graphics.Paint}
23497      * instance that controls how the layer is composed on screen. The following
23498      * properties of the paint are taken into account when composing the layer:</p>
23499      * <ul>
23500      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
23501      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
23502      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
23503      * </ul>
23504      *
23505      * <p>If this view has an alpha value set to < 1.0 by calling
23506      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
23507      * by this view's alpha value.</p>
23508      *
23509      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
23510      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
23511      * for more information on when and how to use layers.</p>
23512      *
23513      * @param layerType The type of layer to use with this view, must be one of
23514      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
23515      *        {@link #LAYER_TYPE_HARDWARE}
23516      * @param paint The paint used to compose the layer. This argument is optional
23517      *        and can be null. It is ignored when the layer type is
23518      *        {@link #LAYER_TYPE_NONE}
23519      *
23520      * @see #getLayerType()
23521      * @see #LAYER_TYPE_NONE
23522      * @see #LAYER_TYPE_SOFTWARE
23523      * @see #LAYER_TYPE_HARDWARE
23524      * @see #setAlpha(float)
23525      *
23526      * @attr ref android.R.styleable#View_layerType
23527      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)23528     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
23529         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
23530             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
23531                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
23532         }
23533 
23534         boolean typeChanged = mRenderNode.setLayerType(layerType);
23535 
23536         if (!typeChanged) {
23537             setLayerPaint(paint);
23538             return;
23539         }
23540 
23541         if (layerType != LAYER_TYPE_SOFTWARE) {
23542             // Destroy any previous software drawing cache if present
23543             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
23544             // drawing cache created in View#draw when drawing to a SW canvas.
23545             destroyDrawingCache();
23546         }
23547 
23548         mLayerType = layerType;
23549         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
23550         mRenderNode.setLayerPaint(mLayerPaint);
23551 
23552         // draw() behaves differently if we are on a layer, so we need to
23553         // invalidate() here
23554         invalidateParentCaches();
23555         invalidate(true);
23556     }
23557 
23558     /**
23559      * Configure the {@link android.graphics.RenderEffect} to apply to this View.
23560      * This will apply a visual effect to the results of the View before it is drawn. For example if
23561      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
23562      * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
23563      * when this View is drawn.
23564      * @param renderEffect to be applied to the View. Passing null clears the previously configured
23565      *                     {@link RenderEffect}
23566      */
setRenderEffect(@ullable RenderEffect renderEffect)23567     public void setRenderEffect(@Nullable RenderEffect renderEffect) {
23568         if (mRenderNode.setRenderEffect(renderEffect)) {
23569             invalidateViewProperty(true, true);
23570         }
23571     }
23572 
23573     /**
23574      * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of this
23575      * View. This will apply a visual effect to the result of the backdrop contents of this View
23576      * before it is drawn. For example if
23577      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
23578      * is provided, the previous content behind this View will be blurred before this View is drawn.
23579      * @param renderEffect to be applied to the View. Passing null clears the previously configured
23580      *                     {@link RenderEffect}
23581      * @hide
23582      */
setBackdropRenderEffect(@ullable RenderEffect renderEffect)23583     public void setBackdropRenderEffect(@Nullable RenderEffect renderEffect) {
23584         if (mRenderNode.setBackdropRenderEffect(renderEffect)) {
23585             invalidateViewProperty(true, true);
23586         }
23587     }
23588 
23589     /**
23590      * Updates the {@link Paint} object used with the current layer (used only if the current
23591      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
23592      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
23593      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
23594      * ensure that the view gets redrawn immediately.
23595      *
23596      * <p>A layer is associated with an optional {@link android.graphics.Paint}
23597      * instance that controls how the layer is composed on screen. The following
23598      * properties of the paint are taken into account when composing the layer:</p>
23599      * <ul>
23600      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
23601      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
23602      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
23603      * </ul>
23604      *
23605      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
23606      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
23607      *
23608      * @param paint The paint used to compose the layer. This argument is optional
23609      *        and can be null. It is ignored when the layer type is
23610      *        {@link #LAYER_TYPE_NONE}
23611      *
23612      * @see #setLayerType(int, android.graphics.Paint)
23613      */
setLayerPaint(@ullable Paint paint)23614     public void setLayerPaint(@Nullable Paint paint) {
23615         int layerType = getLayerType();
23616         if (layerType != LAYER_TYPE_NONE) {
23617             mLayerPaint = paint;
23618             if (layerType == LAYER_TYPE_HARDWARE) {
23619                 if (mRenderNode.setLayerPaint(paint)) {
23620                     invalidateViewProperty(false, false);
23621                 }
23622             } else {
23623                 invalidate();
23624             }
23625         }
23626     }
23627 
23628     /**
23629      * Indicates what type of layer is currently associated with this view. By default
23630      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
23631      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
23632      * for more information on the different types of layers.
23633      *
23634      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
23635      *         {@link #LAYER_TYPE_HARDWARE}
23636      *
23637      * @see #setLayerType(int, android.graphics.Paint)
23638      * @see #buildLayer()
23639      * @see #LAYER_TYPE_NONE
23640      * @see #LAYER_TYPE_SOFTWARE
23641      * @see #LAYER_TYPE_HARDWARE
23642      */
23643     @InspectableProperty(enumMapping = {
23644             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
23645             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
23646             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
23647     })
23648     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
23649             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
23650             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
23651             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
23652     })
23653     @LayerType
getLayerType()23654     public int getLayerType() {
23655         return mLayerType;
23656     }
23657 
23658     /**
23659      * Forces this view's layer to be created and this view to be rendered
23660      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
23661      * invoking this method will have no effect.
23662      *
23663      * This method can for instance be used to render a view into its layer before
23664      * starting an animation. If this view is complex, rendering into the layer
23665      * before starting the animation will avoid skipping frames.
23666      *
23667      * @throws IllegalStateException If this view is not attached to a window
23668      *
23669      * @see #setLayerType(int, android.graphics.Paint)
23670      */
buildLayer()23671     public void buildLayer() {
23672         if (mLayerType == LAYER_TYPE_NONE) return;
23673 
23674         final AttachInfo attachInfo = mAttachInfo;
23675         if (attachInfo == null) {
23676             throw new IllegalStateException("This view must be attached to a window first");
23677         }
23678 
23679         if (getWidth() == 0 || getHeight() == 0) {
23680             return;
23681         }
23682 
23683         switch (mLayerType) {
23684             case LAYER_TYPE_HARDWARE:
23685                 updateDisplayListIfDirty();
23686                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
23687                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
23688                 }
23689                 break;
23690             case LAYER_TYPE_SOFTWARE:
23691                 buildDrawingCache(true);
23692                 break;
23693         }
23694     }
23695 
23696     /**
23697      * Determines whether an unprocessed input event is available on the window.
23698      *
23699      * This is only a performance hint (a.k.a. the Input Hint) and may return false negative
23700      * results.  Callers should not rely on availability of the input event based on the return
23701      * value of this method.
23702      *
23703      * The Input Hint functionality is experimental, and can be removed in the future OS releases.
23704      *
23705      * This method only returns nontrivial results on a View that is attached to a Window. Such View
23706      * can be acquired using `Activity.getWindow().getDecorView()`, and only after the view
23707      * hierarchy is attached (via {@link android.app.Activity#setContentView(android.view.View)}).
23708      *
23709      * In multi-window mode the View can provide the Input Hint only for the window it is attached
23710      * to. Therefore, checking input availability for the whole application would require asking
23711      * for the hint from more than one View.
23712      *
23713      * The initial implementation does not return false positives, but callers should not rely on
23714      * it: false positives may occur in future OS releases.
23715      *
23716      * @hide
23717      */
probablyHasInput()23718     public boolean probablyHasInput() {
23719         ViewRootImpl viewRootImpl = getViewRootImpl();
23720         if (viewRootImpl == null) {
23721             return false;
23722         }
23723         return viewRootImpl.probablyHasInput();
23724     }
23725 
23726     /**
23727      * Destroys all hardware rendering resources. This method is invoked
23728      * when the system needs to reclaim resources. Upon execution of this
23729      * method, you should free any OpenGL resources created by the view.
23730      *
23731      * Note: you <strong>must</strong> call
23732      * <code>super.destroyHardwareResources()</code> when overriding
23733      * this method.
23734      *
23735      * @hide
23736      */
23737     @CallSuper
23738     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
destroyHardwareResources()23739     protected void destroyHardwareResources() {
23740         if (mOverlay != null) {
23741             mOverlay.getOverlayView().destroyHardwareResources();
23742         }
23743         if (mGhostView != null) {
23744             mGhostView.destroyHardwareResources();
23745         }
23746     }
23747 
23748     /**
23749      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
23750      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
23751      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
23752      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
23753      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
23754      * null.</p>
23755      *
23756      * <p>Enabling the drawing cache is similar to
23757      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
23758      * acceleration is turned off. When hardware acceleration is turned on, enabling the
23759      * drawing cache has no effect on rendering because the system uses a different mechanism
23760      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
23761      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
23762      * for information on how to enable software and hardware layers.</p>
23763      *
23764      * <p>This API can be used to manually generate
23765      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
23766      * {@link #getDrawingCache()}.</p>
23767      *
23768      * @param enabled true to enable the drawing cache, false otherwise
23769      *
23770      * @see #isDrawingCacheEnabled()
23771      * @see #getDrawingCache()
23772      * @see #buildDrawingCache()
23773      * @see #setLayerType(int, android.graphics.Paint)
23774      *
23775      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23776      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23777      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23778      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23779      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23780      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23781      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23782      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23783      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23784      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23785      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23786      * reports or unit testing the {@link PixelCopy} API is recommended.
23787      */
23788     @Deprecated
setDrawingCacheEnabled(boolean enabled)23789     public void setDrawingCacheEnabled(boolean enabled) {
23790         mCachingFailed = false;
23791         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
23792     }
23793 
23794     /**
23795      * <p>Indicates whether the drawing cache is enabled for this view.</p>
23796      *
23797      * @return true if the drawing cache is enabled
23798      *
23799      * @see #setDrawingCacheEnabled(boolean)
23800      * @see #getDrawingCache()
23801      *
23802      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23803      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23804      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23805      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23806      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23807      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23808      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23809      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23810      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23811      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23812      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23813      * reports or unit testing the {@link PixelCopy} API is recommended.
23814      */
23815     @Deprecated
23816     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()23817     public boolean isDrawingCacheEnabled() {
23818         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
23819     }
23820 
23821     /**
23822      * Debugging utility which recursively outputs the dirty state of a view and its
23823      * descendants.
23824      *
23825      * @hide
23826      */
23827     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)23828     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
23829         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
23830                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
23831                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
23832                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
23833                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
23834         if (clear) {
23835             mPrivateFlags &= clearMask;
23836         }
23837         if (this instanceof ViewGroup) {
23838             ViewGroup parent = (ViewGroup) this;
23839             final int count = parent.getChildCount();
23840             for (int i = 0; i < count; i++) {
23841                 final View child = parent.getChildAt(i);
23842                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
23843             }
23844         }
23845     }
23846 
23847     /**
23848      * This method is used by ViewGroup to cause its children to restore or recreate their
23849      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
23850      * to recreate its own display list, which would happen if it went through the normal
23851      * draw/dispatchDraw mechanisms.
23852      *
23853      * @hide
23854      */
dispatchGetDisplayList()23855     protected void dispatchGetDisplayList() {}
23856 
23857     /**
23858      * A view that is not attached or hardware accelerated cannot create a display list.
23859      * This method checks these conditions and returns the appropriate result.
23860      *
23861      * @return true if view has the ability to create a display list, false otherwise.
23862      *
23863      * @hide
23864      */
canHaveDisplayList()23865     public boolean canHaveDisplayList() {
23866         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
23867     }
23868 
23869     /**
23870      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
23871      * @hide
23872      */
23873     @NonNull
23874     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateDisplayListIfDirty()23875     public RenderNode updateDisplayListIfDirty() {
23876         final RenderNode renderNode = mRenderNode;
23877         if (!canHaveDisplayList()) {
23878             // can't populate RenderNode, don't try
23879             return renderNode;
23880         }
23881 
23882         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
23883                 || !renderNode.hasDisplayList()
23884                 || (mRecreateDisplayList)) {
23885             // Don't need to recreate the display list, just need to tell our
23886             // children to restore/recreate theirs
23887             if (renderNode.hasDisplayList()
23888                     && !mRecreateDisplayList) {
23889                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
23890                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23891                 dispatchGetDisplayList();
23892 
23893                 return renderNode; // no work needed
23894             }
23895 
23896             // If we got here, we're recreating it. Mark it as such to ensure that
23897             // we copy in child display lists into ours in drawChild()
23898             mRecreateDisplayList = true;
23899 
23900             int width = mRight - mLeft;
23901             int height = mBottom - mTop;
23902             int layerType = getLayerType();
23903 
23904             // Hacky hack: Reset any stretch effects as those are applied during the draw pass
23905             // instead of being "stateful" like other RenderNode properties
23906             renderNode.clearStretch();
23907 
23908             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
23909 
23910             try {
23911                 if (layerType == LAYER_TYPE_SOFTWARE) {
23912                     buildDrawingCache(true);
23913                     Bitmap cache = getDrawingCache(true);
23914                     if (cache != null) {
23915                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
23916                     }
23917                 } else {
23918                     computeScroll();
23919 
23920                     canvas.translate(-mScrollX, -mScrollY);
23921                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
23922                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23923 
23924                     mPrivateFlags4 |= PFLAG4_HAS_DRAWN;
23925 
23926                     // Fast path for layouts with no backgrounds
23927                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
23928                         dispatchDraw(canvas);
23929                         drawAutofilledHighlight(canvas);
23930                         if (mOverlay != null && !mOverlay.isEmpty()) {
23931                             mOverlay.getOverlayView().draw(canvas);
23932                         }
23933                         if (isShowingLayoutBounds()) {
23934                             debugDrawFocus(canvas);
23935                         }
23936                     } else {
23937                         draw(canvas);
23938                     }
23939 
23940                     // For VRR to vote the preferred frame rate
23941                     if (sToolkitSetFrameRateReadOnlyFlagValue
23942                             && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
23943                         votePreferredFrameRate();
23944                     }
23945                 }
23946             } finally {
23947                 renderNode.endRecording();
23948                 setDisplayListProperties(renderNode);
23949             }
23950         } else {
23951             if ((mPrivateFlags4 & PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION)
23952                     == PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION) {
23953                 // For VRR to vote the preferred frame rate
23954                 if (sToolkitSetFrameRateReadOnlyFlagValue
23955                         && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
23956                     votePreferredFrameRate();
23957                 }
23958                 mPrivateFlags4 &= ~PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
23959             }
23960             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
23961             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23962         }
23963         mPrivateFlags4 &= ~PFLAG4_HAS_MOVED;
23964         mFrameContentVelocity = -1;
23965         return renderNode;
23966     }
23967 
23968     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resetDisplayList()23969     private void resetDisplayList() {
23970         mRenderNode.discardDisplayList();
23971         if (mBackgroundRenderNode != null) {
23972             mBackgroundRenderNode.discardDisplayList();
23973         }
23974     }
23975 
23976     /**
23977      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
23978      *
23979      * @return A non-scaled bitmap representing this view or null if cache is disabled.
23980      *
23981      * @see #getDrawingCache(boolean)
23982      *
23983      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23984      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23985      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23986      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23987      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23988      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23989      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23990      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23991      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23992      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23993      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23994      * reports or unit testing the {@link PixelCopy} API is recommended.
23995      */
23996     @Deprecated
getDrawingCache()23997     public Bitmap getDrawingCache() {
23998         return getDrawingCache(false);
23999     }
24000 
24001     /**
24002      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
24003      * is null when caching is disabled. If caching is enabled and the cache is not ready,
24004      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
24005      * draw from the cache when the cache is enabled. To benefit from the cache, you must
24006      * request the drawing cache by calling this method and draw it on screen if the
24007      * returned bitmap is not null.</p>
24008      *
24009      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
24010      * this method will create a bitmap of the same size as this view. Because this bitmap
24011      * will be drawn scaled by the parent ViewGroup, the result on screen might show
24012      * scaling artifacts. To avoid such artifacts, you should call this method by setting
24013      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
24014      * size than the view. This implies that your application must be able to handle this
24015      * size.</p>
24016      *
24017      * @param autoScale Indicates whether the generated bitmap should be scaled based on
24018      *        the current density of the screen when the application is in compatibility
24019      *        mode.
24020      *
24021      * @return A bitmap representing this view or null if cache is disabled.
24022      *
24023      * @see #setDrawingCacheEnabled(boolean)
24024      * @see #isDrawingCacheEnabled()
24025      * @see #buildDrawingCache(boolean)
24026      * @see #destroyDrawingCache()
24027      *
24028      * @deprecated The view drawing cache was largely made obsolete with the introduction of
24029      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
24030      * layers are largely unnecessary and can easily result in a net loss in performance due to the
24031      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
24032      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
24033      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
24034      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
24035      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
24036      * software-rendered usages are discouraged and have compatibility issues with hardware-only
24037      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
24038      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
24039      * reports or unit testing the {@link PixelCopy} API is recommended.
24040      */
24041     @Deprecated
getDrawingCache(boolean autoScale)24042     public Bitmap getDrawingCache(boolean autoScale) {
24043         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
24044             return null;
24045         }
24046         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
24047             buildDrawingCache(autoScale);
24048         }
24049         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
24050     }
24051 
24052     /**
24053      * <p>Frees the resources used by the drawing cache. If you call
24054      * {@link #buildDrawingCache()} manually without calling
24055      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
24056      * should cleanup the cache with this method afterwards.</p>
24057      *
24058      * @see #setDrawingCacheEnabled(boolean)
24059      * @see #buildDrawingCache()
24060      * @see #getDrawingCache()
24061      *
24062      * @deprecated The view drawing cache was largely made obsolete with the introduction of
24063      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
24064      * layers are largely unnecessary and can easily result in a net loss in performance due to the
24065      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
24066      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
24067      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
24068      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
24069      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
24070      * software-rendered usages are discouraged and have compatibility issues with hardware-only
24071      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
24072      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
24073      * reports or unit testing the {@link PixelCopy} API is recommended.
24074      */
24075     @Deprecated
destroyDrawingCache()24076     public void destroyDrawingCache() {
24077         if (mDrawingCache != null) {
24078             mDrawingCache.recycle();
24079             mDrawingCache = null;
24080         }
24081         if (mUnscaledDrawingCache != null) {
24082             mUnscaledDrawingCache.recycle();
24083             mUnscaledDrawingCache = null;
24084         }
24085     }
24086 
24087     /**
24088      * Setting a solid background color for the drawing cache's bitmaps will improve
24089      * performance and memory usage. Note, though that this should only be used if this
24090      * view will always be drawn on top of a solid color.
24091      *
24092      * @param color The background color to use for the drawing cache's bitmap
24093      *
24094      * @see #setDrawingCacheEnabled(boolean)
24095      * @see #buildDrawingCache()
24096      * @see #getDrawingCache()
24097      *
24098      * @deprecated The view drawing cache was largely made obsolete with the introduction of
24099      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
24100      * layers are largely unnecessary and can easily result in a net loss in performance due to the
24101      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
24102      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
24103      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
24104      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
24105      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
24106      * software-rendered usages are discouraged and have compatibility issues with hardware-only
24107      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
24108      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
24109      * reports or unit testing the {@link PixelCopy} API is recommended.
24110      */
24111     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)24112     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
24113         if (color != mDrawingCacheBackgroundColor) {
24114             mDrawingCacheBackgroundColor = color;
24115             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
24116         }
24117     }
24118 
24119     /**
24120      * @see #setDrawingCacheBackgroundColor(int)
24121      *
24122      * @return The background color to used for the drawing cache's bitmap
24123      *
24124      * @deprecated The view drawing cache was largely made obsolete with the introduction of
24125      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
24126      * layers are largely unnecessary and can easily result in a net loss in performance due to the
24127      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
24128      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
24129      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
24130      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
24131      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
24132      * software-rendered usages are discouraged and have compatibility issues with hardware-only
24133      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
24134      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
24135      * reports or unit testing the {@link PixelCopy} API is recommended.
24136      */
24137     @Deprecated
24138     @ColorInt
getDrawingCacheBackgroundColor()24139     public int getDrawingCacheBackgroundColor() {
24140         return mDrawingCacheBackgroundColor;
24141     }
24142 
24143     /**
24144      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
24145      *
24146      * @see #buildDrawingCache(boolean)
24147      *
24148      * @deprecated The view drawing cache was largely made obsolete with the introduction of
24149      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
24150      * layers are largely unnecessary and can easily result in a net loss in performance due to the
24151      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
24152      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
24153      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
24154      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
24155      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
24156      * software-rendered usages are discouraged and have compatibility issues with hardware-only
24157      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
24158      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
24159      * reports or unit testing the {@link PixelCopy} API is recommended.
24160      */
24161     @Deprecated
buildDrawingCache()24162     public void buildDrawingCache() {
24163         buildDrawingCache(false);
24164     }
24165 
24166     /**
24167      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
24168      *
24169      * <p>If you call {@link #buildDrawingCache()} manually without calling
24170      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
24171      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
24172      *
24173      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
24174      * this method will create a bitmap of the same size as this view. Because this bitmap
24175      * will be drawn scaled by the parent ViewGroup, the result on screen might show
24176      * scaling artifacts. To avoid such artifacts, you should call this method by setting
24177      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
24178      * size than the view. This implies that your application must be able to handle this
24179      * size.</p>
24180      *
24181      * <p>You should avoid calling this method when hardware acceleration is enabled. If
24182      * you do not need the drawing cache bitmap, calling this method will increase memory
24183      * usage and cause the view to be rendered in software once, thus negatively impacting
24184      * performance.</p>
24185      *
24186      * @see #getDrawingCache()
24187      * @see #destroyDrawingCache()
24188      *
24189      * @deprecated The view drawing cache was largely made obsolete with the introduction of
24190      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
24191      * layers are largely unnecessary and can easily result in a net loss in performance due to the
24192      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
24193      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
24194      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
24195      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
24196      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
24197      * software-rendered usages are discouraged and have compatibility issues with hardware-only
24198      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
24199      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
24200      * reports or unit testing the {@link PixelCopy} API is recommended.
24201      */
24202     @Deprecated
buildDrawingCache(boolean autoScale)24203     public void buildDrawingCache(boolean autoScale) {
24204         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
24205                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
24206             if (Trace.isTagEnabled(TRACE_TAG_VIEW)) {
24207                 Trace.traceBegin(TRACE_TAG_VIEW,
24208                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
24209             }
24210             try {
24211                 buildDrawingCacheImpl(autoScale);
24212             } finally {
24213                 Trace.traceEnd(TRACE_TAG_VIEW);
24214             }
24215         }
24216     }
24217 
24218     /**
24219      * private, internal implementation of buildDrawingCache, used to enable tracing
24220      */
buildDrawingCacheImpl(boolean autoScale)24221     private void buildDrawingCacheImpl(boolean autoScale) {
24222         mCachingFailed = false;
24223 
24224         int width = mRight - mLeft;
24225         int height = mBottom - mTop;
24226 
24227         final AttachInfo attachInfo = mAttachInfo;
24228         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
24229 
24230         if (autoScale && scalingRequired) {
24231             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
24232             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
24233         }
24234 
24235         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
24236         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
24237         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
24238 
24239         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
24240         final long drawingCacheSize =
24241                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
24242         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
24243             if (width > 0 && height > 0) {
24244                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
24245                         + " too large to fit into a software layer (or drawing cache), needs "
24246                         + projectedBitmapSize + " bytes, only "
24247                         + drawingCacheSize + " available");
24248             }
24249             destroyDrawingCache();
24250             mCachingFailed = true;
24251             return;
24252         }
24253 
24254         boolean clear = true;
24255         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
24256 
24257         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
24258             Bitmap.Config quality;
24259             if (!opaque) {
24260                 // Never pick ARGB_4444 because it looks awful
24261                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
24262                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
24263                     case DRAWING_CACHE_QUALITY_AUTO:
24264                     case DRAWING_CACHE_QUALITY_LOW:
24265                     case DRAWING_CACHE_QUALITY_HIGH:
24266                     default:
24267                         quality = Bitmap.Config.ARGB_8888;
24268                         break;
24269                 }
24270             } else {
24271                 // Optimization for translucent windows
24272                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
24273                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
24274             }
24275 
24276             // Try to cleanup memory
24277             if (bitmap != null) bitmap.recycle();
24278 
24279             try {
24280                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
24281                         width, height, quality);
24282                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
24283                 if (autoScale) {
24284                     mDrawingCache = bitmap;
24285                 } else {
24286                     mUnscaledDrawingCache = bitmap;
24287                 }
24288                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
24289             } catch (OutOfMemoryError e) {
24290                 // If there is not enough memory to create the bitmap cache, just
24291                 // ignore the issue as bitmap caches are not required to draw the
24292                 // view hierarchy
24293                 if (autoScale) {
24294                     mDrawingCache = null;
24295                 } else {
24296                     mUnscaledDrawingCache = null;
24297                 }
24298                 mCachingFailed = true;
24299                 return;
24300             }
24301 
24302             clear = drawingCacheBackgroundColor != 0;
24303         }
24304 
24305         Canvas canvas;
24306         if (attachInfo != null) {
24307             canvas = attachInfo.mCanvas;
24308             if (canvas == null) {
24309                 canvas = new Canvas();
24310             }
24311             canvas.setBitmap(bitmap);
24312             // Temporarily clobber the cached Canvas in case one of our children
24313             // is also using a drawing cache. Without this, the children would
24314             // steal the canvas by attaching their own bitmap to it and bad, bad
24315             // thing would happen (invisible views, corrupted drawings, etc.)
24316             attachInfo.mCanvas = null;
24317         } else {
24318             // This case should hopefully never or seldom happen
24319             canvas = new Canvas(bitmap);
24320         }
24321 
24322         if (clear) {
24323             bitmap.eraseColor(drawingCacheBackgroundColor);
24324         }
24325 
24326         computeScroll();
24327         final int restoreCount = canvas.save();
24328 
24329         if (autoScale && scalingRequired) {
24330             final float scale = attachInfo.mApplicationScale;
24331             canvas.scale(scale, scale);
24332         }
24333 
24334         canvas.translate(-mScrollX, -mScrollY);
24335 
24336         mPrivateFlags |= PFLAG_DRAWN;
24337         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
24338                 mLayerType != LAYER_TYPE_NONE) {
24339             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
24340         }
24341 
24342         // Fast path for layouts with no backgrounds
24343         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
24344             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24345             dispatchDraw(canvas);
24346             drawAutofilledHighlight(canvas);
24347             if (mOverlay != null && !mOverlay.isEmpty()) {
24348                 mOverlay.getOverlayView().draw(canvas);
24349             }
24350         } else {
24351             draw(canvas);
24352         }
24353 
24354         canvas.restoreToCount(restoreCount);
24355         canvas.setBitmap(null);
24356 
24357         if (attachInfo != null) {
24358             // Restore the cached Canvas for our siblings
24359             attachInfo.mCanvas = canvas;
24360         }
24361     }
24362 
24363     /**
24364      * Create a snapshot of the view into a bitmap.  We should probably make
24365      * some form of this public, but should think about the API.
24366      *
24367      * @hide
24368      */
24369     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)24370     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
24371         int width = mRight - mLeft;
24372         int height = mBottom - mTop;
24373 
24374         final AttachInfo attachInfo = mAttachInfo;
24375         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
24376         width = (int) ((width * scale) + 0.5f);
24377         height = (int) ((height * scale) + 0.5f);
24378 
24379         Canvas oldCanvas = null;
24380         try {
24381             Canvas canvas = canvasProvider.getCanvas(this,
24382                     width > 0 ? width : 1, height > 0 ? height : 1);
24383 
24384             if (attachInfo != null) {
24385                 oldCanvas = attachInfo.mCanvas;
24386                 // Temporarily clobber the cached Canvas in case one of our children
24387                 // is also using a drawing cache. Without this, the children would
24388                 // steal the canvas by attaching their own bitmap to it and bad, bad
24389                 // things would happen (invisible views, corrupted drawings, etc.)
24390                 attachInfo.mCanvas = null;
24391             }
24392 
24393             computeScroll();
24394             final int restoreCount = canvas.save();
24395             canvas.scale(scale, scale);
24396             canvas.translate(-mScrollX, -mScrollY);
24397 
24398             // Temporarily remove the dirty mask
24399             int flags = mPrivateFlags;
24400             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24401 
24402             // Fast path for layouts with no backgrounds
24403             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
24404                 dispatchDraw(canvas);
24405                 drawAutofilledHighlight(canvas);
24406                 if (mOverlay != null && !mOverlay.isEmpty()) {
24407                     mOverlay.getOverlayView().draw(canvas);
24408                 }
24409             } else {
24410                 draw(canvas);
24411             }
24412 
24413             mPrivateFlags = flags;
24414             canvas.restoreToCount(restoreCount);
24415             return canvasProvider.createBitmap();
24416         } finally {
24417             if (oldCanvas != null) {
24418                 attachInfo.mCanvas = oldCanvas;
24419             }
24420         }
24421     }
24422 
24423     /**
24424      * Indicates whether this View is currently in edit mode. A View is usually
24425      * in edit mode when displayed within a developer tool. For instance, if
24426      * this View is being drawn by a visual user interface builder, this method
24427      * should return true.
24428      *
24429      * Subclasses should check the return value of this method to provide
24430      * different behaviors if their normal behavior might interfere with the
24431      * host environment. For instance: the class spawns a thread in its
24432      * constructor, the drawing code relies on device-specific features, etc.
24433      *
24434      * This method is usually checked in the drawing code of custom widgets.
24435      *
24436      * @return True if this View is in edit mode, false otherwise.
24437      */
isInEditMode()24438     public boolean isInEditMode() {
24439         return false;
24440     }
24441 
24442     /**
24443      * If the View draws content inside its padding and enables fading edges,
24444      * it needs to support padding offsets. Padding offsets are added to the
24445      * fading edges to extend the length of the fade so that it covers pixels
24446      * drawn inside the padding.
24447      *
24448      * Subclasses of this class should override this method if they need
24449      * to draw content inside the padding.
24450      *
24451      * @return True if padding offset must be applied, false otherwise.
24452      *
24453      * @see #getLeftPaddingOffset()
24454      * @see #getRightPaddingOffset()
24455      * @see #getTopPaddingOffset()
24456      * @see #getBottomPaddingOffset()
24457      *
24458      * @since CURRENT
24459      */
isPaddingOffsetRequired()24460     protected boolean isPaddingOffsetRequired() {
24461         return false;
24462     }
24463 
24464     /**
24465      * Amount by which to extend the left fading region. Called only when
24466      * {@link #isPaddingOffsetRequired()} returns true.
24467      *
24468      * @return The left padding offset in pixels.
24469      *
24470      * @see #isPaddingOffsetRequired()
24471      *
24472      * @since CURRENT
24473      */
getLeftPaddingOffset()24474     protected int getLeftPaddingOffset() {
24475         return 0;
24476     }
24477 
24478     /**
24479      * Amount by which to extend the right fading region. Called only when
24480      * {@link #isPaddingOffsetRequired()} returns true.
24481      *
24482      * @return The right padding offset in pixels.
24483      *
24484      * @see #isPaddingOffsetRequired()
24485      *
24486      * @since CURRENT
24487      */
getRightPaddingOffset()24488     protected int getRightPaddingOffset() {
24489         return 0;
24490     }
24491 
24492     /**
24493      * Amount by which to extend the top fading region. Called only when
24494      * {@link #isPaddingOffsetRequired()} returns true.
24495      *
24496      * @return The top padding offset in pixels.
24497      *
24498      * @see #isPaddingOffsetRequired()
24499      *
24500      * @since CURRENT
24501      */
getTopPaddingOffset()24502     protected int getTopPaddingOffset() {
24503         return 0;
24504     }
24505 
24506     /**
24507      * Amount by which to extend the bottom fading region. Called only when
24508      * {@link #isPaddingOffsetRequired()} returns true.
24509      *
24510      * @return The bottom padding offset in pixels.
24511      *
24512      * @see #isPaddingOffsetRequired()
24513      *
24514      * @since CURRENT
24515      */
getBottomPaddingOffset()24516     protected int getBottomPaddingOffset() {
24517         return 0;
24518     }
24519 
24520     /**
24521      * @hide
24522      * @param offsetRequired
24523      */
getFadeTop(boolean offsetRequired)24524     protected int getFadeTop(boolean offsetRequired) {
24525         int top = mPaddingTop;
24526         if (offsetRequired) top += getTopPaddingOffset();
24527         return top;
24528     }
24529 
24530     /**
24531      * @hide
24532      * @param offsetRequired
24533      */
getFadeHeight(boolean offsetRequired)24534     protected int getFadeHeight(boolean offsetRequired) {
24535         int padding = mPaddingTop;
24536         if (offsetRequired) padding += getTopPaddingOffset();
24537         return mBottom - mTop - mPaddingBottom - padding;
24538     }
24539 
24540     /**
24541      * <p>Indicates whether this view is attached to a hardware accelerated
24542      * window or not.</p>
24543      *
24544      * <p>Even if this method returns true, it does not mean that every call
24545      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
24546      * accelerated {@link android.graphics.Canvas}. For instance, if this view
24547      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
24548      * window is hardware accelerated,
24549      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
24550      * return false, and this method will return true.</p>
24551      *
24552      * @return True if the view is attached to a window and the window is
24553      *         hardware accelerated; false in any other case.
24554      */
24555     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()24556     public boolean isHardwareAccelerated() {
24557         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
24558     }
24559 
24560     /**
24561      * Sets a rectangular area on this view to which the view will be clipped
24562      * when it is drawn. Setting the value to null will remove the clip bounds
24563      * and the view will draw normally, using its full bounds.
24564      *
24565      * @param clipBounds The rectangular area, in the local coordinates of
24566      * this view, to which future drawing operations will be clipped.
24567      */
setClipBounds(Rect clipBounds)24568     public void setClipBounds(Rect clipBounds) {
24569         if (clipBounds == mClipBounds
24570                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
24571             return;
24572         }
24573         if (clipBounds != null) {
24574             if (mClipBounds == null) {
24575                 mClipBounds = new Rect(clipBounds);
24576             } else {
24577                 mClipBounds.set(clipBounds);
24578             }
24579         } else {
24580             mClipBounds = null;
24581         }
24582         mRenderNode.setClipRect(mClipBounds);
24583         invalidateViewProperty(false, false);
24584     }
24585 
24586     /**
24587      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
24588      *
24589      * @return A copy of the current clip bounds if clip bounds are set,
24590      * otherwise null.
24591      */
getClipBounds()24592     public Rect getClipBounds() {
24593         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
24594     }
24595 
24596 
24597     /**
24598      * Populates an output rectangle with the clip bounds of the view,
24599      * returning {@code true} if successful or {@code false} if the view's
24600      * clip bounds are {@code null}.
24601      *
24602      * @param outRect rectangle in which to place the clip bounds of the view
24603      * @return {@code true} if successful or {@code false} if the view's
24604      *         clip bounds are {@code null}
24605      */
getClipBounds(Rect outRect)24606     public boolean getClipBounds(Rect outRect) {
24607         if (mClipBounds != null) {
24608             outRect.set(mClipBounds);
24609             return true;
24610         }
24611         return false;
24612     }
24613 
24614     /**
24615      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
24616      * case of an active Animation being run on the view.
24617      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)24618     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
24619             Animation a, boolean scalingRequired) {
24620         Transformation invalidationTransform;
24621         final int flags = parent.mGroupFlags;
24622         final boolean initialized = a.isInitialized();
24623         if (!initialized) {
24624             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
24625             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
24626             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
24627             onAnimationStart();
24628         }
24629 
24630         final Transformation t = parent.getChildTransformation();
24631         boolean more = a.getTransformation(drawingTime, t, 1f);
24632         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
24633             if (parent.mInvalidationTransformation == null) {
24634                 parent.mInvalidationTransformation = new Transformation();
24635             }
24636             invalidationTransform = parent.mInvalidationTransformation;
24637             a.getTransformation(drawingTime, invalidationTransform, 1f);
24638         } else {
24639             invalidationTransform = t;
24640         }
24641 
24642         // Increase the frame rate if there is a transformation that applies a matrix.
24643         if (sToolkitFrameRateAnimationBugfix25q1FlagValue
24644                 && ((t.getTransformationType() & Transformation.TYPE_MATRIX) != 0)) {
24645             mPrivateFlags4 |= PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
24646             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
24647         }
24648 
24649         if (more) {
24650             if (!a.willChangeBounds()) {
24651                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
24652                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
24653                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
24654                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
24655                     // The child need to draw an animation, potentially offscreen, so
24656                     // make sure we do not cancel invalidate requests
24657                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
24658                     parent.invalidate(mLeft, mTop, mRight, mBottom);
24659                 }
24660             } else {
24661                 if (parent.mInvalidateRegion == null) {
24662                     parent.mInvalidateRegion = new RectF();
24663                 }
24664                 final RectF region = parent.mInvalidateRegion;
24665                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
24666                         invalidationTransform);
24667 
24668                 // The child need to draw an animation, potentially offscreen, so
24669                 // make sure we do not cancel invalidate requests
24670                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
24671 
24672                 final int left = mLeft + (int) region.left;
24673                 final int top = mTop + (int) region.top;
24674                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
24675                         top + (int) (region.height() + .5f));
24676             }
24677         }
24678         return more;
24679     }
24680 
24681     /**
24682      * This method is called by getDisplayList() when a display list is recorded for a View.
24683      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
24684      */
setDisplayListProperties(RenderNode renderNode)24685     void setDisplayListProperties(RenderNode renderNode) {
24686         if (renderNode != null) {
24687             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
24688             renderNode.setClipToBounds(mParent instanceof ViewGroup
24689                     && ((ViewGroup) mParent).getClipChildren());
24690 
24691             float alpha = 1;
24692             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
24693                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
24694                 ViewGroup parentVG = (ViewGroup) mParent;
24695                 final Transformation t = parentVG.getChildTransformation();
24696                 if (parentVG.getChildStaticTransformation(this, t)) {
24697                     final int transformType = t.getTransformationType();
24698                     if (transformType != Transformation.TYPE_IDENTITY) {
24699                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
24700                             alpha = t.getAlpha();
24701                         }
24702                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
24703                             renderNode.setStaticMatrix(t.getMatrix());
24704                         }
24705                     }
24706                 }
24707             }
24708             if (mTransformationInfo != null) {
24709                 alpha *= getFinalAlpha();
24710                 if (alpha < 1) {
24711                     final int multipliedAlpha = (int) (255 * alpha);
24712                     if (onSetAlpha(multipliedAlpha)) {
24713                         alpha = 1;
24714                     }
24715                 }
24716                 renderNode.setAlpha(alpha);
24717             } else if (alpha < 1) {
24718                 renderNode.setAlpha(alpha);
24719             }
24720         }
24721     }
24722 
24723     /**
24724      * If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
24725      *
24726      * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
24727      * HW accelerated, it can't handle drawing RenderNodes.
24728      *
24729      * @hide
24730      */
drawsWithRenderNode(@onNull Canvas canvas)24731     protected final boolean drawsWithRenderNode(@NonNull Canvas canvas) {
24732         return mAttachInfo != null
24733                 && mAttachInfo.mHardwareAccelerated
24734                 && canvas.isHardwareAccelerated();
24735     }
24736 
24737     /**
24738      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
24739      *
24740      * This is where the View specializes rendering behavior based on layer type,
24741      * and hardware acceleration.
24742      */
draw(@onNull Canvas canvas, ViewGroup parent, long drawingTime)24743     boolean draw(@NonNull Canvas canvas, ViewGroup parent, long drawingTime) {
24744 
24745         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
24746 
24747         boolean drawingWithRenderNode = drawsWithRenderNode(canvas);
24748 
24749         boolean more = false;
24750         final boolean childHasIdentityMatrix = hasIdentityMatrix();
24751         final int parentFlags = parent.mGroupFlags;
24752 
24753         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
24754             parent.getChildTransformation().clear();
24755             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24756         }
24757 
24758         Transformation transformToApply = null;
24759         boolean concatMatrix = false;
24760         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
24761         final Animation a = getAnimation();
24762         if (a != null) {
24763             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
24764             concatMatrix = a.willChangeTransformationMatrix();
24765             if (concatMatrix) {
24766                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
24767             }
24768             transformToApply = parent.getChildTransformation();
24769         } else {
24770             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
24771                 // No longer animating: clear out old animation matrix
24772                 mRenderNode.setAnimationMatrix(null);
24773                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
24774             }
24775             if (!drawingWithRenderNode
24776                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
24777                 final Transformation t = parent.getChildTransformation();
24778                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
24779                 if (hasTransform) {
24780                     final int transformType = t.getTransformationType();
24781                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
24782                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
24783                 }
24784             }
24785         }
24786 
24787         concatMatrix |= !childHasIdentityMatrix;
24788 
24789         // Sets the flag as early as possible to allow draw() implementations
24790         // to call invalidate() successfully when doing animations
24791         mPrivateFlags |= PFLAG_DRAWN;
24792 
24793         if (!concatMatrix &&
24794                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
24795                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
24796                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
24797                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
24798             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
24799             return more;
24800         }
24801         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
24802 
24803         if (hardwareAcceleratedCanvas) {
24804             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
24805             // retain the flag's value temporarily in the mRecreateDisplayList flag
24806             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
24807             mPrivateFlags &= ~PFLAG_INVALIDATED;
24808         }
24809 
24810         RenderNode renderNode = null;
24811         Bitmap cache = null;
24812         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
24813         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
24814              if (layerType != LAYER_TYPE_NONE) {
24815                  // If not drawing with RenderNode, treat HW layers as SW
24816                  layerType = LAYER_TYPE_SOFTWARE;
24817                  buildDrawingCache(true);
24818             }
24819             cache = getDrawingCache(true);
24820         }
24821 
24822         if (drawingWithRenderNode) {
24823             // Delay getting the display list until animation-driven alpha values are
24824             // set up and possibly passed on to the view
24825             renderNode = updateDisplayListIfDirty();
24826             if (!renderNode.hasDisplayList()) {
24827                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
24828                 // to getDisplayList(), the display list will be marked invalid and we should not
24829                 // try to use it again.
24830                 renderNode = null;
24831                 drawingWithRenderNode = false;
24832             }
24833         }
24834 
24835         int sx = 0;
24836         int sy = 0;
24837         if (!drawingWithRenderNode) {
24838             computeScroll();
24839             sx = mScrollX;
24840             sy = mScrollY;
24841         }
24842 
24843         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
24844         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
24845 
24846         int restoreTo = -1;
24847         if (!drawingWithRenderNode || transformToApply != null) {
24848             restoreTo = canvas.save();
24849         }
24850         if (offsetForScroll) {
24851             canvas.translate(mLeft - sx, mTop - sy);
24852         } else {
24853             if (!drawingWithRenderNode) {
24854                 canvas.translate(mLeft, mTop);
24855             }
24856             if (scalingRequired) {
24857                 if (drawingWithRenderNode) {
24858                     // TODO: Might not need this if we put everything inside the DL
24859                     restoreTo = canvas.save();
24860                 }
24861                 // mAttachInfo cannot be null, otherwise scalingRequired == false
24862                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
24863                 canvas.scale(scale, scale);
24864             }
24865         }
24866 
24867         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
24868         if (transformToApply != null
24869                 || alpha < 1
24870                 || !hasIdentityMatrix()
24871                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
24872             if (transformToApply != null || !childHasIdentityMatrix) {
24873                 int transX = 0;
24874                 int transY = 0;
24875 
24876                 if (offsetForScroll) {
24877                     transX = -sx;
24878                     transY = -sy;
24879                 }
24880 
24881                 if (transformToApply != null) {
24882                     if (concatMatrix) {
24883                         if (drawingWithRenderNode) {
24884                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
24885                         } else {
24886                             // Undo the scroll translation, apply the transformation matrix,
24887                             // then redo the scroll translate to get the correct result.
24888                             canvas.translate(-transX, -transY);
24889                             canvas.concat(transformToApply.getMatrix());
24890                             canvas.translate(transX, transY);
24891                         }
24892                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24893                     }
24894 
24895                     float transformAlpha = transformToApply.getAlpha();
24896                     if (transformAlpha < 1) {
24897                         alpha *= transformAlpha;
24898                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24899                     }
24900                 }
24901 
24902                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
24903                     canvas.translate(-transX, -transY);
24904                     canvas.concat(getMatrix());
24905                     canvas.translate(transX, transY);
24906                 }
24907             }
24908 
24909             // Deal with alpha if it is or used to be <1
24910             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
24911                 if (alpha < 1) {
24912                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
24913                 } else {
24914                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
24915                 }
24916                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
24917                 if (!drawingWithDrawingCache) {
24918                     final int multipliedAlpha = (int) (255 * alpha);
24919                     if (!onSetAlpha(multipliedAlpha)) {
24920                         if (drawingWithRenderNode) {
24921                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
24922                         } else if (layerType == LAYER_TYPE_NONE) {
24923                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
24924                                     multipliedAlpha);
24925                         }
24926                     } else {
24927                         // Alpha is handled by the child directly, clobber the layer's alpha
24928                         mPrivateFlags |= PFLAG_ALPHA_SET;
24929                     }
24930                 }
24931             }
24932         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
24933             onSetAlpha(255);
24934             mPrivateFlags &= ~PFLAG_ALPHA_SET;
24935         }
24936 
24937         if (!drawingWithRenderNode) {
24938             // apply clips directly, since RenderNode won't do it for this draw
24939             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
24940                 if (offsetForScroll) {
24941                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
24942                 } else {
24943                     if (!scalingRequired || cache == null) {
24944                         canvas.clipRect(0, 0, getWidth(), getHeight());
24945                     } else {
24946                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
24947                     }
24948                 }
24949             }
24950 
24951             if (mClipBounds != null) {
24952                 // clip bounds ignore scroll
24953                 canvas.clipRect(mClipBounds);
24954             }
24955         }
24956 
24957         if (!drawingWithDrawingCache) {
24958             if (drawingWithRenderNode) {
24959                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24960                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
24961             } else {
24962                 // Fast path for layouts with no backgrounds
24963                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
24964                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24965                     dispatchDraw(canvas);
24966                 } else {
24967                     draw(canvas);
24968                 }
24969             }
24970         } else if (cache != null) {
24971             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
24972             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
24973                 // no layer paint, use temporary paint to draw bitmap
24974                 Paint cachePaint = parent.mCachePaint;
24975                 if (cachePaint == null) {
24976                     cachePaint = new Paint();
24977                     cachePaint.setDither(false);
24978                     parent.mCachePaint = cachePaint;
24979                 }
24980                 cachePaint.setAlpha((int) (alpha * 255));
24981                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
24982             } else {
24983                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
24984                 int layerPaintAlpha = mLayerPaint.getAlpha();
24985                 if (alpha < 1) {
24986                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
24987                 }
24988                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
24989                 if (alpha < 1) {
24990                     mLayerPaint.setAlpha(layerPaintAlpha);
24991                 }
24992             }
24993         }
24994 
24995         if (restoreTo >= 0) {
24996             canvas.restoreToCount(restoreTo);
24997         }
24998 
24999         if (a != null && !more) {
25000             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
25001                 onSetAlpha(255);
25002             }
25003             parent.finishAnimatingView(this, a);
25004         }
25005 
25006         if (more && hardwareAcceleratedCanvas) {
25007             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
25008                 // alpha animations should cause the child to recreate its display list
25009                 invalidate(true);
25010             }
25011         }
25012 
25013         mRecreateDisplayList = false;
25014 
25015         return more;
25016     }
25017 
getDebugPaint()25018     static Paint getDebugPaint() {
25019         if (sDebugPaint == null) {
25020             sDebugPaint = new Paint();
25021             sDebugPaint.setAntiAlias(false);
25022         }
25023         return sDebugPaint;
25024     }
25025 
dipsToPixels(int dips)25026     final int dipsToPixels(int dips) {
25027         float scale = getContext().getResources().getDisplayMetrics().density;
25028         return (int) (dips * scale + 0.5f);
25029     }
25030 
debugDrawFocus(@onNull Canvas canvas)25031     private void debugDrawFocus(@NonNull Canvas canvas) {
25032         if (isFocused()) {
25033             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
25034             final int l = mScrollX;
25035             final int r = l + mRight - mLeft;
25036             final int t = mScrollY;
25037             final int b = t + mBottom - mTop;
25038 
25039             final Paint paint = getDebugPaint();
25040             paint.setColor(DEBUG_CORNERS_COLOR);
25041 
25042             // Draw squares in corners.
25043             paint.setStyle(Paint.Style.FILL);
25044             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
25045             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
25046             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
25047             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
25048 
25049             // Draw big X across the view.
25050             paint.setStyle(Paint.Style.STROKE);
25051             canvas.drawLine(l, t, r, b, paint);
25052             canvas.drawLine(l, b, r, t, paint);
25053         }
25054     }
25055 
25056     /**
25057      * Manually render this view (and all of its children) to the given Canvas.
25058      * The view must have already done a full layout before this function is
25059      * called.  When implementing a view, implement
25060      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
25061      * If you do need to override this method, call the superclass version.
25062      *
25063      * @param canvas The Canvas to which the View is rendered.
25064      */
25065     @CallSuper
draw(@onNull Canvas canvas)25066     public void draw(@NonNull Canvas canvas) {
25067         final int privateFlags = mPrivateFlags;
25068         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
25069 
25070         /*
25071          * Draw traversal performs several drawing steps which must be executed
25072          * in the appropriate order:
25073          *
25074          *      1. Draw the background
25075          *      2. If necessary, save the canvas' layers to prepare for fading
25076          *      3. Draw view's content
25077          *      4. Draw children
25078          *      5. If necessary, draw the fading edges and restore layers
25079          *      6. Draw decorations (scrollbars for instance)
25080          *      7. If necessary, draw the default focus highlight
25081          */
25082 
25083         // Step 1, draw the background, if needed
25084         int saveCount;
25085 
25086         drawBackground(canvas);
25087 
25088         // skip step 2 & 5 if possible (common case)
25089         final int viewFlags = mViewFlags;
25090         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
25091         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
25092         if (!verticalEdges && !horizontalEdges) {
25093             // Step 3, draw the content
25094             onDraw(canvas);
25095 
25096             // Step 4, draw the children
25097             dispatchDraw(canvas);
25098 
25099             drawAutofilledHighlight(canvas);
25100 
25101             // Overlay is part of the content and draws beneath Foreground
25102             if (mOverlay != null && !mOverlay.isEmpty()) {
25103                 mOverlay.getOverlayView().dispatchDraw(canvas);
25104             }
25105 
25106             // Step 6, draw decorations (foreground, scrollbars)
25107             onDrawForeground(canvas);
25108 
25109             // Step 7, draw the default focus highlight
25110             drawDefaultFocusHighlight(canvas);
25111 
25112             if (isShowingLayoutBounds()) {
25113                 debugDrawFocus(canvas);
25114             }
25115 
25116             // we're done...
25117             return;
25118         }
25119 
25120         /*
25121          * Here we do the full fledged routine...
25122          * (this is an uncommon case where speed matters less,
25123          * this is why we repeat some of the tests that have been
25124          * done above)
25125          */
25126 
25127         boolean drawTop = false;
25128         boolean drawBottom = false;
25129         boolean drawLeft = false;
25130         boolean drawRight = false;
25131 
25132         float topFadeStrength = 0.0f;
25133         float bottomFadeStrength = 0.0f;
25134         float leftFadeStrength = 0.0f;
25135         float rightFadeStrength = 0.0f;
25136 
25137         // Step 2, save the canvas' layers
25138         int paddingLeft = mPaddingLeft;
25139 
25140         final boolean offsetRequired = isPaddingOffsetRequired();
25141         if (offsetRequired) {
25142             paddingLeft += getLeftPaddingOffset();
25143         }
25144 
25145         int left = mScrollX + paddingLeft;
25146         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
25147         int top = mScrollY + getFadeTop(offsetRequired);
25148         int bottom = top + getFadeHeight(offsetRequired);
25149 
25150         if (offsetRequired) {
25151             right += getRightPaddingOffset();
25152             bottom += getBottomPaddingOffset();
25153         }
25154 
25155         final ScrollabilityCache scrollabilityCache = mScrollCache;
25156         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
25157         int length = (int) fadeHeight;
25158 
25159         // clip the fade length if top and bottom fades overlap
25160         // overlapping fades produce odd-looking artifacts
25161         if (verticalEdges && (top + length > bottom - length)) {
25162             length = (bottom - top) / 2;
25163         }
25164 
25165         // also clip horizontal fades if necessary
25166         if (horizontalEdges && (left + length > right - length)) {
25167             length = (right - left) / 2;
25168         }
25169 
25170         if (verticalEdges) {
25171             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
25172             drawTop = topFadeStrength * fadeHeight > 1.0f;
25173             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
25174             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
25175         }
25176 
25177         if (horizontalEdges) {
25178             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
25179             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
25180             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
25181             drawRight = rightFadeStrength * fadeHeight > 1.0f;
25182         }
25183 
25184         saveCount = canvas.getSaveCount();
25185         int topSaveCount = -1;
25186         int bottomSaveCount = -1;
25187         int leftSaveCount = -1;
25188         int rightSaveCount = -1;
25189 
25190         int solidColor = getSolidColor();
25191         if (solidColor == 0) {
25192             if (drawTop) {
25193                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
25194             }
25195 
25196             if (drawBottom) {
25197                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
25198             }
25199 
25200             if (drawLeft) {
25201                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
25202             }
25203 
25204             if (drawRight) {
25205                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
25206             }
25207         } else {
25208             scrollabilityCache.setFadeColor(solidColor);
25209         }
25210 
25211         // Step 3, draw the content
25212         onDraw(canvas);
25213 
25214         // Step 4, draw the children
25215         dispatchDraw(canvas);
25216 
25217         // Step 5, draw the fade effect and restore layers
25218         final Paint p = scrollabilityCache.paint;
25219         final Matrix matrix = scrollabilityCache.matrix;
25220         final Shader fade = scrollabilityCache.shader;
25221 
25222         // must be restored in the reverse order that they were saved
25223         if (drawRight) {
25224             matrix.setScale(1, fadeHeight * rightFadeStrength);
25225             matrix.postRotate(90);
25226             matrix.postTranslate(right, top);
25227             fade.setLocalMatrix(matrix);
25228             p.setShader(fade);
25229             if (solidColor == 0) {
25230                 canvas.restoreUnclippedLayer(rightSaveCount, p);
25231 
25232             } else {
25233                 canvas.drawRect(right - length, top, right, bottom, p);
25234             }
25235         }
25236 
25237         if (drawLeft) {
25238             matrix.setScale(1, fadeHeight * leftFadeStrength);
25239             matrix.postRotate(-90);
25240             matrix.postTranslate(left, top);
25241             fade.setLocalMatrix(matrix);
25242             p.setShader(fade);
25243             if (solidColor == 0) {
25244                 canvas.restoreUnclippedLayer(leftSaveCount, p);
25245             } else {
25246                 canvas.drawRect(left, top, left + length, bottom, p);
25247             }
25248         }
25249 
25250         if (drawBottom) {
25251             matrix.setScale(1, fadeHeight * bottomFadeStrength);
25252             matrix.postRotate(180);
25253             matrix.postTranslate(left, bottom);
25254             fade.setLocalMatrix(matrix);
25255             p.setShader(fade);
25256             if (solidColor == 0) {
25257                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
25258             } else {
25259                 canvas.drawRect(left, bottom - length, right, bottom, p);
25260             }
25261         }
25262 
25263         if (drawTop) {
25264             matrix.setScale(1, fadeHeight * topFadeStrength);
25265             matrix.postTranslate(left, top);
25266             fade.setLocalMatrix(matrix);
25267             p.setShader(fade);
25268             if (solidColor == 0) {
25269                 canvas.restoreUnclippedLayer(topSaveCount, p);
25270             } else {
25271                 canvas.drawRect(left, top, right, top + length, p);
25272             }
25273         }
25274 
25275         canvas.restoreToCount(saveCount);
25276 
25277         drawAutofilledHighlight(canvas);
25278 
25279         // Overlay is part of the content and draws beneath Foreground
25280         if (mOverlay != null && !mOverlay.isEmpty()) {
25281             mOverlay.getOverlayView().dispatchDraw(canvas);
25282         }
25283 
25284         // Step 6, draw decorations (foreground, scrollbars)
25285         onDrawForeground(canvas);
25286 
25287         // Step 7, draw the default focus highlight
25288         drawDefaultFocusHighlight(canvas);
25289 
25290         if (isShowingLayoutBounds()) {
25291             debugDrawFocus(canvas);
25292         }
25293     }
25294 
25295     /**
25296      * Draws the background onto the specified canvas.
25297      *
25298      * @param canvas Canvas on which to draw the background
25299      */
25300     @UnsupportedAppUsage
drawBackground(@onNull Canvas canvas)25301     private void drawBackground(@NonNull Canvas canvas) {
25302         final Drawable background = mBackground;
25303         if (background == null) {
25304             return;
25305         }
25306 
25307         setBackgroundBounds();
25308 
25309         // Attempt to use a display list if requested.
25310         if (canvas.isHardwareAccelerated() && mAttachInfo != null
25311                 && mAttachInfo.mThreadedRenderer != null) {
25312             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
25313 
25314             final RenderNode renderNode = mBackgroundRenderNode;
25315             if (renderNode != null && renderNode.hasDisplayList()) {
25316                 setBackgroundRenderNodeProperties(renderNode);
25317                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
25318                 return;
25319             }
25320         }
25321 
25322         final int scrollX = mScrollX;
25323         final int scrollY = mScrollY;
25324         if ((scrollX | scrollY) == 0) {
25325             background.draw(canvas);
25326         } else {
25327             canvas.translate(scrollX, scrollY);
25328             background.draw(canvas);
25329             canvas.translate(-scrollX, -scrollY);
25330         }
25331     }
25332 
25333     /**
25334      * Sets the correct background bounds and rebuilds the outline, if needed.
25335      * <p/>
25336      * This is called by LayoutLib.
25337      */
setBackgroundBounds()25338     void setBackgroundBounds() {
25339         if (mBackgroundSizeChanged && mBackground != null) {
25340             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
25341             mBackgroundSizeChanged = false;
25342             rebuildOutline();
25343         }
25344     }
25345 
setBackgroundRenderNodeProperties(RenderNode renderNode)25346     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
25347         renderNode.setTranslationX(mScrollX);
25348         renderNode.setTranslationY(mScrollY);
25349     }
25350 
25351     /**
25352      * Creates a new display list or updates the existing display list for the
25353      * specified Drawable.
25354      *
25355      * @param drawable Drawable for which to create a display list
25356      * @param renderNode Existing RenderNode, or {@code null}
25357      * @return A valid display list for the specified drawable
25358      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)25359     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
25360         if (renderNode == null) {
25361             renderNode = RenderNode.create(drawable.getClass().getName(),
25362                     new ViewAnimationHostBridge(this));
25363             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
25364         }
25365 
25366         final Rect bounds = drawable.getBounds();
25367         final int width = bounds.width();
25368         final int height = bounds.height();
25369 
25370         // Hacky hack: Reset any stretch effects as those are applied during the draw pass
25371         // instead of being "stateful" like other RenderNode properties
25372         renderNode.clearStretch();
25373 
25374         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
25375 
25376         // Reverse left/top translation done by drawable canvas, which will
25377         // instead be applied by rendernode's LTRB bounds below. This way, the
25378         // drawable's bounds match with its rendernode bounds and its content
25379         // will lie within those bounds in the rendernode tree.
25380         canvas.translate(-bounds.left, -bounds.top);
25381 
25382         try {
25383             drawable.draw(canvas);
25384         } finally {
25385             renderNode.endRecording();
25386         }
25387 
25388         // Set up drawable properties that are view-independent.
25389         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
25390         renderNode.setProjectBackwards(drawable.isProjected());
25391         renderNode.setProjectionReceiver(true);
25392         renderNode.setClipToBounds(false);
25393         return renderNode;
25394     }
25395 
25396     /**
25397      * Returns the overlay for this view, creating it if it does not yet exist.
25398      * Adding drawables to the overlay will cause them to be displayed whenever
25399      * the view itself is redrawn. Objects in the overlay should be actively
25400      * managed: remove them when they should not be displayed anymore. The
25401      * overlay will always have the same size as its host view.
25402      *
25403      * <p>Note: Overlays do not currently work correctly with {@link
25404      * SurfaceView} or {@link TextureView}; contents in overlays for these
25405      * types of views may not display correctly.</p>
25406      *
25407      * @return The ViewOverlay object for this view.
25408      * @see ViewOverlay
25409      */
getOverlay()25410     public ViewOverlay getOverlay() {
25411         if (mOverlay == null) {
25412             mOverlay = new ViewOverlay(mContext, this);
25413         }
25414         return mOverlay;
25415     }
25416 
25417     /**
25418      * Override this if your view is known to always be drawn on top of a solid color background,
25419      * and needs to draw fading edges. Returning a non-zero color enables the view system to
25420      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
25421      * should be set to 0xFF.
25422      *
25423      * @see #setVerticalFadingEdgeEnabled(boolean)
25424      * @see #setHorizontalFadingEdgeEnabled(boolean)
25425      *
25426      * @return The known solid color background for this view, or 0 if the color may vary
25427      */
25428     @ViewDebug.ExportedProperty(category = "drawing")
25429     @InspectableProperty
25430     @ColorInt
getSolidColor()25431     public int getSolidColor() {
25432         return 0;
25433     }
25434 
25435     /**
25436      * Build a human readable string representation of the specified view flags.
25437      *
25438      * @param flags the view flags to convert to a string
25439      * @return a String representing the supplied flags
25440      */
printFlags(int flags)25441     private static String printFlags(int flags) {
25442         String output = "";
25443         int numFlags = 0;
25444         if ((flags & FOCUSABLE) == FOCUSABLE) {
25445             output += "TAKES_FOCUS";
25446             numFlags++;
25447         }
25448 
25449         switch (flags & VISIBILITY_MASK) {
25450         case INVISIBLE:
25451             if (numFlags > 0) {
25452                 output += " ";
25453             }
25454             output += "INVISIBLE";
25455             // USELESS HERE numFlags++;
25456             break;
25457         case GONE:
25458             if (numFlags > 0) {
25459                 output += " ";
25460             }
25461             output += "GONE";
25462             // USELESS HERE numFlags++;
25463             break;
25464         default:
25465             break;
25466         }
25467         return output;
25468     }
25469 
25470     /**
25471      * Build a human readable string representation of the specified private
25472      * view flags.
25473      *
25474      * @param privateFlags the private view flags to convert to a string
25475      * @return a String representing the supplied flags
25476      */
printPrivateFlags(int privateFlags)25477     private static String printPrivateFlags(int privateFlags) {
25478         String output = "";
25479         int numFlags = 0;
25480 
25481         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
25482             output += "WANTS_FOCUS";
25483             numFlags++;
25484         }
25485 
25486         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
25487             if (numFlags > 0) {
25488                 output += " ";
25489             }
25490             output += "FOCUSED";
25491             numFlags++;
25492         }
25493 
25494         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
25495             if (numFlags > 0) {
25496                 output += " ";
25497             }
25498             output += "SELECTED";
25499             numFlags++;
25500         }
25501 
25502         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
25503             if (numFlags > 0) {
25504                 output += " ";
25505             }
25506             output += "IS_ROOT_NAMESPACE";
25507             numFlags++;
25508         }
25509 
25510         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
25511             if (numFlags > 0) {
25512                 output += " ";
25513             }
25514             output += "HAS_BOUNDS";
25515             numFlags++;
25516         }
25517 
25518         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
25519             if (numFlags > 0) {
25520                 output += " ";
25521             }
25522             output += "DRAWN";
25523             // USELESS HERE numFlags++;
25524         }
25525         return output;
25526     }
25527 
25528     /**
25529      * <p>Indicates whether or not this view's layout will be requested during
25530      * the next hierarchy layout pass.</p>
25531      *
25532      * @return true if the layout will be forced during next layout pass
25533      */
isLayoutRequested()25534     public boolean isLayoutRequested() {
25535         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
25536     }
25537 
25538     /**
25539      * Return true if o is a ViewGroup that is laying out using optical bounds.
25540      * @hide
25541      */
isLayoutModeOptical(Object o)25542     public static boolean isLayoutModeOptical(Object o) {
25543         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
25544     }
25545 
25546     /**
25547      * Enable measure/layout debugging on traces.
25548      *
25549      * @see Trace
25550      * @hide
25551      */
setTraceLayoutSteps(boolean traceLayoutSteps)25552     public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
25553         sTraceLayoutSteps = traceLayoutSteps;
25554     }
25555 
25556     /**
25557      * Enable request layout tracing classes with {@code s} simple name.
25558      * <p>
25559      * When set, a {@link Trace} instant event and a log with the stacktrace is emitted every
25560      * time a requestLayout of a class matching {@code s} name happens.
25561      * This applies only to views attached from this point onwards.
25562      *
25563      * @see Trace#instant(long, String)
25564      * @hide
25565      */
setTracedRequestLayoutClassClass(String s)25566     public static void setTracedRequestLayoutClassClass(String s) {
25567         sTraceRequestLayoutClass = s;
25568     }
25569 
setOpticalFrame(int left, int top, int right, int bottom)25570     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
25571         Insets parentInsets = mParent instanceof View ?
25572                 ((View) mParent).getOpticalInsets() : Insets.NONE;
25573         Insets childInsets = getOpticalInsets();
25574         return setFrame(
25575                 left   + parentInsets.left - childInsets.left,
25576                 top    + parentInsets.top  - childInsets.top,
25577                 right  + parentInsets.left + childInsets.right,
25578                 bottom + parentInsets.top  + childInsets.bottom);
25579     }
25580 
25581     /**
25582      * Assign a size and position to a view and all of its
25583      * descendants
25584      *
25585      * <p>This is the second phase of the layout mechanism.
25586      * (The first is measuring). In this phase, each parent calls
25587      * layout on all of its children to position them.
25588      * This is typically done using the child measurements
25589      * that were stored in the measure pass().</p>
25590      *
25591      * <p>Derived classes should not override this method.
25592      * Derived classes with children should override
25593      * onLayout. In that method, they should
25594      * call layout on each of their children.</p>
25595      *
25596      * @param l Left position, relative to parent
25597      * @param t Top position, relative to parent
25598      * @param r Right position, relative to parent
25599      * @param b Bottom position, relative to parent
25600      */
25601     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)25602     public void layout(int l, int t, int r, int b) {
25603         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
25604             if (isTraversalTracingEnabled()) {
25605                 Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
25606             }
25607             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
25608             if (isTraversalTracingEnabled()) {
25609                 Trace.endSection();
25610             }
25611             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25612         }
25613 
25614         int oldL = mLeft;
25615         int oldT = mTop;
25616         int oldB = mBottom;
25617         int oldR = mRight;
25618 
25619         boolean changed = isLayoutModeOptical(mParent) ?
25620                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
25621 
25622         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
25623             if (isTraversalTracingEnabled()) {
25624                 Trace.beginSection(mTracingStrings.onLayout);
25625             }
25626             onLayout(changed, l, t, r, b);
25627             if (isTraversalTracingEnabled()) {
25628                 Trace.endSection();
25629             }
25630 
25631             if (shouldDrawRoundScrollbar()) {
25632                 if(mRoundScrollbarRenderer == null) {
25633                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
25634                 }
25635             } else {
25636                 mRoundScrollbarRenderer = null;
25637             }
25638 
25639             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
25640 
25641             ListenerInfo li = mListenerInfo;
25642             if (li != null && li.mOnLayoutChangeListeners != null) {
25643                 ArrayList<OnLayoutChangeListener> listenersCopy =
25644                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
25645                 int numListeners = listenersCopy.size();
25646                 for (int i = 0; i < numListeners; ++i) {
25647                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
25648                 }
25649             }
25650         }
25651 
25652         final boolean wasLayoutValid = isLayoutValid();
25653 
25654         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
25655         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
25656 
25657         if (!wasLayoutValid && isFocused()) {
25658             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
25659             if (canTakeFocus()) {
25660                 // We have a robust focus, so parents should no longer be wanting focus.
25661                 clearParentsWantFocus();
25662             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
25663                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
25664                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
25665                 // and thus the safest action is to clear focus here.
25666                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
25667                 clearParentsWantFocus();
25668             } else if (!hasParentWantsFocus()) {
25669                 // original requestFocus was likely on this view directly, so just clear focus
25670                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
25671             }
25672             // otherwise, we let parents handle re-assigning focus during their layout passes.
25673         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
25674             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
25675             View focused = findFocus();
25676             if (focused != null) {
25677                 // Try to restore focus as close as possible to our starting focus.
25678                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
25679                     // Give up and clear focus once we've reached the top-most parent which wants
25680                     // focus.
25681                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
25682                 }
25683             }
25684         }
25685 
25686         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
25687             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
25688             notifyEnterOrExitForAutoFillIfNeeded(true);
25689         }
25690 
25691         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
25692     }
25693 
hasParentWantsFocus()25694     private boolean hasParentWantsFocus() {
25695         ViewParent parent = mParent;
25696         while (parent instanceof ViewGroup) {
25697             ViewGroup pv = (ViewGroup) parent;
25698             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
25699                 return true;
25700             }
25701             parent = pv.mParent;
25702         }
25703         return false;
25704     }
25705 
25706     /**
25707      * Called from layout when this view should
25708      * assign a size and position to each of its children.
25709      *
25710      * Derived classes with children should override
25711      * this method and call layout on each of
25712      * their children.
25713      * @param changed This is a new size or position for this view
25714      * @param left Left position, relative to parent
25715      * @param top Top position, relative to parent
25716      * @param right Right position, relative to parent
25717      * @param bottom Bottom position, relative to parent
25718      */
onLayout(boolean changed, int left, int top, int right, int bottom)25719     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
25720     }
25721 
25722     /**
25723      * Assign a size and position to this view.
25724      *
25725      * This is called from layout.
25726      *
25727      * @param left Left position, relative to parent
25728      * @param top Top position, relative to parent
25729      * @param right Right position, relative to parent
25730      * @param bottom Bottom position, relative to parent
25731      * @return true if the new size and position are different than the
25732      *         previous ones
25733      * {@hide}
25734      */
25735     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)25736     protected boolean setFrame(int left, int top, int right, int bottom) {
25737         boolean changed = false;
25738 
25739         if (DBG) {
25740             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
25741                     + right + "," + bottom + ")");
25742         }
25743 
25744         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
25745             changed = true;
25746 
25747             // Remember our drawn bit
25748             int drawn = mPrivateFlags & PFLAG_DRAWN;
25749 
25750             int oldWidth = mRight - mLeft;
25751             int oldHeight = mBottom - mTop;
25752             int newWidth = right - left;
25753             int newHeight = bottom - top;
25754             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
25755 
25756             // Invalidate our old position
25757             invalidate(sizeChanged);
25758 
25759             mLeft = left;
25760             mTop = top;
25761             mRight = right;
25762             mBottom = bottom;
25763             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
25764 
25765             mPrivateFlags |= PFLAG_HAS_BOUNDS;
25766 
25767 
25768             if (sizeChanged) {
25769                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
25770             }
25771 
25772             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
25773                 // If we are visible, force the DRAWN bit to on so that
25774                 // this invalidate will go through (at least to our parent).
25775                 // This is because someone may have invalidated this view
25776                 // before this call to setFrame came in, thereby clearing
25777                 // the DRAWN bit.
25778                 mPrivateFlags |= PFLAG_DRAWN;
25779                 invalidate(sizeChanged);
25780                 // parent display list may need to be recreated based on a change in the bounds
25781                 // of any child
25782                 invalidateParentCaches();
25783             }
25784 
25785             // Reset drawn bit to original value (invalidate turns it off)
25786             mPrivateFlags |= drawn;
25787 
25788             mBackgroundSizeChanged = true;
25789             mDefaultFocusHighlightSizeChanged = true;
25790             if (mForegroundInfo != null) {
25791                 mForegroundInfo.mBoundsChanged = true;
25792             }
25793 
25794             notifySubtreeAccessibilityStateChangedIfNeeded();
25795         }
25796         return changed;
25797     }
25798 
25799     /**
25800      * Assign a size and position to this view.
25801      *
25802      * This method is meant to be used in animations only as it applies this position and size
25803      * for the view only temporary and it can be changed back at any time by the layout.
25804      *
25805      * @param left Left position, relative to parent
25806      * @param top Top position, relative to parent
25807      * @param right Right position, relative to parent
25808      * @param bottom Bottom position, relative to parent
25809      *
25810      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
25811      */
setLeftTopRightBottom(int left, int top, int right, int bottom)25812     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
25813         setFrame(left, top, right, bottom);
25814     }
25815 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)25816     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
25817         if (mAttachInfo != null && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
25818             boolean isSmall;
25819             if (sToolkitFrameRateSmallUsesPercentReadOnlyFlagValue) {
25820                 int size = newWidth * newHeight;
25821                 float percent = size / mAttachInfo.mDisplayPixelCount;
25822                 isSmall = percent <= FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD;
25823             } else {
25824                 float density = mAttachInfo.mDensity;
25825                 int narrowSize = (int) (density * FRAME_RATE_NARROW_SIZE_DP);
25826                 int smallSize = (int) (density * FRAME_RATE_SQUARE_SMALL_SIZE_DP);
25827                 isSmall = newWidth <= narrowSize || newHeight <= narrowSize
25828                         || (newWidth <= smallSize && newHeight <= smallSize);
25829             }
25830             if (isSmall) {
25831                 int category = sToolkitFrameRateBySizeReadOnlyFlagValue
25832                         ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
25833                 mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_SMALL;
25834             } else {
25835                 int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
25836                         ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
25837                 mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_LARGE;
25838             }
25839             mPrivateFlags4 |= PFLAG4_HAS_MOVED;
25840         }
25841 
25842         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
25843         if (mOverlay != null) {
25844             mOverlay.getOverlayView().setRight(newWidth);
25845             mOverlay.getOverlayView().setBottom(newHeight);
25846         }
25847         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
25848         // backtracking" of requestFocus during layout, so don't touch focus here.
25849         if (!sCanFocusZeroSized && isLayoutValid()
25850                 // Don't touch focus if animating
25851                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
25852             if (newWidth <= 0 || newHeight <= 0) {
25853                 if (hasFocus()) {
25854                     clearFocus();
25855                     if (mParent instanceof ViewGroup) {
25856                         ((ViewGroup) mParent).clearFocusedInCluster();
25857                     }
25858                 }
25859                 clearAccessibilityFocus();
25860             } else if (oldWidth <= 0 || oldHeight <= 0) {
25861                 if (mParent != null && canTakeFocus()) {
25862                     mParent.focusableViewAvailable(this);
25863                 }
25864             }
25865         }
25866         rebuildOutline();
25867         if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
25868             setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
25869         }
25870     }
25871 
25872     /**
25873      * Finalize inflating a view from XML.  This is called as the last phase
25874      * of inflation, after all child views have been added.
25875      *
25876      * <p>Even if the subclass overrides onFinishInflate, they should always be
25877      * sure to call the super method, so that we get called.
25878      */
25879     @CallSuper
onFinishInflate()25880     protected void onFinishInflate() {
25881     }
25882 
25883     /**
25884      * Returns the resources associated with this view.
25885      *
25886      * @return Resources object.
25887      */
getResources()25888     public Resources getResources() {
25889         return mResources;
25890     }
25891 
25892     /**
25893      * Invalidates the specified Drawable.
25894      *
25895      * @param drawable the drawable to invalidate
25896      */
25897     @Override
invalidateDrawable(@onNull Drawable drawable)25898     public void invalidateDrawable(@NonNull Drawable drawable) {
25899         if (verifyDrawable(drawable)) {
25900             final Rect dirty = drawable.getDirtyBounds();
25901             final int scrollX = mScrollX;
25902             final int scrollY = mScrollY;
25903 
25904             invalidate(dirty.left + scrollX, dirty.top + scrollY,
25905                     dirty.right + scrollX, dirty.bottom + scrollY);
25906             rebuildOutline();
25907         }
25908     }
25909 
25910     /**
25911      * Schedules an action on a drawable to occur at a specified time.
25912      *
25913      * @param who the recipient of the action
25914      * @param what the action to run on the drawable
25915      * @param when the time at which the action must occur. Uses the
25916      *        {@link SystemClock#uptimeMillis} timebase.
25917      */
25918     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)25919     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
25920         if (verifyDrawable(who) && what != null) {
25921             final long delay = when - SystemClock.uptimeMillis();
25922             if (mAttachInfo != null) {
25923                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
25924                         Choreographer.CALLBACK_ANIMATION, what, who,
25925                         Choreographer.subtractFrameDelay(delay));
25926             } else {
25927                 // Postpone the runnable until we know
25928                 // on which thread it needs to run.
25929                 getRunQueue().postDelayed(what, delay);
25930             }
25931         }
25932     }
25933 
25934     /**
25935      * Cancels a scheduled action on a drawable.
25936      *
25937      * @param who the recipient of the action
25938      * @param what the action to cancel
25939      */
25940     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)25941     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
25942         if (verifyDrawable(who) && what != null) {
25943             if (mAttachInfo != null) {
25944                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
25945                         Choreographer.CALLBACK_ANIMATION, what, who);
25946             }
25947             getRunQueue().removeCallbacks(what);
25948         }
25949     }
25950 
25951     /**
25952      * Unschedule any events associated with the given Drawable.  This can be
25953      * used when selecting a new Drawable into a view, so that the previous
25954      * one is completely unscheduled.
25955      *
25956      * @param who The Drawable to unschedule.
25957      *
25958      * @see #drawableStateChanged
25959      */
unscheduleDrawable(Drawable who)25960     public void unscheduleDrawable(Drawable who) {
25961         if (mAttachInfo != null && who != null) {
25962             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
25963                     Choreographer.CALLBACK_ANIMATION, null, who);
25964         }
25965     }
25966 
25967     /**
25968      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
25969      * that the View directionality can and will be resolved before its Drawables.
25970      *
25971      * Will call {@link View#onResolveDrawables} when resolution is done.
25972      *
25973      * @hide
25974      */
resolveDrawables()25975     protected void resolveDrawables() {
25976         // Drawables resolution may need to happen before resolving the layout direction (which is
25977         // done only during the measure() call).
25978         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
25979         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
25980         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
25981         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
25982         // direction to be resolved as its resolved value will be the same as its raw value.
25983         if (!isLayoutDirectionResolved() &&
25984                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
25985             return;
25986         }
25987 
25988         final int layoutDirection = isLayoutDirectionResolved() ?
25989                 getLayoutDirection() : getRawLayoutDirection();
25990 
25991         if (mBackground != null) {
25992             mBackground.setLayoutDirection(layoutDirection);
25993         }
25994         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
25995             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
25996         }
25997         if (mDefaultFocusHighlight != null) {
25998             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
25999         }
26000         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
26001         onResolveDrawables(layoutDirection);
26002     }
26003 
areDrawablesResolved()26004     boolean areDrawablesResolved() {
26005         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
26006     }
26007 
26008     /**
26009      * Called when layout direction has been resolved.
26010      *
26011      * The default implementation does nothing.
26012      *
26013      * @param layoutDirection The resolved layout direction.
26014      *
26015      * @see #LAYOUT_DIRECTION_LTR
26016      * @see #LAYOUT_DIRECTION_RTL
26017      *
26018      * @hide
26019      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)26020     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
26021     }
26022 
26023     /**
26024      * @hide
26025      */
26026     @TestApi
resetResolvedDrawables()26027     protected void resetResolvedDrawables() {
26028         resetResolvedDrawablesInternal();
26029     }
26030 
resetResolvedDrawablesInternal()26031     void resetResolvedDrawablesInternal() {
26032         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
26033     }
26034 
26035     /**
26036      * If your view subclass is displaying its own Drawable objects, it should
26037      * override this function and return true for any Drawable it is
26038      * displaying.  This allows animations for those drawables to be
26039      * scheduled.
26040      *
26041      * <p>Be sure to call through to the super class when overriding this
26042      * function.
26043      *
26044      * @param who The Drawable to verify.  Return true if it is one you are
26045      *            displaying, else return the result of calling through to the
26046      *            super class.
26047      *
26048      * @return boolean If true then the Drawable is being displayed in the
26049      *         view; else false and it is not allowed to animate.
26050      *
26051      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
26052      * @see #drawableStateChanged()
26053      */
26054     @CallSuper
verifyDrawable(@onNull Drawable who)26055     protected boolean verifyDrawable(@NonNull Drawable who) {
26056         // Avoid verifying the scroll bar drawable so that we don't end up in
26057         // an invalidation loop. This effectively prevents the scroll bar
26058         // drawable from triggering invalidations and scheduling runnables.
26059         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
26060                 || (mDefaultFocusHighlight == who);
26061     }
26062 
26063     /**
26064      * This function is called whenever the state of the view changes in such
26065      * a way that it impacts the state of drawables being shown.
26066      * <p>
26067      * If the View has a StateListAnimator, it will also be called to run necessary state
26068      * change animations.
26069      * <p>
26070      * Be sure to call through to the superclass when overriding this function.
26071      *
26072      * @see Drawable#setState(int[])
26073      */
26074     @CallSuper
drawableStateChanged()26075     protected void drawableStateChanged() {
26076         final int[] state = getDrawableState();
26077         boolean changed = false;
26078 
26079         final Drawable bg = mBackground;
26080         if (bg != null && bg.isStateful()) {
26081             changed |= bg.setState(state);
26082         }
26083 
26084         final Drawable hl = mDefaultFocusHighlight;
26085         if (hl != null && hl.isStateful()) {
26086             changed |= hl.setState(state);
26087         }
26088 
26089         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
26090         if (fg != null && fg.isStateful()) {
26091             changed |= fg.setState(state);
26092         }
26093 
26094         if (mScrollCache != null) {
26095             final Drawable scrollBar = mScrollCache.scrollBar;
26096             if (scrollBar != null && scrollBar.isStateful()) {
26097                 changed |= scrollBar.setState(state)
26098                         && mScrollCache.state != ScrollabilityCache.OFF;
26099             }
26100         }
26101 
26102         if (mStateListAnimator != null) {
26103             mStateListAnimator.setState(state);
26104         }
26105 
26106         if (!isAggregatedVisible()) {
26107             // If we're not visible, skip any animated changes
26108             jumpDrawablesToCurrentState();
26109         }
26110 
26111         if (changed) {
26112             invalidate();
26113         }
26114     }
26115 
26116     /**
26117      * This function is called whenever the view hotspot changes and needs to
26118      * be propagated to drawables or child views managed by the view.
26119      * <p>
26120      * Dispatching to child views is handled by
26121      * {@link #dispatchDrawableHotspotChanged(float, float)}.
26122      * <p>
26123      * Be sure to call through to the superclass when overriding this function.
26124      *
26125      * @param x hotspot x coordinate
26126      * @param y hotspot y coordinate
26127      */
26128     @CallSuper
drawableHotspotChanged(float x, float y)26129     public void drawableHotspotChanged(float x, float y) {
26130         if (mBackground != null) {
26131             mBackground.setHotspot(x, y);
26132         }
26133         if (mDefaultFocusHighlight != null) {
26134             mDefaultFocusHighlight.setHotspot(x, y);
26135         }
26136         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
26137             mForegroundInfo.mDrawable.setHotspot(x, y);
26138         }
26139 
26140         dispatchDrawableHotspotChanged(x, y);
26141     }
26142 
26143     /**
26144      * Dispatches drawableHotspotChanged to all of this View's children.
26145      *
26146      * @param x hotspot x coordinate
26147      * @param y hotspot y coordinate
26148      * @see #drawableHotspotChanged(float, float)
26149      */
dispatchDrawableHotspotChanged(float x, float y)26150     public void dispatchDrawableHotspotChanged(float x, float y) {
26151     }
26152 
26153     /**
26154      * Call this to force a view to update its drawable state. This will cause
26155      * drawableStateChanged to be called on this view. Views that are interested
26156      * in the new state should call getDrawableState.
26157      *
26158      * @see #drawableStateChanged
26159      * @see #getDrawableState
26160      */
refreshDrawableState()26161     public void refreshDrawableState() {
26162         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
26163         drawableStateChanged();
26164 
26165         ViewParent parent = mParent;
26166         if (parent != null) {
26167             parent.childDrawableStateChanged(this);
26168         }
26169     }
26170 
26171     /**
26172      * Create a default focus highlight if it doesn't exist.
26173      * @return a default focus highlight.
26174      */
getDefaultFocusHighlightDrawable()26175     private Drawable getDefaultFocusHighlightDrawable() {
26176         if (mDefaultFocusHighlightCache == null) {
26177             if (mContext != null) {
26178                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
26179                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
26180                 mDefaultFocusHighlightCache = ta.getDrawable(0);
26181                 ta.recycle();
26182             }
26183         }
26184         return mDefaultFocusHighlightCache;
26185     }
26186 
26187     /**
26188      * Set the current default focus highlight.
26189      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
26190      */
setDefaultFocusHighlight(Drawable highlight)26191     private void setDefaultFocusHighlight(Drawable highlight) {
26192         mDefaultFocusHighlight = highlight;
26193         mDefaultFocusHighlightSizeChanged = true;
26194         if (highlight != null) {
26195             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
26196                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
26197             }
26198             highlight.setLayoutDirection(getLayoutDirection());
26199             if (highlight.isStateful()) {
26200                 highlight.setState(getDrawableState());
26201             }
26202             if (isAttachedToWindow()) {
26203                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
26204             }
26205             // Set callback last, since the view may still be initializing.
26206             highlight.setCallback(this);
26207         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
26208                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
26209             mPrivateFlags |= PFLAG_SKIP_DRAW;
26210         }
26211         invalidate();
26212     }
26213 
26214     /**
26215      * Check whether we need to draw a default focus highlight when this view gets focused,
26216      * which requires:
26217      * <ul>
26218      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
26219      *         is not defined.</li>
26220      *     <li>This view is not in touch mode.</li>
26221      *     <li>This view doesn't opt out for a default focus highlight, via
26222      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
26223      *     <li>This view is attached to window.</li>
26224      * </ul>
26225      * @return {@code true} if a default focus highlight is needed.
26226      * @hide
26227      */
26228     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)26229     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
26230         final boolean lackFocusState = (background == null || !background.isStateful()
26231                 || !background.hasFocusStateSpecified())
26232                 && (foreground == null || !foreground.isStateful()
26233                 || !foreground.hasFocusStateSpecified());
26234         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
26235                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
26236     }
26237 
26238     /**
26239      * When this view is focused, switches on/off the default focused highlight.
26240      * <p>
26241      * This always happens when this view is focused, and only at this moment the default focus
26242      * highlight can be visible.
26243      */
switchDefaultFocusHighlight()26244     private void switchDefaultFocusHighlight() {
26245         if (isFocused()) {
26246             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
26247                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
26248             final boolean active = mDefaultFocusHighlight != null;
26249             if (needed && !active) {
26250                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
26251             } else if (!needed && active) {
26252                 // The highlight is no longer needed, so tear it down.
26253                 setDefaultFocusHighlight(null);
26254             }
26255         }
26256     }
26257 
26258     /**
26259      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
26260      * @param canvas the canvas where we're drawing the highlight.
26261      */
drawDefaultFocusHighlight(@onNull Canvas canvas)26262     private void drawDefaultFocusHighlight(@NonNull Canvas canvas) {
26263         if (mDefaultFocusHighlight != null && isFocused()) {
26264             if (mDefaultFocusHighlightSizeChanged) {
26265                 mDefaultFocusHighlightSizeChanged = false;
26266                 final int l = mScrollX;
26267                 final int r = l + mRight - mLeft;
26268                 final int t = mScrollY;
26269                 final int b = t + mBottom - mTop;
26270                 mDefaultFocusHighlight.setBounds(l, t, r, b);
26271             }
26272             mDefaultFocusHighlight.draw(canvas);
26273         }
26274     }
26275 
26276     /**
26277      * Return an array of resource IDs of the drawable states representing the
26278      * current state of the view.
26279      *
26280      * @return The current drawable state
26281      *
26282      * @see Drawable#setState(int[])
26283      * @see #drawableStateChanged()
26284      * @see #onCreateDrawableState(int)
26285      */
getDrawableState()26286     public final int[] getDrawableState() {
26287         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
26288             return mDrawableState;
26289         } else {
26290             mDrawableState = onCreateDrawableState(0);
26291             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
26292             return mDrawableState;
26293         }
26294     }
26295 
26296     /**
26297      * Generate the new {@link android.graphics.drawable.Drawable} state for
26298      * this view. This is called by the view
26299      * system when the cached Drawable state is determined to be invalid.  To
26300      * retrieve the current state, you should use {@link #getDrawableState}.
26301      *
26302      * @param extraSpace if non-zero, this is the number of extra entries you
26303      * would like in the returned array in which you can place your own
26304      * states.
26305      *
26306      * @return Returns an array holding the current {@link Drawable} state of
26307      * the view.
26308      *
26309      * @see #mergeDrawableStates(int[], int[])
26310      */
onCreateDrawableState(int extraSpace)26311     protected int[] onCreateDrawableState(int extraSpace) {
26312         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
26313                 mParent instanceof View) {
26314             return ((View) mParent).onCreateDrawableState(extraSpace);
26315         }
26316 
26317         int[] drawableState;
26318 
26319         int privateFlags = mPrivateFlags;
26320 
26321         int viewStateIndex = 0;
26322         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
26323         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
26324         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
26325         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
26326         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
26327         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
26328         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
26329             // This is set if HW acceleration is requested, even if the current
26330             // process doesn't allow it.  This is just to allow app preview
26331             // windows to better match their app.
26332             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
26333         }
26334         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
26335 
26336         final int privateFlags2 = mPrivateFlags2;
26337         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
26338             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
26339         }
26340         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
26341             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
26342         }
26343 
26344         drawableState = StateSet.get(viewStateIndex);
26345 
26346         //noinspection ConstantIfStatement
26347         if (false) {
26348             Log.i("View", "drawableStateIndex=" + viewStateIndex);
26349             Log.i("View", toString()
26350                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
26351                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
26352                     + " fo=" + hasFocus()
26353                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
26354                     + " wf=" + hasWindowFocus()
26355                     + ": " + Arrays.toString(drawableState));
26356         }
26357 
26358         if (extraSpace == 0) {
26359             return drawableState;
26360         }
26361 
26362         final int[] fullState;
26363         if (drawableState != null) {
26364             fullState = new int[drawableState.length + extraSpace];
26365             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
26366         } else {
26367             fullState = new int[extraSpace];
26368         }
26369 
26370         return fullState;
26371     }
26372 
26373     /**
26374      * Merge your own state values in <var>additionalState</var> into the base
26375      * state values <var>baseState</var> that were returned by
26376      * {@link #onCreateDrawableState(int)}.
26377      *
26378      * @param baseState The base state values returned by
26379      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
26380      * own additional state values.
26381      *
26382      * @param additionalState The additional state values you would like
26383      * added to <var>baseState</var>; this array is not modified.
26384      *
26385      * @return As a convenience, the <var>baseState</var> array you originally
26386      * passed into the function is returned.
26387      *
26388      * @see #onCreateDrawableState(int)
26389      */
mergeDrawableStates(int[] baseState, int[] additionalState)26390     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
26391         final int N = baseState.length;
26392         int i = N - 1;
26393         while (i >= 0 && baseState[i] == 0) {
26394             i--;
26395         }
26396         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
26397         return baseState;
26398     }
26399 
26400     /**
26401      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
26402      * on all Drawable objects associated with this view.
26403      * <p>
26404      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
26405      * attached to this view.
26406      */
26407     @CallSuper
jumpDrawablesToCurrentState()26408     public void jumpDrawablesToCurrentState() {
26409         if (mBackground != null) {
26410             mBackground.jumpToCurrentState();
26411         }
26412         if (mStateListAnimator != null) {
26413             mStateListAnimator.jumpToCurrentState();
26414         }
26415         if (mDefaultFocusHighlight != null) {
26416             mDefaultFocusHighlight.jumpToCurrentState();
26417         }
26418         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
26419             mForegroundInfo.mDrawable.jumpToCurrentState();
26420         }
26421     }
26422 
26423     /**
26424      * Sets the background color for this view.
26425      * @param color the color of the background
26426      */
26427     @RemotableViewMethod
setBackgroundColor(@olorInt int color)26428     public void setBackgroundColor(@ColorInt int color) {
26429         if (mBackground instanceof ColorDrawable) {
26430             ((ColorDrawable) mBackground.mutate()).setColor(color);
26431             computeOpaqueFlags();
26432             mBackgroundResource = 0;
26433         } else {
26434             setBackground(new ColorDrawable(color));
26435         }
26436     }
26437 
26438     /**
26439      * Set the background to a given resource. The resource should refer to
26440      * a Drawable object or 0 to remove the background.
26441      * @param resid The identifier of the resource.
26442      *
26443      * @attr ref android.R.styleable#View_background
26444      */
26445     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)26446     public void setBackgroundResource(@DrawableRes int resid) {
26447         if (resid != 0 && resid == mBackgroundResource) {
26448             return;
26449         }
26450 
26451         Drawable d = null;
26452         if (resid != 0) {
26453             d = mContext.getDrawable(resid);
26454         }
26455         setBackground(d);
26456 
26457         mBackgroundResource = resid;
26458     }
26459 
26460     /**
26461      * Set the background to a given Drawable, or remove the background. If the
26462      * background has padding, this View's padding is set to the background's
26463      * padding. However, when a background is removed, this View's padding isn't
26464      * touched. If setting the padding is desired, please use
26465      * {@link #setPadding(int, int, int, int)}.
26466      *
26467      * @param background The Drawable to use as the background, or null to remove the
26468      *        background
26469      */
setBackground(Drawable background)26470     public void setBackground(Drawable background) {
26471         //noinspection deprecation
26472         setBackgroundDrawable(background);
26473     }
26474 
26475     /**
26476      * @deprecated use {@link #setBackground(Drawable)} instead
26477      */
26478     @Deprecated
setBackgroundDrawable(Drawable background)26479     public void setBackgroundDrawable(Drawable background) {
26480         computeOpaqueFlags();
26481 
26482         if (background == mBackground) {
26483             return;
26484         }
26485 
26486         boolean requestLayout = false;
26487 
26488         mBackgroundResource = 0;
26489 
26490         /*
26491          * Regardless of whether we're setting a new background or not, we want
26492          * to clear the previous drawable. setVisible first while we still have the callback set.
26493          */
26494         if (mBackground != null) {
26495             if (isAttachedToWindow()) {
26496                 mBackground.setVisible(false, false);
26497             }
26498             mBackground.setCallback(null);
26499             unscheduleDrawable(mBackground);
26500         }
26501 
26502         if (background != null) {
26503             Rect padding = sThreadLocal.get();
26504             if (padding == null) {
26505                 padding = new Rect();
26506                 sThreadLocal.set(padding);
26507             }
26508             resetResolvedDrawablesInternal();
26509             background.setLayoutDirection(getLayoutDirection());
26510             if (background.getPadding(padding)) {
26511                 resetResolvedPaddingInternal();
26512                 switch (background.getLayoutDirection()) {
26513                     case LAYOUT_DIRECTION_RTL:
26514                         mUserPaddingLeftInitial = padding.right;
26515                         mUserPaddingRightInitial = padding.left;
26516                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
26517                         break;
26518                     case LAYOUT_DIRECTION_LTR:
26519                     default:
26520                         mUserPaddingLeftInitial = padding.left;
26521                         mUserPaddingRightInitial = padding.right;
26522                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
26523                 }
26524                 mLeftPaddingDefined = false;
26525                 mRightPaddingDefined = false;
26526             }
26527 
26528             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
26529             // if it has a different minimum size, we should layout again
26530             if (mBackground == null
26531                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
26532                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
26533                 requestLayout = true;
26534             }
26535 
26536             // Set mBackground before we set this as the callback and start making other
26537             // background drawable state change calls. In particular, the setVisible call below
26538             // can result in drawables attempting to start animations or otherwise invalidate,
26539             // which requires the view set as the callback (us) to recognize the drawable as
26540             // belonging to it as per verifyDrawable.
26541             mBackground = background;
26542             if (background.isStateful()) {
26543                 background.setState(getDrawableState());
26544             }
26545             if (isAttachedToWindow()) {
26546                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
26547             }
26548 
26549             applyBackgroundTint();
26550 
26551             // Set callback last, since the view may still be initializing.
26552             background.setCallback(this);
26553 
26554             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
26555                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
26556                 requestLayout = true;
26557             }
26558         } else {
26559             /* Remove the background */
26560             mBackground = null;
26561             if ((mViewFlags & WILL_NOT_DRAW) != 0
26562                     && (mDefaultFocusHighlight == null)
26563                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
26564                 mPrivateFlags |= PFLAG_SKIP_DRAW;
26565             }
26566 
26567             /*
26568              * When the background is set, we try to apply its padding to this
26569              * View. When the background is removed, we don't touch this View's
26570              * padding. This is noted in the Javadocs. Hence, we don't need to
26571              * requestLayout(), the invalidate() below is sufficient.
26572              */
26573 
26574             // The old background's minimum size could have affected this
26575             // View's layout, so let's requestLayout
26576             requestLayout = true;
26577         }
26578 
26579         computeOpaqueFlags();
26580 
26581         if (requestLayout) {
26582             requestLayout();
26583         }
26584 
26585         mBackgroundSizeChanged = true;
26586         invalidate(true);
26587         invalidateOutline();
26588     }
26589 
26590     /**
26591      * Gets the background drawable
26592      *
26593      * @return The drawable used as the background for this view, if any.
26594      *
26595      * @see #setBackground(Drawable)
26596      *
26597      * @attr ref android.R.styleable#View_background
26598      */
26599     @InspectableProperty
getBackground()26600     public Drawable getBackground() {
26601         return mBackground;
26602     }
26603 
26604     /**
26605      * Applies a tint to the background drawable. Does not modify the current tint
26606      * mode, which is {@link BlendMode#SRC_IN} by default.
26607      * <p>
26608      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
26609      * mutate the drawable and apply the specified tint and tint mode using
26610      * {@link Drawable#setTintList(ColorStateList)}.
26611      *
26612      * @param tint the tint to apply, may be {@code null} to clear tint
26613      *
26614      * @attr ref android.R.styleable#View_backgroundTint
26615      * @see #getBackgroundTintList()
26616      * @see Drawable#setTintList(ColorStateList)
26617      */
26618     @RemotableViewMethod
setBackgroundTintList(@ullable ColorStateList tint)26619     public void setBackgroundTintList(@Nullable ColorStateList tint) {
26620         if (mBackgroundTint == null) {
26621             mBackgroundTint = new TintInfo();
26622         }
26623         mBackgroundTint.mTintList = tint;
26624         mBackgroundTint.mHasTintList = true;
26625 
26626         applyBackgroundTint();
26627     }
26628 
26629     /**
26630      * Return the tint applied to the background drawable, if specified.
26631      *
26632      * @return the tint applied to the background drawable
26633      * @attr ref android.R.styleable#View_backgroundTint
26634      * @see #setBackgroundTintList(ColorStateList)
26635      */
26636     @InspectableProperty(name = "backgroundTint")
26637     @Nullable
getBackgroundTintList()26638     public ColorStateList getBackgroundTintList() {
26639         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
26640     }
26641 
26642     /**
26643      * Specifies the blending mode used to apply the tint specified by
26644      * {@link #setBackgroundTintList(ColorStateList)}} to the background
26645      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
26646      *
26647      * @param tintMode the blending mode used to apply the tint, may be
26648      *                 {@code null} to clear tint
26649      * @attr ref android.R.styleable#View_backgroundTintMode
26650      * @see #getBackgroundTintMode()
26651      * @see Drawable#setTintMode(PorterDuff.Mode)
26652      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)26653     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
26654         BlendMode mode = null;
26655         if (tintMode != null) {
26656             mode = BlendMode.fromValue(tintMode.nativeInt);
26657         }
26658 
26659         setBackgroundTintBlendMode(mode);
26660     }
26661 
26662     /**
26663      * Specifies the blending mode used to apply the tint specified by
26664      * {@link #setBackgroundTintList(ColorStateList)}} to the background
26665      * drawable. The default mode is {@link BlendMode#SRC_IN}.
26666      *
26667      * @param blendMode the blending mode used to apply the tint, may be
26668      *                 {@code null} to clear tint
26669      * @attr ref android.R.styleable#View_backgroundTintMode
26670      * @see #getBackgroundTintMode()
26671      * @see Drawable#setTintBlendMode(BlendMode)
26672      */
26673     @RemotableViewMethod
setBackgroundTintBlendMode(@ullable BlendMode blendMode)26674     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
26675         if (mBackgroundTint == null) {
26676             mBackgroundTint = new TintInfo();
26677         }
26678 
26679         mBackgroundTint.mBlendMode = blendMode;
26680         mBackgroundTint.mHasTintMode = true;
26681 
26682         applyBackgroundTint();
26683     }
26684 
26685     /**
26686      * Return the blending mode used to apply the tint to the background
26687      * drawable, if specified.
26688      *
26689      * @return the blending mode used to apply the tint to the background
26690      *         drawable
26691      * @attr ref android.R.styleable#View_backgroundTintMode
26692      * @see #setBackgroundTintBlendMode(BlendMode)
26693      *
26694      */
26695     @Nullable
26696     @InspectableProperty
getBackgroundTintMode()26697     public PorterDuff.Mode getBackgroundTintMode() {
26698         PorterDuff.Mode porterDuffMode;
26699         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
26700             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
26701         } else {
26702             porterDuffMode = null;
26703         }
26704         return porterDuffMode;
26705     }
26706 
26707     /**
26708      * Return the blending mode used to apply the tint to the background
26709      * drawable, if specified.
26710      *
26711      * @return the blending mode used to apply the tint to the background
26712      *         drawable, null if no blend has previously been configured
26713      * @attr ref android.R.styleable#View_backgroundTintMode
26714      * @see #setBackgroundTintBlendMode(BlendMode)
26715      */
getBackgroundTintBlendMode()26716     public @Nullable BlendMode getBackgroundTintBlendMode() {
26717         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
26718     }
26719 
applyBackgroundTint()26720     private void applyBackgroundTint() {
26721         if (mBackground != null && mBackgroundTint != null) {
26722             final TintInfo tintInfo = mBackgroundTint;
26723             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
26724                 mBackground = mBackground.mutate();
26725 
26726                 if (tintInfo.mHasTintList) {
26727                     mBackground.setTintList(tintInfo.mTintList);
26728                 }
26729 
26730                 if (tintInfo.mHasTintMode) {
26731                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
26732                 }
26733 
26734                 // The drawable (or one of its children) may not have been
26735                 // stateful before applying the tint, so let's try again.
26736                 if (mBackground.isStateful()) {
26737                     mBackground.setState(getDrawableState());
26738                 }
26739             }
26740         }
26741     }
26742 
26743     /**
26744      * Returns the drawable used as the foreground of this View. The
26745      * foreground drawable, if non-null, is always drawn on top of the view's content.
26746      *
26747      * @return a Drawable or null if no foreground was set
26748      *
26749      * @see #onDrawForeground(Canvas)
26750      */
26751     @InspectableProperty
getForeground()26752     public Drawable getForeground() {
26753         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
26754     }
26755 
26756     /**
26757      * Supply a Drawable that is to be rendered on top of all of the content in the view.
26758      *
26759      * @param foreground the Drawable to be drawn on top of the children
26760      *
26761      * @attr ref android.R.styleable#View_foreground
26762      */
setForeground(Drawable foreground)26763     public void setForeground(Drawable foreground) {
26764         if (mForegroundInfo == null) {
26765             if (foreground == null) {
26766                 // Nothing to do.
26767                 return;
26768             }
26769             mForegroundInfo = new ForegroundInfo();
26770         }
26771 
26772         if (foreground == mForegroundInfo.mDrawable) {
26773             // Nothing to do
26774             return;
26775         }
26776 
26777         if (mForegroundInfo.mDrawable != null) {
26778             if (isAttachedToWindow()) {
26779                 mForegroundInfo.mDrawable.setVisible(false, false);
26780             }
26781             mForegroundInfo.mDrawable.setCallback(null);
26782             unscheduleDrawable(mForegroundInfo.mDrawable);
26783         }
26784 
26785         mForegroundInfo.mDrawable = foreground;
26786         mForegroundInfo.mBoundsChanged = true;
26787         if (foreground != null) {
26788             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
26789                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
26790             }
26791             foreground.setLayoutDirection(getLayoutDirection());
26792             if (foreground.isStateful()) {
26793                 foreground.setState(getDrawableState());
26794             }
26795             applyForegroundTint();
26796             if (isAttachedToWindow()) {
26797                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
26798             }
26799             // Set callback last, since the view may still be initializing.
26800             foreground.setCallback(this);
26801         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
26802                 && (mDefaultFocusHighlight == null)) {
26803             mPrivateFlags |= PFLAG_SKIP_DRAW;
26804         }
26805         requestLayout();
26806         invalidate();
26807     }
26808 
26809     /**
26810      * Magic bit used to support features of framework-internal window decor implementation details.
26811      * This used to live exclusively in FrameLayout.
26812      *
26813      * @return true if the foreground should draw inside the padding region or false
26814      *         if it should draw inset by the view's padding
26815      * @hide internal use only; only used by FrameLayout and internal screen layouts.
26816      */
isForegroundInsidePadding()26817     public boolean isForegroundInsidePadding() {
26818         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
26819     }
26820 
26821     /**
26822      * Describes how the foreground is positioned.
26823      *
26824      * @return foreground gravity.
26825      *
26826      * @see #setForegroundGravity(int)
26827      *
26828      * @attr ref android.R.styleable#View_foregroundGravity
26829      */
26830     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()26831     public int getForegroundGravity() {
26832         return mForegroundInfo != null ? mForegroundInfo.mGravity
26833                 : Gravity.START | Gravity.TOP;
26834     }
26835 
26836     /**
26837      * Describes how the foreground is positioned. Defaults to START and TOP.
26838      *
26839      * @param gravity see {@link android.view.Gravity}
26840      *
26841      * @see #getForegroundGravity()
26842      *
26843      * @attr ref android.R.styleable#View_foregroundGravity
26844      */
setForegroundGravity(int gravity)26845     public void setForegroundGravity(int gravity) {
26846         if (mForegroundInfo == null) {
26847             mForegroundInfo = new ForegroundInfo();
26848         }
26849 
26850         if (mForegroundInfo.mGravity != gravity) {
26851             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
26852                 gravity |= Gravity.START;
26853             }
26854 
26855             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
26856                 gravity |= Gravity.TOP;
26857             }
26858 
26859             mForegroundInfo.mGravity = gravity;
26860             requestLayout();
26861         }
26862     }
26863 
26864     /**
26865      * Applies a tint to the foreground drawable. Does not modify the current tint
26866      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
26867      * <p>
26868      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
26869      * mutate the drawable and apply the specified tint and tint mode using
26870      * {@link Drawable#setTintList(ColorStateList)}.
26871      *
26872      * @param tint the tint to apply, may be {@code null} to clear tint
26873      *
26874      * @attr ref android.R.styleable#View_foregroundTint
26875      * @see #getForegroundTintList()
26876      * @see Drawable#setTintList(ColorStateList)
26877      */
26878     @RemotableViewMethod
setForegroundTintList(@ullable ColorStateList tint)26879     public void setForegroundTintList(@Nullable ColorStateList tint) {
26880         if (mForegroundInfo == null) {
26881             mForegroundInfo = new ForegroundInfo();
26882         }
26883         if (mForegroundInfo.mTintInfo == null) {
26884             mForegroundInfo.mTintInfo = new TintInfo();
26885         }
26886         mForegroundInfo.mTintInfo.mTintList = tint;
26887         mForegroundInfo.mTintInfo.mHasTintList = true;
26888 
26889         applyForegroundTint();
26890     }
26891 
26892     /**
26893      * Return the tint applied to the foreground drawable, if specified.
26894      *
26895      * @return the tint applied to the foreground drawable
26896      * @attr ref android.R.styleable#View_foregroundTint
26897      * @see #setForegroundTintList(ColorStateList)
26898      */
26899     @InspectableProperty(name = "foregroundTint")
26900     @Nullable
getForegroundTintList()26901     public ColorStateList getForegroundTintList() {
26902         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
26903                 ? mForegroundInfo.mTintInfo.mTintList : null;
26904     }
26905 
26906     /**
26907      * Specifies the blending mode used to apply the tint specified by
26908      * {@link #setForegroundTintList(ColorStateList)}} to the background
26909      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
26910      *
26911      * @param tintMode the blending mode used to apply the tint, may be
26912      *                 {@code null} to clear tint
26913      * @attr ref android.R.styleable#View_foregroundTintMode
26914      * @see #getForegroundTintMode()
26915      * @see Drawable#setTintMode(PorterDuff.Mode)
26916      *
26917      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)26918     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
26919         BlendMode mode = null;
26920         if (tintMode != null) {
26921             mode = BlendMode.fromValue(tintMode.nativeInt);
26922         }
26923         setForegroundTintBlendMode(mode);
26924     }
26925 
26926     /**
26927      * Specifies the blending mode used to apply the tint specified by
26928      * {@link #setForegroundTintList(ColorStateList)}} to the background
26929      * drawable. The default mode is {@link BlendMode#SRC_IN}.
26930      *
26931      * @param blendMode the blending mode used to apply the tint, may be
26932      *                 {@code null} to clear tint
26933      * @attr ref android.R.styleable#View_foregroundTintMode
26934      * @see #getForegroundTintMode()
26935      * @see Drawable#setTintBlendMode(BlendMode)
26936      */
26937     @RemotableViewMethod
setForegroundTintBlendMode(@ullable BlendMode blendMode)26938     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
26939         if (mForegroundInfo == null) {
26940             mForegroundInfo = new ForegroundInfo();
26941         }
26942         if (mForegroundInfo.mTintInfo == null) {
26943             mForegroundInfo.mTintInfo = new TintInfo();
26944         }
26945         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
26946         mForegroundInfo.mTintInfo.mHasTintMode = true;
26947 
26948         applyForegroundTint();
26949     }
26950 
26951     /**
26952      * Return the blending mode used to apply the tint to the foreground
26953      * drawable, if specified.
26954      *
26955      * @return the blending mode used to apply the tint to the foreground
26956      *         drawable
26957      * @attr ref android.R.styleable#View_foregroundTintMode
26958      * @see #setForegroundTintMode(PorterDuff.Mode)
26959      */
26960     @InspectableProperty
26961     @Nullable
getForegroundTintMode()26962     public PorterDuff.Mode getForegroundTintMode() {
26963         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
26964                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
26965         if (blendMode != null) {
26966             return BlendMode.blendModeToPorterDuffMode(blendMode);
26967         } else {
26968             return null;
26969         }
26970     }
26971 
26972     /**
26973      * Return the blending mode used to apply the tint to the foreground
26974      * drawable, if specified.
26975      *
26976      * @return the blending mode used to apply the tint to the foreground
26977      *         drawable
26978      * @attr ref android.R.styleable#View_foregroundTintMode
26979      * @see #setForegroundTintBlendMode(BlendMode)
26980      *
26981      */
getForegroundTintBlendMode()26982     public @Nullable BlendMode getForegroundTintBlendMode() {
26983         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
26984                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
26985     }
26986 
applyForegroundTint()26987     private void applyForegroundTint() {
26988         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
26989                 && mForegroundInfo.mTintInfo != null) {
26990             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
26991             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
26992                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
26993 
26994                 if (tintInfo.mHasTintList) {
26995                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
26996                 }
26997 
26998                 if (tintInfo.mHasTintMode) {
26999                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
27000                 }
27001 
27002                 // The drawable (or one of its children) may not have been
27003                 // stateful before applying the tint, so let's try again.
27004                 if (mForegroundInfo.mDrawable.isStateful()) {
27005                     mForegroundInfo.mDrawable.setState(getDrawableState());
27006                 }
27007             }
27008         }
27009     }
27010 
27011     /**
27012      * Get the drawable to be overlayed when a view is autofilled
27013      *
27014      * @return The drawable
27015      *
27016      * @throws IllegalStateException if the drawable could not be found.
27017      */
getAutofilledDrawable()27018     @Nullable private Drawable getAutofilledDrawable() {
27019         if (mAttachInfo == null) {
27020             return null;
27021         }
27022         // Lazily load the isAutofilled drawable.
27023         if (mAttachInfo.mAutofilledDrawable == null) {
27024             Context rootContext = getRootView().getContext();
27025             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
27026             int attributeResourceId = a.getResourceId(0, 0);
27027             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
27028             a.recycle();
27029         }
27030 
27031         return mAttachInfo.mAutofilledDrawable;
27032     }
27033 
27034     /**
27035      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
27036      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
27037      *
27038      * @param canvas The canvas to draw on
27039      */
drawAutofilledHighlight(@onNull Canvas canvas)27040     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
27041         if (isAutofilled() && !hideAutofillHighlight()) {
27042             Drawable autofilledHighlight = getAutofilledDrawable();
27043 
27044             if (autofilledHighlight != null) {
27045                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
27046                 autofilledHighlight.draw(canvas);
27047             }
27048         }
27049     }
27050 
27051     /**
27052      * Draw any foreground content for this view.
27053      *
27054      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
27055      * drawable or other view-specific decorations. The foreground is drawn on top of the
27056      * primary view content.</p>
27057      *
27058      * @param canvas canvas to draw into
27059      */
onDrawForeground(@onNull Canvas canvas)27060     public void onDrawForeground(@NonNull Canvas canvas) {
27061         onDrawScrollIndicators(canvas);
27062         onDrawScrollBars(canvas);
27063 
27064         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
27065         if (foreground != null) {
27066             if (mForegroundInfo.mBoundsChanged) {
27067                 mForegroundInfo.mBoundsChanged = false;
27068                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
27069                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
27070 
27071                 if (mForegroundInfo.mInsidePadding) {
27072                     selfBounds.set(0, 0, getWidth(), getHeight());
27073                 } else {
27074                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
27075                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
27076                 }
27077 
27078                 final int ld = getLayoutDirection();
27079                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
27080                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
27081                 foreground.setBounds(overlayBounds);
27082             }
27083 
27084             foreground.draw(canvas);
27085         }
27086     }
27087 
27088     /**
27089      * Sets the padding. The view may add on the space required to display
27090      * the scrollbars, depending on the style and visibility of the scrollbars.
27091      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
27092      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
27093      * from the values set in this call.
27094      *
27095      * @attr ref android.R.styleable#View_padding
27096      * @attr ref android.R.styleable#View_paddingBottom
27097      * @attr ref android.R.styleable#View_paddingLeft
27098      * @attr ref android.R.styleable#View_paddingRight
27099      * @attr ref android.R.styleable#View_paddingTop
27100      * @param left the left padding in pixels
27101      * @param top the top padding in pixels
27102      * @param right the right padding in pixels
27103      * @param bottom the bottom padding in pixels
27104      */
setPadding(int left, int top, int right, int bottom)27105     public void setPadding(int left, int top, int right, int bottom) {
27106         resetResolvedPaddingInternal();
27107 
27108         mUserPaddingStart = UNDEFINED_PADDING;
27109         mUserPaddingEnd = UNDEFINED_PADDING;
27110 
27111         mUserPaddingLeftInitial = left;
27112         mUserPaddingRightInitial = right;
27113 
27114         mLeftPaddingDefined = true;
27115         mRightPaddingDefined = true;
27116 
27117         internalSetPadding(left, top, right, bottom);
27118     }
27119 
27120     /**
27121      * @hide
27122      */
27123     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)27124     protected void internalSetPadding(int left, int top, int right, int bottom) {
27125         mUserPaddingLeft = left;
27126         mUserPaddingRight = right;
27127         mUserPaddingBottom = bottom;
27128 
27129         final int viewFlags = mViewFlags;
27130         boolean changed = false;
27131 
27132         // Common case is there are no scroll bars.
27133         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
27134             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
27135                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
27136                         ? 0 : getVerticalScrollbarWidth();
27137                 switch (mVerticalScrollbarPosition) {
27138                     case SCROLLBAR_POSITION_DEFAULT:
27139                         if (isLayoutRtl()) {
27140                             left += offset;
27141                         } else {
27142                             right += offset;
27143                         }
27144                         break;
27145                     case SCROLLBAR_POSITION_RIGHT:
27146                         right += offset;
27147                         break;
27148                     case SCROLLBAR_POSITION_LEFT:
27149                         left += offset;
27150                         break;
27151                 }
27152             }
27153             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
27154                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
27155                         ? 0 : getHorizontalScrollbarHeight();
27156             }
27157         }
27158 
27159         if (mPaddingLeft != left) {
27160             changed = true;
27161             mPaddingLeft = left;
27162         }
27163         if (mPaddingTop != top) {
27164             changed = true;
27165             mPaddingTop = top;
27166         }
27167         if (mPaddingRight != right) {
27168             changed = true;
27169             mPaddingRight = right;
27170         }
27171         if (mPaddingBottom != bottom) {
27172             changed = true;
27173             mPaddingBottom = bottom;
27174         }
27175 
27176         if (changed) {
27177             requestLayout();
27178             invalidateOutline();
27179         }
27180     }
27181 
27182     /**
27183      * Sets the relative padding. The view may add on the space required to display
27184      * the scrollbars, depending on the style and visibility of the scrollbars.
27185      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
27186      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
27187      * from the values set in this call.
27188      *
27189      * @attr ref android.R.styleable#View_padding
27190      * @attr ref android.R.styleable#View_paddingBottom
27191      * @attr ref android.R.styleable#View_paddingStart
27192      * @attr ref android.R.styleable#View_paddingEnd
27193      * @attr ref android.R.styleable#View_paddingTop
27194      * @param start the start padding in pixels
27195      * @param top the top padding in pixels
27196      * @param end the end padding in pixels
27197      * @param bottom the bottom padding in pixels
27198      */
setPaddingRelative(int start, int top, int end, int bottom)27199     public void setPaddingRelative(int start, int top, int end, int bottom) {
27200         resetResolvedPaddingInternal();
27201 
27202         mUserPaddingStart = start;
27203         mUserPaddingEnd = end;
27204         mLeftPaddingDefined = true;
27205         mRightPaddingDefined = true;
27206 
27207         switch(getLayoutDirection()) {
27208             case LAYOUT_DIRECTION_RTL:
27209                 mUserPaddingLeftInitial = end;
27210                 mUserPaddingRightInitial = start;
27211                 internalSetPadding(end, top, start, bottom);
27212                 break;
27213             case LAYOUT_DIRECTION_LTR:
27214             default:
27215                 mUserPaddingLeftInitial = start;
27216                 mUserPaddingRightInitial = end;
27217                 internalSetPadding(start, top, end, bottom);
27218         }
27219     }
27220 
27221     /**
27222      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
27223      * resource ID of the source layout.
27224      *
27225      * @return The layout resource id if this view was inflated from XML, otherwise
27226      * {@link Resources#ID_NULL}.
27227      */
27228     @LayoutRes
getSourceLayoutResId()27229     public int getSourceLayoutResId() {
27230         return mSourceLayoutId;
27231     }
27232 
27233     /**
27234      * Returns the top padding of this view.
27235      *
27236      * @return the top padding in pixels
27237      */
27238     @InspectableProperty
getPaddingTop()27239     public int getPaddingTop() {
27240         return mPaddingTop;
27241     }
27242 
27243     /**
27244      * Returns the bottom padding of this view. If there are inset and enabled
27245      * scrollbars, this value may include the space required to display the
27246      * scrollbars as well.
27247      *
27248      * @return the bottom padding in pixels
27249      */
27250     @InspectableProperty
getPaddingBottom()27251     public int getPaddingBottom() {
27252         return mPaddingBottom;
27253     }
27254 
27255     /**
27256      * Returns the left padding of this view. If there are inset and enabled
27257      * scrollbars, this value may include the space required to display the
27258      * scrollbars as well.
27259      *
27260      * @return the left padding in pixels
27261      */
27262     @InspectableProperty
getPaddingLeft()27263     public int getPaddingLeft() {
27264         if (!isPaddingResolved()) {
27265             resolvePadding();
27266         }
27267         return mPaddingLeft;
27268     }
27269 
27270     /**
27271      * Returns the start padding of this view depending on its resolved layout direction.
27272      * If there are inset and enabled scrollbars, this value may include the space
27273      * required to display the scrollbars as well.
27274      *
27275      * @return the start padding in pixels
27276      */
getPaddingStart()27277     public int getPaddingStart() {
27278         if (!isPaddingResolved()) {
27279             resolvePadding();
27280         }
27281         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
27282                 mPaddingRight : mPaddingLeft;
27283     }
27284 
27285     /**
27286      * Returns the right padding of this view. If there are inset and enabled
27287      * scrollbars, this value may include the space required to display the
27288      * scrollbars as well.
27289      *
27290      * @return the right padding in pixels
27291      */
27292     @InspectableProperty
getPaddingRight()27293     public int getPaddingRight() {
27294         if (!isPaddingResolved()) {
27295             resolvePadding();
27296         }
27297         return mPaddingRight;
27298     }
27299 
27300     /**
27301      * Returns the end padding of this view depending on its resolved layout direction.
27302      * If there are inset and enabled scrollbars, this value may include the space
27303      * required to display the scrollbars as well.
27304      *
27305      * @return the end padding in pixels
27306      */
getPaddingEnd()27307     public int getPaddingEnd() {
27308         if (!isPaddingResolved()) {
27309             resolvePadding();
27310         }
27311         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
27312                 mPaddingLeft : mPaddingRight;
27313     }
27314 
27315     /**
27316      * Return if the padding has been set through relative values
27317      * {@link #setPaddingRelative(int, int, int, int)} or through
27318      * @attr ref android.R.styleable#View_paddingStart or
27319      * @attr ref android.R.styleable#View_paddingEnd
27320      *
27321      * @return true if the padding is relative or false if it is not.
27322      */
isPaddingRelative()27323     public boolean isPaddingRelative() {
27324         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
27325     }
27326 
computeOpticalInsets()27327     Insets computeOpticalInsets() {
27328         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
27329     }
27330 
27331     /**
27332      * @hide
27333      */
27334     @UnsupportedAppUsage
resetPaddingToInitialValues()27335     public void resetPaddingToInitialValues() {
27336         if (isRtlCompatibilityMode()) {
27337             mPaddingLeft = mUserPaddingLeftInitial;
27338             mPaddingRight = mUserPaddingRightInitial;
27339             return;
27340         }
27341         if (isLayoutRtl()) {
27342             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
27343             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
27344         } else {
27345             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
27346             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
27347         }
27348     }
27349 
27350     /**
27351      * @hide
27352      */
getOpticalInsets()27353     public Insets getOpticalInsets() {
27354         if (mLayoutInsets == null) {
27355             mLayoutInsets = computeOpticalInsets();
27356         }
27357         return mLayoutInsets;
27358     }
27359 
27360     /**
27361      * Set this view's optical insets.
27362      *
27363      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
27364      * property. Views that compute their own optical insets should call it as part of measurement.
27365      * This method does not request layout. If you are setting optical insets outside of
27366      * measure/layout itself you will want to call requestLayout() yourself.
27367      * </p>
27368      * @hide
27369      */
setOpticalInsets(Insets insets)27370     public void setOpticalInsets(Insets insets) {
27371         mLayoutInsets = insets;
27372     }
27373 
27374     /**
27375      * Changes the selection state of this view. A view can be selected or not.
27376      * Note that selection is not the same as focus. Views are typically
27377      * selected in the context of an AdapterView like ListView or GridView;
27378      * the selected view is the view that is highlighted.
27379      *
27380      * @param selected true if the view must be selected, false otherwise
27381      */
setSelected(boolean selected)27382     public void setSelected(boolean selected) {
27383         //noinspection DoubleNegation
27384         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
27385             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
27386             if (!selected) resetPressedState();
27387             invalidate(true);
27388             refreshDrawableState();
27389             dispatchSetSelected(selected);
27390             if (selected) {
27391                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
27392             } else {
27393                 notifyViewAccessibilityStateChangedIfNeeded(
27394                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
27395             }
27396         }
27397     }
27398 
27399     /**
27400      * Dispatch setSelected to all of this View's children.
27401      *
27402      * @see #setSelected(boolean)
27403      *
27404      * @param selected The new selected state
27405      */
dispatchSetSelected(boolean selected)27406     protected void dispatchSetSelected(boolean selected) {
27407     }
27408 
27409     /**
27410      * Indicates the selection state of this view.
27411      *
27412      * @return true if the view is selected, false otherwise
27413      */
27414     @ViewDebug.ExportedProperty
27415     @InspectableProperty(hasAttributeId = false)
isSelected()27416     public boolean isSelected() {
27417         return (mPrivateFlags & PFLAG_SELECTED) != 0;
27418     }
27419 
27420     /**
27421      * Changes the activated state of this view. A view can be activated or not.
27422      * Note that activation is not the same as selection.  Selection is
27423      * a transient property, representing the view (hierarchy) the user is
27424      * currently interacting with.  Activation is a longer-term state that the
27425      * user can move views in and out of.  For example, in a list view with
27426      * single or multiple selection enabled, the views in the current selection
27427      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
27428      * here.)  The activated state is propagated down to children of the view it
27429      * is set on.
27430      *
27431      * @param activated true if the view must be activated, false otherwise
27432      */
setActivated(boolean activated)27433     public void setActivated(boolean activated) {
27434         //noinspection DoubleNegation
27435         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
27436             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
27437             invalidate(true);
27438             refreshDrawableState();
27439             dispatchSetActivated(activated);
27440         }
27441     }
27442 
27443     /**
27444      * Dispatch setActivated to all of this View's children.
27445      *
27446      * @see #setActivated(boolean)
27447      *
27448      * @param activated The new activated state
27449      */
dispatchSetActivated(boolean activated)27450     protected void dispatchSetActivated(boolean activated) {
27451     }
27452 
27453     /**
27454      * Indicates the activation state of this view.
27455      *
27456      * @return true if the view is activated, false otherwise
27457      */
27458     @ViewDebug.ExportedProperty
27459     @InspectableProperty(hasAttributeId = false)
isActivated()27460     public boolean isActivated() {
27461         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
27462     }
27463 
27464     /**
27465      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
27466      * observer can be used to get notifications when global events, like
27467      * layout, happen.
27468      *
27469      * The returned ViewTreeObserver observer is not guaranteed to remain
27470      * valid for the lifetime of this View. If the caller of this method keeps
27471      * a long-lived reference to ViewTreeObserver, it should always check for
27472      * the return value of {@link ViewTreeObserver#isAlive()}.
27473      *
27474      * @return The ViewTreeObserver for this view's hierarchy.
27475      */
getViewTreeObserver()27476     public ViewTreeObserver getViewTreeObserver() {
27477         if (mAttachInfo != null) {
27478             return mAttachInfo.mTreeObserver;
27479         }
27480         if (mFloatingTreeObserver == null) {
27481             mFloatingTreeObserver = new ViewTreeObserver(mContext);
27482         }
27483         return mFloatingTreeObserver;
27484     }
27485 
27486     /**
27487      * <p>Finds the topmost view in the current view hierarchy.</p>
27488      *
27489      * @return the topmost view containing this view
27490      */
getRootView()27491     public View getRootView() {
27492         if (mAttachInfo != null) {
27493             final View v = mAttachInfo.mRootView;
27494             if (v != null) {
27495                 return v;
27496             }
27497         }
27498 
27499         View parent = this;
27500 
27501         while (parent.mParent instanceof View) {
27502             parent = (View) parent.mParent;
27503         }
27504 
27505         return parent;
27506     }
27507 
27508     /**
27509      * Transforms a motion event from view-local coordinates to on-screen
27510      * coordinates.
27511      *
27512      * @param ev the view-local motion event
27513      * @return false if the transformation could not be applied
27514      * @hide
27515      */
27516     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toGlobalMotionEvent(MotionEvent ev)27517     public boolean toGlobalMotionEvent(MotionEvent ev) {
27518         final AttachInfo info = mAttachInfo;
27519         if (info == null) {
27520             return false;
27521         }
27522 
27523         final Matrix m = info.mTmpMatrix;
27524         m.set(Matrix.IDENTITY_MATRIX);
27525         transformMatrixToGlobal(m);
27526         ev.transform(m);
27527         return true;
27528     }
27529 
27530     /**
27531      * Transforms a motion event from on-screen coordinates to view-local
27532      * coordinates.
27533      *
27534      * @param ev the on-screen motion event
27535      * @return false if the transformation could not be applied
27536      * @hide
27537      */
27538     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toLocalMotionEvent(MotionEvent ev)27539     public boolean toLocalMotionEvent(MotionEvent ev) {
27540         final AttachInfo info = mAttachInfo;
27541         if (info == null) {
27542             return false;
27543         }
27544 
27545         final Matrix m = info.mTmpMatrix;
27546         m.set(Matrix.IDENTITY_MATRIX);
27547         transformMatrixToLocal(m);
27548         ev.transform(m);
27549         return true;
27550     }
27551 
27552     /**
27553      * Modifies the input matrix such that it maps view-local coordinates to
27554      * on-screen coordinates.
27555      *
27556      * @param matrix input matrix to modify
27557      */
transformMatrixToGlobal(@onNull Matrix matrix)27558     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
27559         final ViewParent parent = mParent;
27560         if (parent instanceof View) {
27561             final View vp = (View) parent;
27562             vp.transformMatrixToGlobal(matrix);
27563             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
27564         } else if (parent instanceof ViewRootImpl) {
27565             final ViewRootImpl vr = (ViewRootImpl) parent;
27566             vr.transformMatrixToGlobal(matrix);
27567             matrix.preTranslate(0, -vr.mCurScrollY);
27568         }
27569 
27570         matrix.preTranslate(mLeft, mTop);
27571 
27572         if (!hasIdentityMatrix()) {
27573             matrix.preConcat(getMatrix());
27574         }
27575     }
27576 
27577     /**
27578      * Modifies the input matrix such that it maps on-screen coordinates to
27579      * view-local coordinates.
27580      *
27581      * @param matrix input matrix to modify
27582      */
transformMatrixToLocal(@onNull Matrix matrix)27583     public void transformMatrixToLocal(@NonNull Matrix matrix) {
27584         final ViewParent parent = mParent;
27585         if (parent instanceof View) {
27586             final View vp = (View) parent;
27587             vp.transformMatrixToLocal(matrix);
27588             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
27589         } else if (parent instanceof ViewRootImpl) {
27590             final ViewRootImpl vr = (ViewRootImpl) parent;
27591             vr.transformMatrixToLocal(matrix);
27592             matrix.postTranslate(0, vr.mCurScrollY);
27593         }
27594 
27595         matrix.postTranslate(-mLeft, -mTop);
27596 
27597         if (!hasIdentityMatrix()) {
27598             matrix.postConcat(getInverseMatrix());
27599         }
27600     }
27601 
27602     /**
27603      * Modifiers the input matrix such that it maps root view's coordinates to view-local
27604      * coordinates.
27605      *
27606      * @param matrix input matrix to modify
27607      * @hide
27608      */
transformMatrixRootToLocal(@onNull Matrix matrix)27609     public void transformMatrixRootToLocal(@NonNull Matrix matrix) {
27610         final ViewParent parent = mParent;
27611         if (parent instanceof final View vp) {
27612             vp.transformMatrixRootToLocal(matrix);
27613             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
27614         }
27615         // This method is different from transformMatrixToLocal that it doesn't perform any
27616         // transformation for ViewRootImpl
27617 
27618         matrix.postTranslate(-mLeft, -mTop);
27619 
27620         if (!hasIdentityMatrix()) {
27621             matrix.postConcat(getInverseMatrix());
27622         }
27623     }
27624 
27625     /**
27626      * @hide
27627      */
27628     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
27629             @ViewDebug.IntToString(from = 0, to = "x"),
27630             @ViewDebug.IntToString(from = 1, to = "y")
27631     })
27632     @UnsupportedAppUsage
getLocationOnScreen()27633     public int[] getLocationOnScreen() {
27634         int[] location = new int[2];
27635         getLocationOnScreen(location);
27636         return location;
27637     }
27638 
27639     /**
27640      * Gets the coordinates of this view in the coordinate space of the device
27641      * screen, irrespective of system decorations and whether the system is in
27642      * multi-window mode.
27643      *
27644      * <p>In multi-window mode, the coordinate space encompasses the entire
27645      * device screen, ignoring the bounds of the app window. For example, if the
27646      * view is in the bottom portion of a horizontal split screen, the top edge
27647      * of the screen&mdash;not the top edge of the window&mdash;is the origin
27648      * from which the y-coordinate is calculated.
27649      *
27650      * <p>In multiple-screen scenarios, the coordinate space can span screens.
27651      * For example, if the app is spanning both screens of a dual-screen device
27652      * and the view is located on the right-hand screen, the x-coordinate is
27653      * calculated from the left edge of the left-hand screen to the left edge of
27654      * the view. When the app is restricted to a single screen in a
27655      * multiple-screen environment, the coordinate space includes only the
27656      * screen on which the app is running.
27657      *
27658      * <p>After the method returns, the argument array contains the x and y
27659      * coordinates of the view relative to the view's left and top edges,
27660      * respectively.
27661      *
27662      * @param outLocation A two-element integer array in which the view
27663      *      coordinates are stored. The x-coordinate is at index 0; the
27664      *      y-coordinate, at index 1.
27665      */
getLocationOnScreen(@ize2) int[] outLocation)27666     public void getLocationOnScreen(@Size(2) int[] outLocation) {
27667         getLocationInWindow(outLocation);
27668 
27669         final AttachInfo info = mAttachInfo;
27670         if (info != null) {
27671             outLocation[0] += info.mWindowLeft;
27672             outLocation[1] += info.mWindowTop;
27673             // If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
27674             // applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
27675             info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
27676         }
27677     }
27678 
27679     /**
27680      * Gets the coordinates of this view in the coordinate space of the window
27681      * that contains the view, irrespective of system decorations.
27682      *
27683      * <p>In multi-window mode, the origin of the coordinate space is the
27684      * top left corner of the window that contains the view. In full screen
27685      * mode, the origin is the top left corner of the device screen.
27686      *
27687      * <p>In multiple-screen scenarios, if the app spans multiple screens, the
27688      * coordinate space also spans multiple screens. But if the app is
27689      * restricted to a single screen, the coordinate space includes only the
27690      * screen on which the app is running.
27691      *
27692      * <p>After the method returns, the argument array contains the x and y
27693      * coordinates of the view relative to the view's left and top edges,
27694      * respectively.
27695      *
27696      * @param outLocation A two-element integer array in which the view
27697      *      coordinates are stored. The x-coordinate is at index 0; the
27698      *      y-coordinate, at index 1.
27699      */
getLocationInWindow(@ize2) int[] outLocation)27700     public void getLocationInWindow(@Size(2) int[] outLocation) {
27701         if (outLocation == null || outLocation.length < 2) {
27702             throw new IllegalArgumentException("outLocation must be an array of two integers");
27703         }
27704 
27705         outLocation[0] = 0;
27706         outLocation[1] = 0;
27707 
27708         transformFromViewToWindowSpace(outLocation);
27709     }
27710 
27711     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)27712     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
27713         if (inOutLocation == null || inOutLocation.length < 2) {
27714             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
27715         }
27716 
27717         if (mAttachInfo == null) {
27718             // When the view is not attached to a window, this method does not make sense
27719             inOutLocation[0] = inOutLocation[1] = 0;
27720             return;
27721         }
27722 
27723         float position[] = mAttachInfo.mTmpTransformLocation;
27724         position[0] = inOutLocation[0];
27725         position[1] = inOutLocation[1];
27726 
27727         if (!hasIdentityMatrix()) {
27728             getMatrix().mapPoints(position);
27729         }
27730 
27731         position[0] += mLeft;
27732         position[1] += mTop;
27733 
27734         ViewParent viewParent = mParent;
27735         while (viewParent instanceof View) {
27736             final View view = (View) viewParent;
27737 
27738             position[0] -= view.mScrollX;
27739             position[1] -= view.mScrollY;
27740 
27741             if (!view.hasIdentityMatrix()) {
27742                 view.getMatrix().mapPoints(position);
27743             }
27744 
27745             position[0] += view.mLeft;
27746             position[1] += view.mTop;
27747 
27748             viewParent = view.mParent;
27749          }
27750 
27751         if (viewParent instanceof ViewRootImpl) {
27752             // *cough*
27753             final ViewRootImpl vr = (ViewRootImpl) viewParent;
27754             position[1] -= vr.mCurScrollY;
27755         }
27756 
27757         inOutLocation[0] = Math.round(position[0]);
27758         inOutLocation[1] = Math.round(position[1]);
27759     }
27760 
27761     /**
27762      * @param id the id of the view to be found
27763      * @return the view of the specified id, null if cannot be found
27764      * @hide
27765      */
findViewTraversal(@dRes int id)27766     protected <T extends View> T findViewTraversal(@IdRes int id) {
27767         if (id == mID) {
27768             return (T) this;
27769         }
27770         return null;
27771     }
27772 
27773     /**
27774      * @param tag the tag of the view to be found
27775      * @return the view of specified tag, null if cannot be found
27776      * @hide
27777      */
findViewWithTagTraversal(Object tag)27778     protected <T extends View> T findViewWithTagTraversal(Object tag) {
27779         if (tag != null && tag.equals(mTag)) {
27780             return (T) this;
27781         }
27782         return null;
27783     }
27784 
27785     /**
27786      * @param predicate The predicate to evaluate.
27787      * @param childToSkip If not null, ignores this child during the recursive traversal.
27788      * @return The first view that matches the predicate or null.
27789      * @hide
27790      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)27791     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
27792             View childToSkip) {
27793         if (predicate.test(this)) {
27794             return (T) this;
27795         }
27796         return null;
27797     }
27798 
27799     /**
27800      * Finds the first descendant view with the given ID, the view itself if
27801      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
27802      * (< 0) or there is no matching view in the hierarchy.
27803      * <p>
27804      * <strong>Note:</strong> In most cases -- depending on compiler support --
27805      * the resulting view is automatically cast to the target class type. If
27806      * the target class type is unconstrained, an explicit cast may be
27807      * necessary.
27808      *
27809      * @param id the ID to search for
27810      * @return a view with given ID if found, or {@code null} otherwise
27811      * @see View#requireViewById(int)
27812      */
27813     // Strictly speaking this should be marked as @Nullable but the nullability of the return value
27814     // is deliberately left unspecified as idiomatically correct code can make assumptions either
27815     // way based on local context, e.g. layout specification.
findViewById(@dRes int id)27816     public final <T extends View> T findViewById(@IdRes int id) {
27817         if (id == NO_ID) {
27818             return null;
27819         }
27820         return findViewTraversal(id);
27821     }
27822 
27823     /**
27824      * Finds the first descendant view with the given ID, the view itself if the ID matches
27825      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
27826      * matching view in the hierarchy.
27827      * <p>
27828      * <strong>Note:</strong> In most cases -- depending on compiler support --
27829      * the resulting view is automatically cast to the target class type. If
27830      * the target class type is unconstrained, an explicit cast may be
27831      * necessary.
27832      *
27833      * @param id the ID to search for
27834      * @return a view with given ID
27835      * @see View#findViewById(int)
27836      */
27837     @NonNull
requireViewById(@dRes int id)27838     public final <T extends View> T requireViewById(@IdRes int id) {
27839         T view = findViewById(id);
27840         if (view == null) {
27841             throw new IllegalArgumentException("ID does not reference a View inside this View");
27842         }
27843         return view;
27844     }
27845 
27846     /**
27847      * Performs the traversal to find a view by its unique and stable accessibility id.
27848      *
27849      * <strong>Note:</strong>This method does not stop at the root namespace
27850      * boundary since the user can touch the screen at an arbitrary location
27851      * potentially crossing the root namespace boundary which will send an
27852      * accessibility event to accessibility services and they should be able
27853      * to obtain the event source. Also accessibility ids are guaranteed to be
27854      * unique in the window.
27855      *
27856      * @param accessibilityId The accessibility id.
27857      * @return The found view.
27858      * @hide
27859      */
findViewByAccessibilityIdTraversal(int accessibilityId)27860     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
27861         if (getAccessibilityViewId() == accessibilityId) {
27862             return (T) this;
27863         }
27864         return null;
27865     }
27866 
27867     /**
27868      * Performs the traversal to find a view by its autofill id.
27869      *
27870      * <strong>Note:</strong>This method does not stop at the root namespace
27871      * boundary.
27872      *
27873      * @param autofillId The autofill id.
27874      * @return The found view.
27875      * @hide
27876      */
findViewByAutofillIdTraversal(int autofillId)27877     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
27878         if (getAutofillViewId() == autofillId) {
27879             return (T) this;
27880         }
27881         return null;
27882     }
27883 
27884 
27885     /**
27886      * Performs the traversal to find views that are autofillable.
27887      * Autofillable views are added to the provided list.
27888      *
27889      * <strong>Note:</strong>This method does not stop at the root namespace
27890      * boundary.
27891      *
27892      * @param autofillableViews The output list of autofillable Views.
27893      * @hide
27894      */
findAutofillableViewsByTraversal(@onNull List<View> autofillableViews)27895     public void findAutofillableViewsByTraversal(@NonNull List<View> autofillableViews) {
27896         if (isAutofillable()) {
27897             autofillableViews.add(this);
27898         }
27899     }
27900 
27901     /**
27902      * Look for a child view with the given tag.  If this view has the given
27903      * tag, return this view.
27904      *
27905      * @param tag The tag to search for, using "tag.equals(getTag())".
27906      * @return The View that has the given tag in the hierarchy or null
27907      */
findViewWithTag(Object tag)27908     public final <T extends View> T findViewWithTag(Object tag) {
27909         if (tag == null) {
27910             return null;
27911         }
27912         return findViewWithTagTraversal(tag);
27913     }
27914 
27915     /**
27916      * Look for a child view that matches the specified predicate.
27917      * If this view matches the predicate, return this view.
27918      *
27919      * @param predicate The predicate to evaluate.
27920      * @return The first view that matches the predicate or null.
27921      * @hide
27922      */
findViewByPredicate(Predicate<View> predicate)27923     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
27924         return findViewByPredicateTraversal(predicate, null);
27925     }
27926 
27927     /**
27928      * Look for a child view that matches the specified predicate,
27929      * starting with the specified view and its descendents and then
27930      * recusively searching the ancestors and siblings of that view
27931      * until this view is reached.
27932      *
27933      * This method is useful in cases where the predicate does not match
27934      * a single unique view (perhaps multiple views use the same id)
27935      * and we are trying to find the view that is "closest" in scope to the
27936      * starting view.
27937      *
27938      * @param start The view to start from.
27939      * @param predicate The predicate to evaluate.
27940      * @return The first view that matches the predicate or null.
27941      * @hide
27942      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)27943     public final <T extends View> T findViewByPredicateInsideOut(
27944             View start, Predicate<View> predicate) {
27945         View childToSkip = null;
27946         for (;;) {
27947             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
27948             if (view != null || start == this) {
27949                 return view;
27950             }
27951 
27952             ViewParent parent = start.getParent();
27953             if (parent == null || !(parent instanceof View)) {
27954                 return null;
27955             }
27956 
27957             childToSkip = start;
27958             start = (View) parent;
27959         }
27960     }
27961 
27962     /**
27963      * Sets the identifier for this view. The identifier does not have to be
27964      * unique in this view's hierarchy. The identifier should be a positive
27965      * number.
27966      *
27967      * @see #NO_ID
27968      * @see #getId()
27969      * @see #findViewById(int)
27970      *
27971      * @param id a number used to identify the view
27972      *
27973      * @attr ref android.R.styleable#View_id
27974      */
setId(@dRes int id)27975     public void setId(@IdRes int id) {
27976         mID = id;
27977         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
27978             mID = generateViewId();
27979         }
27980     }
27981 
27982     /**
27983      * {@hide}
27984      *
27985      * @param isRoot true if the view belongs to the root namespace, false
27986      *        otherwise
27987      */
27988     @UnsupportedAppUsage
27989     @TestApi
setIsRootNamespace(boolean isRoot)27990     public void setIsRootNamespace(boolean isRoot) {
27991         if (isRoot) {
27992             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
27993         } else {
27994             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
27995         }
27996     }
27997 
27998     /**
27999      * {@hide}
28000      *
28001      * @return true if the view belongs to the root namespace, false otherwise
28002      */
28003     @UnsupportedAppUsage
isRootNamespace()28004     public boolean isRootNamespace() {
28005         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
28006     }
28007 
28008     /**
28009      * Returns this view's identifier.
28010      *
28011      * @return a positive integer used to identify the view or {@link #NO_ID}
28012      *         if the view has no ID
28013      *
28014      * @see #setId(int)
28015      * @see #findViewById(int)
28016      * @attr ref android.R.styleable#View_id
28017      */
28018     @IdRes
28019     @ViewDebug.CapturedViewProperty
28020     @InspectableProperty
getId()28021     public int getId() {
28022         return mID;
28023     }
28024 
28025     /**
28026      * Get the identifier used for this view by the drawing system.
28027      *
28028      * @see RenderNode#getUniqueId()
28029      * @return A long that uniquely identifies this view's drawing component
28030      */
getUniqueDrawingId()28031     public long getUniqueDrawingId() {
28032         return mRenderNode.getUniqueId();
28033     }
28034 
28035     /**
28036      * Returns this view's tag.
28037      *
28038      * @return the Object stored in this view as a tag, or {@code null} if not
28039      *         set
28040      *
28041      * @see #setTag(Object)
28042      * @see #getTag(int)
28043      */
28044     @ViewDebug.ExportedProperty
28045     @InspectableProperty
getTag()28046     public Object getTag() {
28047         return mTag;
28048     }
28049 
28050     /**
28051      * Sets the tag associated with this view. A tag can be used to mark
28052      * a view in its hierarchy and does not have to be unique within the
28053      * hierarchy. Tags can also be used to store data within a view without
28054      * resorting to another data structure.
28055      *
28056      * @param tag an Object to tag the view with
28057      *
28058      * @see #getTag()
28059      * @see #setTag(int, Object)
28060      */
setTag(final Object tag)28061     public void setTag(final Object tag) {
28062         mTag = tag;
28063     }
28064 
28065     /**
28066      * Returns the tag associated with this view and the specified key.
28067      *
28068      * @param key The key identifying the tag
28069      *
28070      * @return the Object stored in this view as a tag, or {@code null} if not
28071      *         set
28072      *
28073      * @see #setTag(int, Object)
28074      * @see #getTag()
28075      */
getTag(int key)28076     public Object getTag(int key) {
28077         if (mKeyedTags != null) return mKeyedTags.get(key);
28078         return null;
28079     }
28080 
28081     /**
28082      * Sets a tag associated with this view and a key. A tag can be used
28083      * to mark a view in its hierarchy and does not have to be unique within
28084      * the hierarchy. Tags can also be used to store data within a view
28085      * without resorting to another data structure.
28086      *
28087      * The specified key should be an id declared in the resources of the
28088      * application to ensure it is unique (see the <a
28089      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
28090      * Keys identified as belonging to
28091      * the Android framework or not associated with any package will cause
28092      * an {@link IllegalArgumentException} to be thrown.
28093      *
28094      * @param key The key identifying the tag
28095      * @param tag An Object to tag the view with
28096      *
28097      * @throws IllegalArgumentException If they specified key is not valid
28098      *
28099      * @see #setTag(Object)
28100      * @see #getTag(int)
28101      */
setTag(int key, final Object tag)28102     public void setTag(int key, final Object tag) {
28103         // If the package id is 0x00 or 0x01, it's either an undefined package
28104         // or a framework id
28105         if ((key >>> 24) < 2) {
28106             throw new IllegalArgumentException("The key must be an application-specific "
28107                     + "resource id.");
28108         }
28109 
28110         setKeyedTag(key, tag);
28111     }
28112 
28113     /**
28114      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
28115      * framework id.
28116      *
28117      * @hide
28118      */
28119     @UnsupportedAppUsage
setTagInternal(int key, Object tag)28120     public void setTagInternal(int key, Object tag) {
28121         if ((key >>> 24) != 0x1) {
28122             throw new IllegalArgumentException("The key must be a framework-specific "
28123                     + "resource id.");
28124         }
28125 
28126         setKeyedTag(key, tag);
28127     }
28128 
setKeyedTag(int key, Object tag)28129     private void setKeyedTag(int key, Object tag) {
28130         if (mKeyedTags == null) {
28131             mKeyedTags = new SparseArray<Object>(2);
28132         }
28133 
28134         mKeyedTags.put(key, tag);
28135     }
28136 
28137     /**
28138      * Prints information about this view in the log output, with the tag
28139      * {@link #VIEW_LOG_TAG}.
28140      *
28141      * @hide
28142      */
28143     @UnsupportedAppUsage
debug()28144     public void debug() {
28145         debug(0);
28146     }
28147 
28148     /**
28149      * Prints information about this view in the log output, with the tag
28150      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
28151      * indentation defined by the <code>depth</code>.
28152      *
28153      * @param depth the indentation level
28154      *
28155      * @hide
28156      */
28157     @UnsupportedAppUsage
debug(int depth)28158     protected void debug(int depth) {
28159         String output = debugIndent(depth - 1);
28160 
28161         output += "+ " + this;
28162         int id = getId();
28163         if (id != -1) {
28164             output += " (id=" + id + ")";
28165         }
28166         Object tag = getTag();
28167         if (tag != null) {
28168             output += " (tag=" + tag + ")";
28169         }
28170         Log.d(VIEW_LOG_TAG, output);
28171 
28172         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
28173             output = debugIndent(depth) + " FOCUSED";
28174             Log.d(VIEW_LOG_TAG, output);
28175         }
28176 
28177         output = debugIndent(depth);
28178         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
28179                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
28180                 + "} ";
28181         Log.d(VIEW_LOG_TAG, output);
28182 
28183         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
28184                 || mPaddingBottom != 0) {
28185             output = debugIndent(depth);
28186             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
28187                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
28188             Log.d(VIEW_LOG_TAG, output);
28189         }
28190 
28191         output = debugIndent(depth);
28192         output += "mMeasureWidth=" + mMeasuredWidth +
28193                 " mMeasureHeight=" + mMeasuredHeight;
28194         Log.d(VIEW_LOG_TAG, output);
28195 
28196         output = debugIndent(depth);
28197         if (mLayoutParams == null) {
28198             output += "BAD! no layout params";
28199         } else {
28200             output = mLayoutParams.debug(output);
28201         }
28202         Log.d(VIEW_LOG_TAG, output);
28203 
28204         output = debugIndent(depth);
28205         output += "flags={";
28206         output += View.printFlags(mViewFlags);
28207         output += "}";
28208         Log.d(VIEW_LOG_TAG, output);
28209 
28210         output = debugIndent(depth);
28211         output += "privateFlags={";
28212         output += View.printPrivateFlags(mPrivateFlags);
28213         output += "}";
28214         Log.d(VIEW_LOG_TAG, output);
28215     }
28216 
28217     /**
28218      * Creates a string of whitespaces used for indentation.
28219      *
28220      * @param depth the indentation level
28221      * @return a String containing (depth * 2 + 3) * 2 white spaces
28222      *
28223      * @hide
28224      */
debugIndent(int depth)28225     protected static String debugIndent(int depth) {
28226         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
28227         for (int i = 0; i < (depth * 2) + 3; i++) {
28228             spaces.append(' ').append(' ');
28229         }
28230         return spaces.toString();
28231     }
28232 
28233     /**
28234      * <p>Return the offset of the widget's text baseline from the widget's top
28235      * boundary. If this widget does not support baseline alignment, this
28236      * method returns -1. </p>
28237      *
28238      * @return the offset of the baseline within the widget's bounds or -1
28239      *         if baseline alignment is not supported
28240      */
28241     @ViewDebug.ExportedProperty(category = "layout")
28242     @InspectableProperty
getBaseline()28243     public int getBaseline() {
28244         return -1;
28245     }
28246 
28247     /**
28248      * Returns whether the view hierarchy is currently undergoing a layout pass. This
28249      * information is useful to avoid situations such as calling {@link #requestLayout()} during
28250      * a layout pass.
28251      *
28252      * @return whether the view hierarchy is currently undergoing a layout pass
28253      */
isInLayout()28254     public boolean isInLayout() {
28255         ViewRootImpl viewRoot = getViewRootImpl();
28256         return (viewRoot != null && viewRoot.isInLayout());
28257     }
28258 
28259     /** To be used only for debugging purposes. */
printStackStrace(String name)28260     private void printStackStrace(String name) {
28261         Log.d(VIEW_LOG_TAG, "---- ST:" + name);
28262 
28263         StringBuilder sb = new StringBuilder();
28264         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
28265         int startIndex = 1;
28266         int endIndex = Math.min(stackTraceElements.length, startIndex + 20); // max 20 entries.
28267         for (int i = startIndex; i < endIndex; i++) {
28268             StackTraceElement s = stackTraceElements[i];
28269             sb.append(s.getMethodName())
28270                     .append("(")
28271                     .append(s.getFileName())
28272                     .append(":")
28273                     .append(s.getLineNumber())
28274                     .append(") <- ");
28275         }
28276         Log.d(VIEW_LOG_TAG, name + ": " + sb);
28277     }
28278     /**
28279      * Call this when something has changed which has invalidated the
28280      * layout of this view. This will schedule a layout pass of the view
28281      * tree. This should not be called while the view hierarchy is currently in a layout
28282      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
28283      * end of the current layout pass (and then layout will run again) or after the current
28284      * frame is drawn and the next layout occurs.
28285      *
28286      * <p>Subclasses which override this method should call the superclass method to
28287      * handle possible request-during-layout errors correctly.</p>
28288      */
28289     @CallSuper
requestLayout()28290     public void requestLayout() {
28291         if (isRelayoutTracingEnabled()) {
28292             Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
28293                     mTracingStrings.classSimpleName);
28294             printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
28295         }
28296 
28297         if (mMeasureCache != null) mMeasureCache.clear();
28298 
28299         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
28300             // Only trigger request-during-layout logic if this is the view requesting it,
28301             // not the views in its parent hierarchy
28302             ViewRootImpl viewRoot = getViewRootImpl();
28303             if (viewRoot != null && viewRoot.isInLayout()) {
28304                 if (!viewRoot.requestLayoutDuringLayout(this)) {
28305                     return;
28306                 }
28307             }
28308             mAttachInfo.mViewRequestingLayout = this;
28309         }
28310 
28311         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
28312         mPrivateFlags |= PFLAG_INVALIDATED;
28313 
28314         if (mParent != null && !mParent.isLayoutRequested()) {
28315             mParent.requestLayout();
28316         }
28317         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
28318             mAttachInfo.mViewRequestingLayout = null;
28319         }
28320     }
28321 
28322     /**
28323      * Forces this view to be laid out during the next layout pass.
28324      * This method does not call requestLayout() or forceLayout()
28325      * on the parent.
28326      */
forceLayout()28327     public void forceLayout() {
28328         if (mMeasureCache != null) mMeasureCache.clear();
28329 
28330         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
28331         mPrivateFlags |= PFLAG_INVALIDATED;
28332     }
28333 
28334     /**
28335      * <p>
28336      * This is called to find out how big a view should be. The parent
28337      * supplies constraint information in the width and height parameters.
28338      * </p>
28339      *
28340      * <p>
28341      * The actual measurement work of a view is performed in
28342      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
28343      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
28344      * </p>
28345      *
28346      *
28347      * @param widthMeasureSpec Horizontal space requirements as imposed by the
28348      *        parent
28349      * @param heightMeasureSpec Vertical space requirements as imposed by the
28350      *        parent
28351      *
28352      * @see #onMeasure(int, int)
28353      */
measure(int widthMeasureSpec, int heightMeasureSpec)28354     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
28355         boolean optical = isLayoutModeOptical(this);
28356         if (optical != isLayoutModeOptical(mParent)) {
28357             Insets insets = getOpticalInsets();
28358             int oWidth  = insets.left + insets.right;
28359             int oHeight = insets.top  + insets.bottom;
28360             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
28361             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
28362         }
28363 
28364         // Suppress sign extension for the low bytes
28365         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
28366         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
28367 
28368         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
28369 
28370         // Optimize layout by avoiding an extra EXACTLY pass when the view is
28371         // already measured as the correct size. In API 23 and below, this
28372         // extra pass is required to make LinearLayout re-distribute weight.
28373         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
28374                 || heightMeasureSpec != mOldHeightMeasureSpec;
28375         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
28376                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
28377         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
28378                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
28379         final boolean needsLayout = specChanged
28380                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
28381 
28382         if (forceLayout || needsLayout) {
28383             // first clears the measured dimension flag
28384             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
28385 
28386             resolveRtlPropertiesIfNeeded();
28387 
28388             int cacheIndex;
28389             if (sUseMeasureCacheDuringForceLayoutFlagValue) {
28390                 cacheIndex =  mMeasureCache.indexOfKey(key);
28391             } else {
28392                 cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
28393             }
28394 
28395             if (cacheIndex < 0) {
28396                 if (isTraversalTracingEnabled()) {
28397                     Trace.beginSection(mTracingStrings.onMeasure);
28398                 }
28399                 if (android.os.Flags.adpfMeasureDuringInputEventBoost()) {
28400                     final boolean notifyRenderer = hasExpensiveMeasuresDuringInputEvent();
28401                     if (notifyRenderer) {
28402                         getViewRootImpl().notifyRendererOfExpensiveFrame(
28403                                 "ADPF_SendHint: hasExpensiveMeasuresDuringInputEvent");
28404                     }
28405                 }
28406                 // measure ourselves, this should set the measured dimension flag back
28407                 onMeasure(widthMeasureSpec, heightMeasureSpec);
28408                 if (isTraversalTracingEnabled()) {
28409                     Trace.endSection();
28410                 }
28411                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
28412             } else {
28413                 long value = mMeasureCache.valueAt(cacheIndex);
28414                 // Casting a long to int drops the high 32 bits, no mask needed
28415                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
28416                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
28417             }
28418 
28419             // flag not set, setMeasuredDimension() was not invoked, we raise
28420             // an exception to warn the developer
28421             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
28422                 throw new IllegalStateException("View with id " + getId() + ": "
28423                         + getClass().getName() + "#onMeasure() did not set the"
28424                         + " measured dimension by calling"
28425                         + " setMeasuredDimension()");
28426             }
28427 
28428             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
28429         }
28430 
28431         mOldWidthMeasureSpec = widthMeasureSpec;
28432         mOldHeightMeasureSpec = heightMeasureSpec;
28433 
28434         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
28435                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
28436     }
28437 
28438     /**
28439      * <p>
28440      * Measure the view and its content to determine the measured width and the
28441      * measured height. This method is invoked by {@link #measure(int, int)} and
28442      * should be overridden by subclasses to provide accurate and efficient
28443      * measurement of their contents.
28444      * </p>
28445      *
28446      * <p>
28447      * <strong>CONTRACT:</strong> When overriding this method, you
28448      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
28449      * measured width and height of this view. Failure to do so will trigger an
28450      * <code>IllegalStateException</code>, thrown by
28451      * {@link #measure(int, int)}. Calling the superclass'
28452      * {@link #onMeasure(int, int)} is a valid use.
28453      * </p>
28454      *
28455      * <p>
28456      * The base class implementation of measure defaults to the background size,
28457      * unless a larger size is allowed by the MeasureSpec. Subclasses should
28458      * override {@link #onMeasure(int, int)} to provide better measurements of
28459      * their content.
28460      * </p>
28461      *
28462      * <p>
28463      * If this method is overridden, it is the subclass's responsibility to make
28464      * sure the measured height and width are at least the view's minimum height
28465      * and width ({@link #getSuggestedMinimumHeight()} and
28466      * {@link #getSuggestedMinimumWidth()}).
28467      * </p>
28468      *
28469      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
28470      *                         The requirements are encoded with
28471      *                         {@link android.view.View.MeasureSpec}.
28472      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
28473      *                         The requirements are encoded with
28474      *                         {@link android.view.View.MeasureSpec}.
28475      *
28476      * @see #getMeasuredWidth()
28477      * @see #getMeasuredHeight()
28478      * @see #setMeasuredDimension(int, int)
28479      * @see #getSuggestedMinimumHeight()
28480      * @see #getSuggestedMinimumWidth()
28481      * @see android.view.View.MeasureSpec#getMode(int)
28482      * @see android.view.View.MeasureSpec#getSize(int)
28483      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)28484     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
28485         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
28486                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
28487     }
28488 
28489     /**
28490      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
28491      * measured width and measured height. Failing to do so will trigger an
28492      * exception at measurement time.</p>
28493      *
28494      * @param measuredWidth The measured width of this view.  May be a complex
28495      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28496      * {@link #MEASURED_STATE_TOO_SMALL}.
28497      * @param measuredHeight The measured height of this view.  May be a complex
28498      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28499      * {@link #MEASURED_STATE_TOO_SMALL}.
28500      */
setMeasuredDimension(int measuredWidth, int measuredHeight)28501     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
28502         boolean optical = isLayoutModeOptical(this);
28503         if (optical != isLayoutModeOptical(mParent)) {
28504             Insets insets = getOpticalInsets();
28505             int opticalWidth  = insets.left + insets.right;
28506             int opticalHeight = insets.top  + insets.bottom;
28507 
28508             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
28509             measuredHeight += optical ? opticalHeight : -opticalHeight;
28510         }
28511         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
28512     }
28513 
28514     /**
28515      * Sets the measured dimension without extra processing for things like optical bounds.
28516      * Useful for reapplying consistent values that have already been cooked with adjustments
28517      * for optical bounds, etc. such as those from the measurement cache.
28518      *
28519      * @param measuredWidth The measured width of this view.  May be a complex
28520      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28521      * {@link #MEASURED_STATE_TOO_SMALL}.
28522      * @param measuredHeight The measured height of this view.  May be a complex
28523      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
28524      * {@link #MEASURED_STATE_TOO_SMALL}.
28525      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)28526     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
28527         mMeasuredWidth = measuredWidth;
28528         mMeasuredHeight = measuredHeight;
28529 
28530         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
28531     }
28532 
28533     /**
28534      * Merge two states as returned by {@link #getMeasuredState()}.
28535      * @param curState The current state as returned from a view or the result
28536      * of combining multiple views.
28537      * @param newState The new view state to combine.
28538      * @return Returns a new integer reflecting the combination of the two
28539      * states.
28540      */
combineMeasuredStates(int curState, int newState)28541     public static int combineMeasuredStates(int curState, int newState) {
28542         return curState | newState;
28543     }
28544 
28545     /**
28546      * Version of {@link #resolveSizeAndState(int, int, int)}
28547      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
28548      */
resolveSize(int size, int measureSpec)28549     public static int resolveSize(int size, int measureSpec) {
28550         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
28551     }
28552 
28553     /**
28554      * Utility to reconcile a desired size and state, with constraints imposed
28555      * by a MeasureSpec. Will take the desired size, unless a different size
28556      * is imposed by the constraints. The returned value is a compound integer,
28557      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
28558      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
28559      * resulting size is smaller than the size the view wants to be.
28560      *
28561      * @param size How big the view wants to be.
28562      * @param measureSpec Constraints imposed by the parent.
28563      * @param childMeasuredState Size information bit mask for the view's
28564      *                           children.
28565      * @return Size information bit mask as defined by
28566      *         {@link #MEASURED_SIZE_MASK} and
28567      *         {@link #MEASURED_STATE_TOO_SMALL}.
28568      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)28569     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
28570         final int specMode = MeasureSpec.getMode(measureSpec);
28571         final int specSize = MeasureSpec.getSize(measureSpec);
28572         final int result;
28573         switch (specMode) {
28574             case MeasureSpec.AT_MOST:
28575                 if (specSize < size) {
28576                     result = specSize | MEASURED_STATE_TOO_SMALL;
28577                 } else {
28578                     result = size;
28579                 }
28580                 break;
28581             case MeasureSpec.EXACTLY:
28582                 result = specSize;
28583                 break;
28584             case MeasureSpec.UNSPECIFIED:
28585             default:
28586                 result = size;
28587         }
28588         return result | (childMeasuredState & MEASURED_STATE_MASK);
28589     }
28590 
28591     /**
28592      * Utility to return a default size. Uses the supplied size if the
28593      * MeasureSpec imposed no constraints. Will get larger if allowed
28594      * by the MeasureSpec.
28595      *
28596      * @param size Default size for this view
28597      * @param measureSpec Constraints imposed by the parent
28598      * @return The size this view should be.
28599      */
getDefaultSize(int size, int measureSpec)28600     public static int getDefaultSize(int size, int measureSpec) {
28601         int result = size;
28602         int specMode = MeasureSpec.getMode(measureSpec);
28603         int specSize = MeasureSpec.getSize(measureSpec);
28604 
28605         switch (specMode) {
28606         case MeasureSpec.UNSPECIFIED:
28607             result = size;
28608             break;
28609         case MeasureSpec.AT_MOST:
28610         case MeasureSpec.EXACTLY:
28611             result = specSize;
28612             break;
28613         }
28614         return result;
28615     }
28616 
28617     /**
28618      * Returns the suggested minimum height that the view should use. This
28619      * returns the maximum of the view's minimum height
28620      * and the background's minimum height
28621      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
28622      * <p>
28623      * When being used in {@link #onMeasure(int, int)}, the caller should still
28624      * ensure the returned height is within the requirements of the parent.
28625      *
28626      * @return The suggested minimum height of the view.
28627      */
getSuggestedMinimumHeight()28628     protected int getSuggestedMinimumHeight() {
28629         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
28630 
28631     }
28632 
28633     /**
28634      * Returns the suggested minimum width that the view should use. This
28635      * returns the maximum of the view's minimum width
28636      * and the background's minimum width
28637      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
28638      * <p>
28639      * When being used in {@link #onMeasure(int, int)}, the caller should still
28640      * ensure the returned width is within the requirements of the parent.
28641      *
28642      * @return The suggested minimum width of the view.
28643      */
getSuggestedMinimumWidth()28644     protected int getSuggestedMinimumWidth() {
28645         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
28646     }
28647 
28648     /**
28649      * Returns the minimum height of the view.
28650      *
28651      * @return the minimum height the view will try to be, in pixels
28652      *
28653      * @see #setMinimumHeight(int)
28654      *
28655      * @attr ref android.R.styleable#View_minHeight
28656      */
28657     @InspectableProperty(name = "minHeight")
getMinimumHeight()28658     public int getMinimumHeight() {
28659         return mMinHeight;
28660     }
28661 
28662     /**
28663      * Sets the minimum height of the view. It is not guaranteed the view will
28664      * be able to achieve this minimum height (for example, if its parent layout
28665      * constrains it with less available height).
28666      *
28667      * @param minHeight The minimum height the view will try to be, in pixels
28668      *
28669      * @see #getMinimumHeight()
28670      *
28671      * @attr ref android.R.styleable#View_minHeight
28672      */
28673     @RemotableViewMethod
setMinimumHeight(int minHeight)28674     public void setMinimumHeight(int minHeight) {
28675         mMinHeight = minHeight;
28676         requestLayout();
28677     }
28678 
28679     /**
28680      * Returns the minimum width of the view.
28681      *
28682      * @return the minimum width the view will try to be, in pixels
28683      *
28684      * @see #setMinimumWidth(int)
28685      *
28686      * @attr ref android.R.styleable#View_minWidth
28687      */
28688     @InspectableProperty(name = "minWidth")
getMinimumWidth()28689     public int getMinimumWidth() {
28690         return mMinWidth;
28691     }
28692 
28693     /**
28694      * Sets the minimum width of the view. It is not guaranteed the view will
28695      * be able to achieve this minimum width (for example, if its parent layout
28696      * constrains it with less available width).
28697      *
28698      * @param minWidth The minimum width the view will try to be, in pixels
28699      *
28700      * @see #getMinimumWidth()
28701      *
28702      * @attr ref android.R.styleable#View_minWidth
28703      */
28704     @RemotableViewMethod
setMinimumWidth(int minWidth)28705     public void setMinimumWidth(int minWidth) {
28706         mMinWidth = minWidth;
28707         requestLayout();
28708 
28709     }
28710 
28711     /**
28712      * Get the animation currently associated with this view.
28713      *
28714      * @return The animation that is currently playing or
28715      *         scheduled to play for this view.
28716      */
getAnimation()28717     public Animation getAnimation() {
28718         return mCurrentAnimation;
28719     }
28720 
28721     /**
28722      * Start the specified animation now.
28723      *
28724      * @param animation the animation to start now
28725      */
startAnimation(Animation animation)28726     public void startAnimation(Animation animation) {
28727         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
28728         setAnimation(animation);
28729         invalidateParentCaches();
28730         invalidate(true);
28731     }
28732 
28733     /**
28734      * Cancels any animations for this view.
28735      */
clearAnimation()28736     public void clearAnimation() {
28737         if (mCurrentAnimation != null) {
28738             mCurrentAnimation.detach();
28739         }
28740         mCurrentAnimation = null;
28741         invalidateParentIfNeeded();
28742     }
28743 
28744     /**
28745      * Sets the next animation to play for this view.
28746      * If you want the animation to play immediately, use
28747      * {@link #startAnimation(android.view.animation.Animation)} instead.
28748      * This method provides allows fine-grained
28749      * control over the start time and invalidation, but you
28750      * must make sure that 1) the animation has a start time set, and
28751      * 2) the view's parent (which controls animations on its children)
28752      * will be invalidated when the animation is supposed to
28753      * start.
28754      *
28755      * @param animation The next animation, or null.
28756      */
setAnimation(Animation animation)28757     public void setAnimation(Animation animation) {
28758         mCurrentAnimation = animation;
28759 
28760         if (animation != null) {
28761             // If the screen is off assume the animation start time is now instead of
28762             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
28763             // would cause the animation to start when the screen turns back on
28764             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
28765                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
28766                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
28767             }
28768             animation.reset();
28769         }
28770     }
28771 
28772     /**
28773      * Invoked by a parent ViewGroup to notify the start of the animation
28774      * currently associated with this view. If you override this method,
28775      * always call super.onAnimationStart();
28776      *
28777      * @see #setAnimation(android.view.animation.Animation)
28778      * @see #getAnimation()
28779      */
28780     @CallSuper
onAnimationStart()28781     protected void onAnimationStart() {
28782         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
28783     }
28784 
28785     /**
28786      * Invoked by a parent ViewGroup to notify the end of the animation
28787      * currently associated with this view. If you override this method,
28788      * always call super.onAnimationEnd();
28789      *
28790      * @see #setAnimation(android.view.animation.Animation)
28791      * @see #getAnimation()
28792      */
28793     @CallSuper
onAnimationEnd()28794     protected void onAnimationEnd() {
28795         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
28796     }
28797 
28798     /**
28799      * Invoked if there is a Transform that involves alpha. Subclass that can
28800      * draw themselves with the specified alpha should return true, and then
28801      * respect that alpha when their onDraw() is called. If this returns false
28802      * then the view may be redirected to draw into an offscreen buffer to
28803      * fulfill the request, which will look fine, but may be slower than if the
28804      * subclass handles it internally. The default implementation returns false.
28805      *
28806      * @param alpha The alpha (0..255) to apply to the view's drawing
28807      * @return true if the view can draw with the specified alpha.
28808      */
onSetAlpha(int alpha)28809     protected boolean onSetAlpha(int alpha) {
28810         return false;
28811     }
28812 
28813     /**
28814      * This is used by the ViewRoot to perform an optimization when
28815      * the view hierarchy contains one or several SurfaceView.
28816      * SurfaceView is always considered transparent, but its children are not,
28817      * therefore all View objects remove themselves from the global transparent
28818      * region (passed as a parameter to this function).
28819      *
28820      * @param region The transparent region for this ViewAncestor (window).
28821      *
28822      * @return Returns true if the effective visibility of the view at this
28823      * point is opaque, regardless of the transparent region; returns false
28824      * if it is possible for underlying windows to be seen behind the view.
28825      *
28826      */
gatherTransparentRegion(@ullable Region region)28827     public boolean gatherTransparentRegion(@Nullable Region region) {
28828         final AttachInfo attachInfo = mAttachInfo;
28829         if (region != null && attachInfo != null) {
28830             final int pflags = mPrivateFlags;
28831             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
28832                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
28833                 // remove it from the transparent region.
28834                 final int[] location = attachInfo.mTransparentLocation;
28835                 getLocationInWindow(location);
28836                 // When a view has Z value, then it will be better to leave some area below the view
28837                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
28838                 // the bottom part needs more offset than the left, top and right parts due to the
28839                 // spot light effects.
28840                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
28841                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
28842                         location[0] + mRight - mLeft + shadowOffset,
28843                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
28844             } else {
28845                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
28846                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
28847                     // the background drawable's non-transparent parts from this transparent region.
28848                     applyDrawableToTransparentRegion(mBackground, region);
28849                 }
28850                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
28851                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
28852                     // Similarly, we remove the foreground drawable's non-transparent parts.
28853                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
28854                 }
28855                 if (mDefaultFocusHighlight != null
28856                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
28857                     // Similarly, we remove the default focus highlight's non-transparent parts.
28858                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
28859                 }
28860             }
28861         }
28862         return true;
28863     }
28864 
28865     /**
28866      * Play a sound effect for this view.
28867      *
28868      * <p>The framework will play sound effects for some built in actions, such as
28869      * clicking, but you may wish to play these effects in your widget,
28870      * for instance, for internal navigation.
28871      *
28872      * <p>The sound effect will only be played if sound effects are enabled by the user, and
28873      * {@link #isSoundEffectsEnabled()} is true.
28874      *
28875      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}.
28876      */
playSoundEffect(@oundEffectConstants.SoundEffect int soundConstant)28877     public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
28878         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
28879             return;
28880         }
28881         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
28882     }
28883 
28884     /**
28885      * BZZZTT!!1!
28886      *
28887      * <p>Provide haptic feedback to the user for this view.
28888      *
28889      * <p>The framework will provide haptic feedback for some built in actions,
28890      * such as long presses, but you may wish to provide feedback for your
28891      * own widget.
28892      *
28893      * <p>The feedback will only be performed if
28894      * {@link #isHapticFeedbackEnabled()} is true.
28895      *
28896      * @param feedbackConstant One of the constants defined in
28897      * {@link HapticFeedbackConstants}
28898      */
performHapticFeedback(int feedbackConstant)28899     public boolean performHapticFeedback(int feedbackConstant) {
28900         return performHapticFeedback(feedbackConstant, 0);
28901     }
28902 
28903     /**
28904      * BZZZTT!!1!
28905      *
28906      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
28907      *
28908      * @param feedbackConstant One of the constants defined in
28909      * {@link HapticFeedbackConstants}
28910      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
28911      */
performHapticFeedback(int feedbackConstant, int flags)28912     public boolean performHapticFeedback(int feedbackConstant, int flags) {
28913         if (isPerformHapticFeedbackSuppressed(feedbackConstant, flags)) {
28914             return false;
28915         }
28916 
28917         int privFlags = computeHapticFeedbackPrivateFlags();
28918         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, flags, privFlags);
28919     }
28920 
28921     /**
28922      * <p>Provide haptic feedback to the user for this view.
28923      *
28924      * <p>Call this method (vs {@link #performHapticFeedback(int)}) to specify more details about
28925      * the {@link InputDevice} that caused this haptic feedback. The framework will choose and
28926      * provide a haptic feedback based on these details.
28927      *
28928      * <p>The feedback will only be performed if {@link #isHapticFeedbackEnabled()} is {@code true}.
28929      *
28930      * @param feedbackConstant One of the constants defined in {@link HapticFeedbackConstants}.
28931      * @param inputDeviceId The ID of the {@link InputDevice} that generated the event which
28932      *          triggered this haptic feedback request.
28933      * @param inputSource The input source of the event which triggered this haptic feedback
28934      *          request, defined as {@code InputDevice#SOURCE_*}.
28935      *
28936      * @hide
28937      */
performHapticFeedbackForInputDevice(int feedbackConstant, int inputDeviceId, int inputSource, int flags)28938     public void performHapticFeedbackForInputDevice(int feedbackConstant, int inputDeviceId,
28939             int inputSource, int flags) {
28940         if (isPerformHapticFeedbackSuppressed(feedbackConstant, flags)) {
28941             return;
28942         }
28943 
28944         int privFlags = computeHapticFeedbackPrivateFlags();
28945         mAttachInfo.mRootCallbacks.performHapticFeedbackForInputDevice(
28946                 feedbackConstant, inputDeviceId, inputSource, flags, privFlags);
28947     }
28948 
isPerformHapticFeedbackSuppressed(int feedbackConstant, int flags)28949     private boolean isPerformHapticFeedbackSuppressed(int feedbackConstant, int flags) {
28950         if (feedbackConstant == HapticFeedbackConstants.NO_HAPTICS
28951                 || mAttachInfo == null
28952                 || mAttachInfo.mSession == null) {
28953             return true;
28954         }
28955         //noinspection SimplifiableIfStatement
28956         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
28957                 && !isHapticFeedbackEnabled()) {
28958             return true;
28959         }
28960         return false;
28961     }
28962 
computeHapticFeedbackPrivateFlags()28963     private int computeHapticFeedbackPrivateFlags() {
28964         int privFlags = 0;
28965         if (mAttachInfo.mViewRootImpl != null
28966                 && mAttachInfo.mViewRootImpl.mWindowAttributes.type == TYPE_INPUT_METHOD) {
28967             privFlags = HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS;
28968         }
28969         return privFlags;
28970     }
28971 
28972     /**
28973      * Request that the visibility of the status bar or other screen/window
28974      * decorations be changed.
28975      *
28976      * <p>This method is used to put the over device UI into temporary modes
28977      * where the user's attention is focused more on the application content,
28978      * by dimming or hiding surrounding system affordances.  This is typically
28979      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
28980      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
28981      * to be placed behind the action bar (and with these flags other system
28982      * affordances) so that smooth transitions between hiding and showing them
28983      * can be done.
28984      *
28985      * <p>Two representative examples of the use of system UI visibility is
28986      * implementing a content browsing application (like a magazine reader)
28987      * and a video playing application.
28988      *
28989      * <p>The first code shows a typical implementation of a View in a content
28990      * browsing application.  In this implementation, the application goes
28991      * into a content-oriented mode by hiding the status bar and action bar,
28992      * and putting the navigation elements into lights out mode.  The user can
28993      * then interact with content while in this mode.  Such an application should
28994      * provide an easy way for the user to toggle out of the mode (such as to
28995      * check information in the status bar or access notifications).  In the
28996      * implementation here, this is done simply by tapping on the content.
28997      *
28998      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
28999      *      content}
29000      *
29001      * <p>This second code sample shows a typical implementation of a View
29002      * in a video playing application.  In this situation, while the video is
29003      * playing the application would like to go into a complete full-screen mode,
29004      * to use as much of the display as possible for the video.  When in this state
29005      * the user can not interact with the application; the system intercepts
29006      * touching on the screen to pop the UI out of full screen mode.  See
29007      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
29008      *
29009      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
29010      *      content}
29011      *
29012      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
29013      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
29014      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
29015      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
29016      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
29017      *
29018      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
29019      * instead.
29020      */
29021     @Deprecated
setSystemUiVisibility(int visibility)29022     public void setSystemUiVisibility(int visibility) {
29023         if (visibility != mSystemUiVisibility) {
29024             mSystemUiVisibility = visibility;
29025             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
29026                 mParent.recomputeViewAttributes(this);
29027             }
29028         }
29029     }
29030 
29031     /**
29032      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
29033      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
29034      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
29035      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
29036      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
29037      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
29038      *
29039      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
29040      * instead.
29041      */
29042     @Deprecated
getSystemUiVisibility()29043     public int getSystemUiVisibility() {
29044         return mSystemUiVisibility;
29045     }
29046 
29047     /**
29048      * Returns the current system UI visibility that is currently set for
29049      * the entire window.  This is the combination of the
29050      * {@link #setSystemUiVisibility(int)} values supplied by all of the
29051      * views in the window.
29052      *
29053      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
29054      * instead.
29055      */
29056     @Deprecated
getWindowSystemUiVisibility()29057     public int getWindowSystemUiVisibility() {
29058         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
29059     }
29060 
29061     /**
29062      * Override to find out when the window's requested system UI visibility
29063      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
29064      * This is different from the callbacks received through
29065      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
29066      * in that this is only telling you about the local request of the window,
29067      * not the actual values applied by the system.
29068      *
29069      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
29070      * instead.
29071      */
29072     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)29073     public void onWindowSystemUiVisibilityChanged(int visible) {
29074     }
29075 
29076     /**
29077      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
29078      * the view hierarchy.
29079      *
29080      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
29081      * instead.
29082      */
29083     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)29084     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
29085         onWindowSystemUiVisibilityChanged(visible);
29086     }
29087 
29088     /**
29089      * Set a listener to receive callbacks when the visibility of the system bar changes.
29090      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
29091      *
29092      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
29093      * by setting a {@link OnApplyWindowInsetsListener} on this view.
29094      */
29095     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)29096     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
29097         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
29098         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
29099             mParent.recomputeViewAttributes(this);
29100         }
29101     }
29102 
29103     /**
29104      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
29105      * the view hierarchy.
29106      *
29107      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
29108      * by setting a {@link OnApplyWindowInsetsListener} on this view.
29109      */
29110     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)29111     public void dispatchSystemUiVisibilityChanged(int visibility) {
29112         ListenerInfo li = mListenerInfo;
29113         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
29114             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
29115                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
29116         }
29117     }
29118 
updateLocalSystemUiVisibility(int localValue, int localChanges)29119     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
29120         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
29121         if (val != mSystemUiVisibility) {
29122             setSystemUiVisibility(val);
29123             return true;
29124         }
29125         return false;
29126     }
29127 
29128     /** @hide */
29129     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDisabledSystemUiVisibility(int flags)29130     public void setDisabledSystemUiVisibility(int flags) {
29131         if (mAttachInfo != null) {
29132             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
29133                 mAttachInfo.mDisabledSystemUiVisibility = flags;
29134                 if (mParent != null) {
29135                     mParent.recomputeViewAttributes(this);
29136                 }
29137             }
29138         }
29139     }
29140 
29141     /**
29142      * This needs to be a better API before it is exposed. For now, only the root view will get
29143      * notified.
29144      * @hide
29145      */
onSystemBarAppearanceChanged(@indowInsetsController.Appearance int appearance)29146     public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
29147     }
29148 
29149     /**
29150      * Creates an image that the system displays during the drag and drop
29151      * operation. This is called a &quot;drag shadow&quot;. The default implementation
29152      * for a DragShadowBuilder based on a View returns an image that has exactly the same
29153      * appearance as the given View. The default also positions the center of the drag shadow
29154      * directly under the touch point. If no View is provided (the constructor with no parameters
29155      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
29156      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
29157      * default is an invisible drag shadow.
29158      * <p>
29159      * You are not required to use the View you provide to the constructor as the basis of the
29160      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
29161      * anything you want as the drag shadow.
29162      * </p>
29163      * <p>
29164      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
29165      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
29166      *  size and position of the drag shadow. It uses this data to construct a
29167      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
29168      *  so that your application can draw the shadow image in the Canvas.
29169      * </p>
29170      *
29171      * <div class="special reference">
29172      * <h3>Developer Guides</h3>
29173      * <p>For a guide to implementing drag and drop features, read the
29174      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
29175      * </div>
29176      */
29177     public static class DragShadowBuilder {
29178         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
29179         private final WeakReference<View> mView;
29180 
29181         /**
29182          * Constructs a shadow image builder based on a View. By default, the resulting drag
29183          * shadow will have the same appearance and dimensions as the View, with the touch point
29184          * over the center of the View.
29185          * @param view A View. Any View in scope can be used.
29186          */
DragShadowBuilder(View view)29187         public DragShadowBuilder(View view) {
29188             mView = new WeakReference<View>(view);
29189         }
29190 
29191         /**
29192          * Construct a shadow builder object with no associated View.  This
29193          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
29194          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
29195          * to supply the drag shadow's dimensions and appearance without
29196          * reference to any View object.
29197          */
DragShadowBuilder()29198         public DragShadowBuilder() {
29199             mView = new WeakReference<View>(null);
29200         }
29201 
29202         /**
29203          * Returns the View object that had been passed to the
29204          * {@link #DragShadowBuilder(View)}
29205          * constructor.  If that View parameter was {@code null} or if the
29206          * {@link #DragShadowBuilder()}
29207          * constructor was used to instantiate the builder object, this method will return
29208          * null.
29209          *
29210          * @return The View object associate with this builder object.
29211          */
29212         @SuppressWarnings({"JavadocReference"})
getView()29213         final public View getView() {
29214             return mView.get();
29215         }
29216 
29217         /**
29218          * Provides the metrics for the shadow image. These include the dimensions of
29219          * the shadow image, and the point within that shadow that should
29220          * be centered under the touch location while dragging.
29221          * <p>
29222          * The default implementation sets the dimensions of the shadow to be the
29223          * same as the dimensions of the View itself and centers the shadow under
29224          * the touch point.
29225          * </p>
29226          *
29227          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
29228          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
29229          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
29230          * image. Since Android P, the width and height must be positive values.
29231          *
29232          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
29233          * shadow image that should be underneath the touch point during the drag and drop
29234          * operation. Your application must set {@link android.graphics.Point#x} to the
29235          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
29236          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)29237         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
29238             final View view = mView.get();
29239             if (view != null) {
29240                 outShadowSize.set(view.getWidth(), view.getHeight());
29241                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
29242             } else {
29243                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
29244             }
29245         }
29246 
29247         /**
29248          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
29249          * based on the dimensions it received from the
29250          * {@link #onProvideShadowMetrics(Point, Point)} callback.
29251          *
29252          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
29253          */
onDrawShadow(@onNull Canvas canvas)29254         public void onDrawShadow(@NonNull Canvas canvas) {
29255             final View view = mView.get();
29256             if (view != null) {
29257                 view.draw(canvas);
29258             } else {
29259                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
29260             }
29261         }
29262     }
29263 
29264     /**
29265      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
29266      * startDragAndDrop()} for newer platform versions.
29267      */
29268     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)29269     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
29270                                    Object myLocalState, int flags) {
29271         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
29272     }
29273 
29274     /**
29275      * Starts a drag and drop operation. When your application calls this method, it passes a
29276      * {@link android.view.View.DragShadowBuilder} object to the system. The
29277      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
29278      * to get metrics for the drag shadow, and then calls the object's
29279      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
29280      * <p>
29281      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
29282      *  drag events to all the View objects in your application that are currently visible. It does
29283      *  this either by calling the View object's drag listener (an implementation of
29284      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
29285      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
29286      *  Both are passed a {@link android.view.DragEvent} object that has a
29287      *  {@link android.view.DragEvent#getAction()} value of
29288      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
29289      * </p>
29290      * <p>
29291      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
29292      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
29293      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
29294      * to the View the user selected for dragging.
29295      * </p>
29296      * @param data A {@link android.content.ClipData} object pointing to the data to be
29297      * transferred by the drag and drop operation.
29298      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
29299      * drag shadow.
29300      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
29301      * drop operation. When dispatching drag events to views in the same activity this object
29302      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
29303      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
29304      * will return null).
29305      * <p>
29306      * myLocalState is a lightweight mechanism for the sending information from the dragged View
29307      * to the target Views. For example, it can contain flags that differentiate between a
29308      * a copy operation and a move operation.
29309      * </p>
29310      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
29311      * flags, or any combination of the following:
29312      *     <ul>
29313      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
29314      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
29315      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
29316      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
29317      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
29318      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
29319      *         <li>{@link #DRAG_FLAG_ACCESSIBILITY_ACTION}</li>
29320      *     </ul>
29321      * @return {@code true} if the method completes successfully, or
29322      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
29323      * do a drag because of another ongoing operation or some other reasons.
29324      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)29325     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
29326             Object myLocalState, int flags) {
29327         if (ViewDebug.DEBUG_DRAG) {
29328             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
29329         }
29330         if (mAttachInfo == null) {
29331             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
29332             return false;
29333         }
29334         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
29335             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
29336             return false;
29337         }
29338         if ((flags & DRAG_FLAG_GLOBAL) != 0 && ((flags & DRAG_FLAG_GLOBAL_SAME_APPLICATION) != 0)) {
29339             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with both DRAG_FLAG_GLOBAL "
29340                     + "and DRAG_FLAG_GLOBAL_SAME_APPLICATION, the drag will default to "
29341                     + "DRAG_FLAG_GLOBAL_SAME_APPLICATION");
29342             flags &= ~DRAG_FLAG_GLOBAL;
29343         }
29344 
29345         if (data != null) {
29346             if (com.android.window.flags.Flags.delegateUnhandledDrags()) {
29347                 data.prepareToLeaveProcess(
29348                         (flags & (DRAG_FLAG_GLOBAL_SAME_APPLICATION | DRAG_FLAG_GLOBAL)) != 0);
29349                 if ((flags & DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG) != 0) {
29350                     if (!hasActivityPendingIntents(data)) {
29351                         // Reset the flag if there is no launchable activity intent
29352                         flags &= ~DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG;
29353                         Log.w(VIEW_LOG_TAG, "startDragAndDrop called with "
29354                                 + "DRAG_FLAG_START_INTENT_ON_UNHANDLED_DRAG but the clip data "
29355                                 + "contains non-activity PendingIntents");
29356                     }
29357                 }
29358             } else {
29359                 data.prepareToLeaveProcess((flags & DRAG_FLAG_GLOBAL) != 0);
29360             }
29361         }
29362 
29363         Rect bounds = new Rect();
29364         getBoundsOnScreen(bounds, true);
29365 
29366         Point lastTouchPoint = new Point();
29367         mAttachInfo.mViewRootImpl.getLastTouchPoint(lastTouchPoint);
29368         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
29369 
29370         // Skip surface logic since shadows and animation are not required during the a11y drag
29371         final boolean a11yEnabled = AccessibilityManager.getInstance(mContext).isEnabled();
29372         if (a11yEnabled && (flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) != 0) {
29373             try {
29374                 IBinder token = mAttachInfo.mSession.performDrag(
29375                         mAttachInfo.mWindow, flags, null,
29376                         mAttachInfo.mViewRootImpl.getLastTouchSource(),
29377                         mAttachInfo.mViewRootImpl.getLastTouchDeviceId(),
29378                         mAttachInfo.mViewRootImpl.getLastTouchPointerId(),
29379                         0f, 0f, 0f, 0f, data);
29380                 if (ViewDebug.DEBUG_DRAG) {
29381                     Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
29382                 }
29383                 if (token != null) {
29384                     root.setLocalDragState(myLocalState);
29385                     mAttachInfo.mDragToken = token;
29386                     mAttachInfo.mDragData = data;
29387                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
29388                     setAccessibilityDragStarted(true);
29389                 }
29390                 return token != null;
29391             } catch (Exception e) {
29392                 Log.e(VIEW_LOG_TAG, "Unable to initiate a11y drag", e);
29393                 return false;
29394             }
29395         }
29396 
29397         Point shadowSize = new Point();
29398         Point shadowTouchPoint = new Point();
29399         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
29400 
29401         if ((shadowSize.x < 0) || (shadowSize.y < 0)
29402                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
29403             throw new IllegalStateException("Drag shadow dimensions must not be negative");
29404         }
29405         final float overrideInvScale = CompatibilityInfo.getOverrideInvertedScale();
29406         if (overrideInvScale != 1f) {
29407             shadowTouchPoint.x = (int) (shadowTouchPoint.x / overrideInvScale);
29408             shadowTouchPoint.y = (int) (shadowTouchPoint.y / overrideInvScale);
29409         }
29410 
29411         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
29412         // does not accept zero size surface.
29413         if (shadowSize.x == 0  || shadowSize.y == 0) {
29414             if (!sAcceptZeroSizeDragShadow) {
29415                 throw new IllegalStateException("Drag shadow dimensions must be positive");
29416             }
29417             shadowSize.x = 1;
29418             shadowSize.y = 1;
29419         }
29420 
29421         if (ViewDebug.DEBUG_DRAG) {
29422             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
29423                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
29424         }
29425 
29426         final SurfaceControl surfaceControl = new SurfaceControl.Builder()
29427                 .setName("drag surface")
29428                 .setParent(root.getSurfaceControl())
29429                 .setBufferSize(shadowSize.x, shadowSize.y)
29430                 .setFormat(PixelFormat.TRANSLUCENT)
29431                 .setCallsite("View.startDragAndDrop")
29432                 .build();
29433         if (overrideInvScale != 1f) {
29434             final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
29435             transaction.setMatrix(surfaceControl, 1 / overrideInvScale, 0, 0, 1 / overrideInvScale)
29436                     .apply();
29437         }
29438         final Surface surface = new Surface();
29439         surface.copyFrom(surfaceControl);
29440         IBinder token = null;
29441         try {
29442             Trace.traceBegin(TRACE_TAG_VIEW, "startDragAndDrop#drawDragShadow");
29443             final Canvas canvas = isHardwareAccelerated()
29444                     ? surface.lockHardwareCanvas()
29445                     : surface.lockCanvas(null);
29446             try {
29447                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
29448                 shadowBuilder.onDrawShadow(canvas);
29449             } finally {
29450                 surface.unlockCanvasAndPost(canvas);
29451                 Trace.traceEnd(TRACE_TAG_VIEW);
29452             }
29453 
29454             Trace.traceBegin(TRACE_TAG_VIEW, "startDragAndDrop#performDrag");
29455             try {
29456                 token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
29457                         root.getLastTouchSource(), root.getLastTouchDeviceId(),
29458                         root.getLastTouchPointerId(), lastTouchPoint.x, lastTouchPoint.y,
29459                         shadowTouchPoint.x, shadowTouchPoint.y, data);
29460                 if (ViewDebug.DEBUG_DRAG) {
29461                     Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
29462                 }
29463                 if (token != null) {
29464                     if (mAttachInfo.mDragSurface != null) {
29465                         mAttachInfo.mDragSurface.release();
29466                     }
29467                     if (mAttachInfo.mDragData != null) {
29468                         // Clean up previous drag data intents
29469                         View.cleanUpPendingIntents(mAttachInfo.mDragData);
29470                     }
29471                     mAttachInfo.mDragSurface = surface;
29472                     mAttachInfo.mDragToken = token;
29473                     mAttachInfo.mDragData = data;
29474                     // Cache the local state object for delivery with DragEvents
29475                     root.setLocalDragState(myLocalState);
29476                     if (a11yEnabled) {
29477                         // Set for AccessibilityEvents
29478                         mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
29479                     }
29480                 }
29481                 return token != null;
29482             } finally {
29483                 Trace.traceEnd(TRACE_TAG_VIEW);
29484             }
29485         } catch (Exception e) {
29486             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
29487             return false;
29488         } finally {
29489             if (token == null) {
29490                 surface.destroy();
29491             }
29492             surfaceControl.release();
29493         }
29494     }
29495 
29496      /**
29497      * Checks if this clip data has a pending intent that is an activity type.
29498      * @hide
29499      */
hasActivityPendingIntents(ClipData data)29500     static boolean hasActivityPendingIntents(ClipData data) {
29501         final int size = data.getItemCount();
29502         for (int i = 0; i < size; i++) {
29503             final ClipData.Item item = data.getItemAt(i);
29504             if (item.getIntentSender() != null) {
29505                 final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());
29506                 if (pi.isActivity()) {
29507                     return true;
29508                 }
29509             }
29510         }
29511         return false;
29512     }
29513 
29514     /**
29515      * Cleans up all pending intents in the ClipData.
29516      * @hide
29517      */
cleanUpPendingIntents(ClipData data)29518     static void cleanUpPendingIntents(ClipData data) {
29519         final int size = data.getItemCount();
29520         for (int i = 0; i < size; i++) {
29521             final ClipData.Item item = data.getItemAt(i);
29522             if (item.getIntentSender() != null) {
29523                 final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());
29524                 pi.cancel();
29525             }
29526         }
29527     }
29528 
setAccessibilityDragStarted(boolean started)29529     void setAccessibilityDragStarted(boolean started) {
29530         int pflags4 = mPrivateFlags4;
29531         if (started) {
29532             pflags4 |= PFLAG4_DRAG_A11Y_STARTED;
29533         } else {
29534             pflags4 &= ~PFLAG4_DRAG_A11Y_STARTED;
29535         }
29536 
29537         if (pflags4 != mPrivateFlags4) {
29538             mPrivateFlags4 = pflags4;
29539             sendWindowContentChangedAccessibilityEvent(CONTENT_CHANGE_TYPE_UNDEFINED);
29540         }
29541     }
29542 
startedSystemDragForAccessibility()29543     private boolean startedSystemDragForAccessibility() {
29544         return (mPrivateFlags4 & PFLAG4_DRAG_A11Y_STARTED) != 0;
29545     }
29546 
29547     /**
29548      * Cancels an ongoing drag and drop operation.
29549      * <p>
29550      * A {@link android.view.DragEvent} object with
29551      * {@link android.view.DragEvent#getAction()} value of
29552      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
29553      * {@link android.view.DragEvent#getResult()} value of {@code false}
29554      * will be sent to every
29555      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
29556      * even if they are not currently visible.
29557      * </p>
29558      * <p>
29559      * This method can be called on any View in the same window as the View on which
29560      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
29561      * was called.
29562      * </p>
29563      */
cancelDragAndDrop()29564     public final void cancelDragAndDrop() {
29565         if (ViewDebug.DEBUG_DRAG) {
29566             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
29567         }
29568         if (mAttachInfo == null) {
29569             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
29570             return;
29571         }
29572         if (mAttachInfo.mDragToken != null) {
29573             try {
29574                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
29575             } catch (Exception e) {
29576                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
29577             }
29578             mAttachInfo.mDragToken = null;
29579         } else {
29580             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
29581         }
29582     }
29583 
29584     /**
29585      * Updates the drag shadow for the ongoing drag and drop operation.
29586      *
29587      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
29588      * new drag shadow.
29589      */
updateDragShadow(DragShadowBuilder shadowBuilder)29590     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
29591         if (ViewDebug.DEBUG_DRAG) {
29592             Log.d(VIEW_LOG_TAG, "updateDragShadow");
29593         }
29594         if (mAttachInfo == null) {
29595             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
29596             return;
29597         }
29598         if (mAttachInfo.mDragToken != null) {
29599             try {
29600                 Canvas canvas = isHardwareAccelerated()
29601                         ? mAttachInfo.mDragSurface.lockHardwareCanvas()
29602                         : mAttachInfo.mDragSurface.lockCanvas(null);
29603                 try {
29604                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
29605                     shadowBuilder.onDrawShadow(canvas);
29606                 } finally {
29607                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
29608                 }
29609             } catch (Exception e) {
29610                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
29611             }
29612         } else {
29613             Log.e(VIEW_LOG_TAG, "No active drag");
29614         }
29615     }
29616 
29617     /**
29618      * Starts a move from {startX, startY}, the amount of the movement will be the offset
29619      * between {startX, startY} and the new cursor positon.
29620      * @param startX horizontal coordinate where the move started.
29621      * @param startY vertical coordinate where the move started.
29622      * @return whether moving was started successfully.
29623      * @hide
29624      */
startMovingTask(float startX, float startY)29625     public final boolean startMovingTask(float startX, float startY) {
29626         if (ViewDebug.DEBUG_POSITIONING) {
29627             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
29628         }
29629         try {
29630             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
29631         } catch (RemoteException e) {
29632             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
29633         }
29634         return false;
29635     }
29636 
29637     /**
29638      * Finish a window move task.
29639      * @hide
29640      */
finishMovingTask()29641     public void finishMovingTask() {
29642         if (ViewDebug.DEBUG_POSITIONING) {
29643             Log.d(VIEW_LOG_TAG, "finishMovingTask");
29644         }
29645         try {
29646             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
29647         } catch (RemoteException e) {
29648             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
29649         }
29650     }
29651 
29652     /**
29653      * Handles drag events sent by the system following a call to
29654      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
29655      * startDragAndDrop()}.
29656      * <p>
29657      * The system calls this method and passes a {@link DragEvent} object in response to drag and
29658      * drop events. This method can then call {@link DragEvent#getAction()} to determine the state
29659      * of the drag and drop operation.
29660      * <p>
29661      * The default implementation returns {@code false} unless an {@link OnReceiveContentListener}
29662      * has been set for this view (see {@link #setOnReceiveContentListener}), in which case
29663      * the default implementation does the following:
29664      * <ul>
29665      *   <li>Returns {@code true} for an
29666      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
29667      *   <li>Calls {@link #performReceiveContent} for an
29668      *     {@link DragEvent#ACTION_DROP ACTION_DROP} event
29669      *   <li>Returns {@code true} for an {@link DragEvent#ACTION_DROP ACTION_DROP} event if the
29670      *     {@code OnReceiveContentListener} consumed some or all of the content
29671      * </ul>
29672      *
29673      * @param event The {@link DragEvent} object sent by the system. The
29674      *   {@link DragEvent#getAction()} method returns an action type constant that indicates the
29675      *   type of drag event represented by this object.
29676      * @return {@code true} if the method successfully handled the drag event, otherwise
29677      *   {@code false}.
29678      *   <p>
29679      *     The method must return {@code true} in response to an
29680      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} action type to continue to
29681      *     receive drag events for the current drag and drop operation.
29682      *   <p>
29683      *     The method should return {@code true} in response to an
29684      *     {@link DragEvent#ACTION_DROP ACTION_DROP} action type if the dropped data was consumed
29685      *     (at least partially); {@code false}, if none of the data was consumed.
29686      *   <p>
29687      *     For all other events, the return value is {@code false}.
29688      */
onDragEvent(DragEvent event)29689     public boolean onDragEvent(DragEvent event) {
29690         if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
29691             return false;
29692         }
29693         // Accept drag events by default if there's an OnReceiveContentListener set.
29694         if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
29695             return true;
29696         }
29697         if (event.getAction() == DragEvent.ACTION_DROP) {
29698             final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
29699             if (permissions != null) {
29700                 permissions.takeTransient();
29701             }
29702             final ContentInfo payload =
29703                     new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
29704                             .setDragAndDropPermissions(permissions)
29705                             .build();
29706             ContentInfo remainingPayload = performReceiveContent(payload);
29707             // Return true unless none of the payload was consumed.
29708             return remainingPayload != payload;
29709         }
29710         return false;
29711     }
29712 
29713     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)29714     boolean dispatchDragEnterExitInPreN(DragEvent event) {
29715         return callDragEventHandler(event);
29716     }
29717 
29718     /**
29719      * Detects if this View is enabled and has a drag event listener.
29720      * If both are true, then it calls the drag event listener with the
29721      * {@link android.view.DragEvent} it received. If the drag event listener returns
29722      * {@code true}, then dispatchDragEvent() returns {@code true}.
29723      * <p>
29724      * For all other cases, the method calls the
29725      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
29726      * method and returns its result.
29727      * </p>
29728      * <p>
29729      * This ensures that a drag event is always consumed, even if the View does not have a drag
29730      * event listener. However, if the View has a listener and the listener returns true, then
29731      * onDragEvent() is not called.
29732      * </p>
29733      */
dispatchDragEvent(DragEvent event)29734     public boolean dispatchDragEvent(DragEvent event) {
29735         event.mEventHandlerWasCalled = true;
29736         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
29737             event.mAction == DragEvent.ACTION_DROP) {
29738             // About to deliver an event with coordinates to this view. Notify that now this view
29739             // has drag focus. This will send exit/enter events as needed.
29740             getViewRootImpl().setDragFocus(this, event);
29741         }
29742         return callDragEventHandler(event);
29743     }
29744 
callDragEventHandler(DragEvent event)29745     final boolean callDragEventHandler(DragEvent event) {
29746         final boolean result;
29747 
29748         ListenerInfo li = mListenerInfo;
29749         //noinspection SimplifiableIfStatement
29750         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
29751                 && li.mOnDragListener.onDrag(this, event)) {
29752             result = true;
29753         } else {
29754             result = onDragEvent(event);
29755         }
29756 
29757         switch (event.mAction) {
29758             case DragEvent.ACTION_DRAG_STARTED: {
29759                 if (result && li != null && li.mOnDragListener != null) {
29760                     sendWindowContentChangedAccessibilityEvent(
29761                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
29762                 }
29763             } break;
29764             case DragEvent.ACTION_DRAG_ENTERED: {
29765                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
29766                 refreshDrawableState();
29767             } break;
29768             case DragEvent.ACTION_DRAG_EXITED: {
29769                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
29770                 refreshDrawableState();
29771             } break;
29772             case DragEvent.ACTION_DROP: {
29773                 if (result && li != null && (li.mOnDragListener != null
29774                         || li.mOnReceiveContentListener != null)) {
29775                     sendWindowContentChangedAccessibilityEvent(
29776                             AccessibilityEvent.CONTENT_CHANGE_TYPE_DRAG_DROPPED);
29777                 }
29778             } break;
29779             case DragEvent.ACTION_DRAG_ENDED: {
29780                 sendWindowContentChangedAccessibilityEvent(
29781                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
29782                 mPrivateFlags2 &= ~View.DRAG_MASK;
29783                 refreshDrawableState();
29784             } break;
29785         }
29786 
29787         return result;
29788     }
29789 
canAcceptDrag()29790     boolean canAcceptDrag() {
29791         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
29792     }
29793 
sendWindowContentChangedAccessibilityEvent(int changeType)29794     void sendWindowContentChangedAccessibilityEvent(int changeType) {
29795         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
29796             AccessibilityEvent event = AccessibilityEvent.obtain();
29797             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
29798             event.setContentChangeTypes(changeType);
29799             sendAccessibilityEventUnchecked(event);
29800         }
29801     }
29802 
29803     /**
29804      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
29805      * it is ever exposed at all.
29806      * @hide
29807      */
29808     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)29809     public void onCloseSystemDialogs(String reason) {
29810     }
29811 
29812     /**
29813      * Given a Drawable whose bounds have been set to draw into this view,
29814      * update a Region being computed for
29815      * {@link #gatherTransparentRegion(android.graphics.Region)} so
29816      * that any non-transparent parts of the Drawable are removed from the
29817      * given transparent region.
29818      *
29819      * @param dr The Drawable whose transparency is to be applied to the region.
29820      * @param region A Region holding the current transparency information,
29821      * where any parts of the region that are set are considered to be
29822      * transparent.  On return, this region will be modified to have the
29823      * transparency information reduced by the corresponding parts of the
29824      * Drawable that are not transparent.
29825      * {@hide}
29826      */
29827     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
applyDrawableToTransparentRegion(Drawable dr, Region region)29828     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
29829         if (DBG) {
29830             Log.i("View", "Getting transparent region for: " + this);
29831         }
29832         final Region r = dr.getTransparentRegion();
29833         final Rect db = dr.getBounds();
29834         final AttachInfo attachInfo = mAttachInfo;
29835         if (r != null && attachInfo != null) {
29836             final int w = getRight()-getLeft();
29837             final int h = getBottom()-getTop();
29838             if (db.left > 0) {
29839                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
29840                 r.op(0, 0, db.left, h, Region.Op.UNION);
29841             }
29842             if (db.right < w) {
29843                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
29844                 r.op(db.right, 0, w, h, Region.Op.UNION);
29845             }
29846             if (db.top > 0) {
29847                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
29848                 r.op(0, 0, w, db.top, Region.Op.UNION);
29849             }
29850             if (db.bottom < h) {
29851                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
29852                 r.op(0, db.bottom, w, h, Region.Op.UNION);
29853             }
29854             final int[] location = attachInfo.mTransparentLocation;
29855             getLocationInWindow(location);
29856             r.translate(location[0], location[1]);
29857             region.op(r, Region.Op.INTERSECT);
29858         } else {
29859             region.op(db, Region.Op.DIFFERENCE);
29860         }
29861     }
29862 
checkForLongClick(long delay, float x, float y, int classification)29863     private void checkForLongClick(long delay, float x, float y, int classification) {
29864         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
29865             mHasPerformedLongPress = false;
29866 
29867             if (mPendingCheckForLongPress == null) {
29868                 mPendingCheckForLongPress = new CheckForLongPress();
29869             }
29870             mPendingCheckForLongPress.setAnchor(x, y);
29871             mPendingCheckForLongPress.rememberWindowAttachCount();
29872             mPendingCheckForLongPress.rememberPressedState();
29873             mPendingCheckForLongPress.setClassification(classification);
29874             postDelayed(mPendingCheckForLongPress, delay);
29875         }
29876     }
29877 
29878     /**
29879      * Inflate a view from an XML resource.  This convenience method wraps the {@link
29880      * LayoutInflater} class, which provides a full range of options for view inflation.
29881      *
29882      * @param context The Context object for your activity or application.
29883      * @param resource The resource ID to inflate
29884      * @param root A view group that will be the parent.  Used to properly inflate the
29885      * layout_* parameters.
29886      * @see LayoutInflater
29887      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)29888     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
29889         LayoutInflater factory = LayoutInflater.from(context);
29890         return factory.inflate(resource, root);
29891     }
29892 
29893     /**
29894      * Scroll the view with standard behavior for scrolling beyond the normal
29895      * content boundaries. Views that call this method should override
29896      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
29897      * results of an over-scroll operation.
29898      *
29899      * Views can use this method to handle any touch or fling-based scrolling.
29900      *
29901      * @param deltaX Change in X in pixels
29902      * @param deltaY Change in Y in pixels
29903      * @param scrollX Current X scroll value in pixels before applying deltaX
29904      * @param scrollY Current Y scroll value in pixels before applying deltaY
29905      * @param scrollRangeX Maximum content scroll range along the X axis
29906      * @param scrollRangeY Maximum content scroll range along the Y axis
29907      * @param maxOverScrollX Number of pixels to overscroll by in either direction
29908      *          along the X axis.
29909      * @param maxOverScrollY Number of pixels to overscroll by in either direction
29910      *          along the Y axis.
29911      * @param isTouchEvent true if this scroll operation is the result of a touch event.
29912      * @return true if scrolling was clamped to an over-scroll boundary along either
29913      *          axis, false otherwise.
29914      */
29915     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)29916     protected boolean overScrollBy(int deltaX, int deltaY,
29917             int scrollX, int scrollY,
29918             int scrollRangeX, int scrollRangeY,
29919             int maxOverScrollX, int maxOverScrollY,
29920             boolean isTouchEvent) {
29921         final int overScrollMode = mOverScrollMode;
29922         final boolean canScrollHorizontal =
29923                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
29924         final boolean canScrollVertical =
29925                 computeVerticalScrollRange() > computeVerticalScrollExtent();
29926         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
29927                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
29928         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
29929                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
29930 
29931         int newScrollX = scrollX + deltaX;
29932         if (!overScrollHorizontal) {
29933             maxOverScrollX = 0;
29934         }
29935 
29936         int newScrollY = scrollY + deltaY;
29937         if (!overScrollVertical) {
29938             maxOverScrollY = 0;
29939         }
29940 
29941         // Clamp values if at the limits and record
29942         final int left = -maxOverScrollX;
29943         final int right = maxOverScrollX + scrollRangeX;
29944         final int top = -maxOverScrollY;
29945         final int bottom = maxOverScrollY + scrollRangeY;
29946 
29947         boolean clampedX = false;
29948         if (newScrollX > right) {
29949             newScrollX = right;
29950             clampedX = true;
29951         } else if (newScrollX < left) {
29952             newScrollX = left;
29953             clampedX = true;
29954         }
29955 
29956         boolean clampedY = false;
29957         if (newScrollY > bottom) {
29958             newScrollY = bottom;
29959             clampedY = true;
29960         } else if (newScrollY < top) {
29961             newScrollY = top;
29962             clampedY = true;
29963         }
29964 
29965         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
29966 
29967         return clampedX || clampedY;
29968     }
29969 
29970     /**
29971      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
29972      * respond to the results of an over-scroll operation.
29973      *
29974      * @param scrollX New X scroll value in pixels
29975      * @param scrollY New Y scroll value in pixels
29976      * @param clampedX True if scrollX was clamped to an over-scroll boundary
29977      * @param clampedY True if scrollY was clamped to an over-scroll boundary
29978      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)29979     protected void onOverScrolled(int scrollX, int scrollY,
29980             boolean clampedX, boolean clampedY) {
29981         // Intentionally empty.
29982     }
29983 
29984     /**
29985      * Returns the over-scroll mode for this view. The result will be
29986      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
29987      * (allow over-scrolling only if the view content is larger than the container),
29988      * or {@link #OVER_SCROLL_NEVER}.
29989      *
29990      * @return This view's over-scroll mode.
29991      */
29992     @InspectableProperty(enumMapping = {
29993             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
29994             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
29995             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
29996     })
getOverScrollMode()29997     public int getOverScrollMode() {
29998         return mOverScrollMode;
29999     }
30000 
30001     /**
30002      * Set the over-scroll mode for this view. Valid over-scroll modes are
30003      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
30004      * (allow over-scrolling only if the view content is larger than the container),
30005      * or {@link #OVER_SCROLL_NEVER}.
30006      *
30007      * Setting the over-scroll mode of a view will have an effect only if the
30008      * view is capable of scrolling.
30009      *
30010      * @param overScrollMode The new over-scroll mode for this view.
30011      */
setOverScrollMode(int overScrollMode)30012     public void setOverScrollMode(int overScrollMode) {
30013         if (overScrollMode != OVER_SCROLL_ALWAYS &&
30014                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
30015                 overScrollMode != OVER_SCROLL_NEVER) {
30016             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
30017         }
30018         mOverScrollMode = overScrollMode;
30019     }
30020 
30021     /**
30022      * Enable or disable nested scrolling for this view.
30023      *
30024      * <p>If this property is set to true the view will be permitted to initiate nested
30025      * scrolling operations with a compatible parent view in the current hierarchy. If this
30026      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
30027      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
30028      * the nested scroll.</p>
30029      *
30030      * @param enabled true to enable nested scrolling, false to disable
30031      *
30032      * @see #isNestedScrollingEnabled()
30033      */
setNestedScrollingEnabled(boolean enabled)30034     public void setNestedScrollingEnabled(boolean enabled) {
30035         if (enabled) {
30036             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
30037         } else {
30038             stopNestedScroll();
30039             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
30040         }
30041     }
30042 
30043     /**
30044      * Returns true if nested scrolling is enabled for this view.
30045      *
30046      * <p>If nested scrolling is enabled and this View class implementation supports it,
30047      * this view will act as a nested scrolling child view when applicable, forwarding data
30048      * about the scroll operation in progress to a compatible and cooperating nested scrolling
30049      * parent.</p>
30050      *
30051      * @return true if nested scrolling is enabled
30052      *
30053      * @see #setNestedScrollingEnabled(boolean)
30054      */
30055     @InspectableProperty
isNestedScrollingEnabled()30056     public boolean isNestedScrollingEnabled() {
30057         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
30058                 PFLAG3_NESTED_SCROLLING_ENABLED;
30059     }
30060 
30061     /**
30062      * Begin a nestable scroll operation along the given axes.
30063      *
30064      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
30065      *
30066      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
30067      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
30068      * In the case of touch scrolling the nested scroll will be terminated automatically in
30069      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
30070      * In the event of programmatic scrolling the caller must explicitly call
30071      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
30072      *
30073      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
30074      * If it returns false the caller may ignore the rest of this contract until the next scroll.
30075      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
30076      *
30077      * <p>At each incremental step of the scroll the caller should invoke
30078      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
30079      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
30080      * parent at least partially consumed the scroll and the caller should adjust the amount it
30081      * scrolls by.</p>
30082      *
30083      * <p>After applying the remainder of the scroll delta the caller should invoke
30084      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
30085      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
30086      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
30087      * </p>
30088      *
30089      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
30090      *             {@link #SCROLL_AXIS_VERTICAL}.
30091      * @return true if a cooperative parent was found and nested scrolling has been enabled for
30092      *         the current gesture.
30093      *
30094      * @see #stopNestedScroll()
30095      * @see #dispatchNestedPreScroll(int, int, int[], int[])
30096      * @see #dispatchNestedScroll(int, int, int, int, int[])
30097      */
startNestedScroll(int axes)30098     public boolean startNestedScroll(int axes) {
30099         if (hasNestedScrollingParent()) {
30100             // Already in progress
30101             return true;
30102         }
30103         if (isNestedScrollingEnabled()) {
30104             ViewParent p = getParent();
30105             View child = this;
30106             while (p != null) {
30107                 try {
30108                     if (p.onStartNestedScroll(child, this, axes)) {
30109                         mNestedScrollingParent = p;
30110                         p.onNestedScrollAccepted(child, this, axes);
30111                         return true;
30112                     }
30113                 } catch (AbstractMethodError e) {
30114                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
30115                             "method onStartNestedScroll", e);
30116                     // Allow the search upward to continue
30117                 }
30118                 if (p instanceof View) {
30119                     child = (View) p;
30120                 }
30121                 p = p.getParent();
30122             }
30123         }
30124         return false;
30125     }
30126 
30127     /**
30128      * Stop a nested scroll in progress.
30129      *
30130      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
30131      *
30132      * @see #startNestedScroll(int)
30133      */
stopNestedScroll()30134     public void stopNestedScroll() {
30135         if (mNestedScrollingParent != null) {
30136             mNestedScrollingParent.onStopNestedScroll(this);
30137             mNestedScrollingParent = null;
30138         }
30139     }
30140 
30141     /**
30142      * Returns true if this view has a nested scrolling parent.
30143      *
30144      * <p>The presence of a nested scrolling parent indicates that this view has initiated
30145      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
30146      *
30147      * @return whether this view has a nested scrolling parent
30148      */
hasNestedScrollingParent()30149     public boolean hasNestedScrollingParent() {
30150         return mNestedScrollingParent != null;
30151     }
30152 
30153     /**
30154      * Dispatch one step of a nested scroll in progress.
30155      *
30156      * <p>Implementations of views that support nested scrolling should call this to report
30157      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
30158      * is not currently in progress or nested scrolling is not
30159      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
30160      *
30161      * <p>Compatible View implementations should also call
30162      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
30163      * consuming a component of the scroll event themselves.</p>
30164      *
30165      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
30166      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
30167      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
30168      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
30169      * @param offsetInWindow Optional. If not null, on return this will contain the offset
30170      *                       in local view coordinates of this view from before this operation
30171      *                       to after it completes. View implementations may use this to adjust
30172      *                       expected input coordinate tracking.
30173      * @return true if the event was dispatched, false if it could not be dispatched.
30174      * @see #dispatchNestedPreScroll(int, int, int[], int[])
30175      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)30176     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
30177             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
30178         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
30179             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
30180                 int startX = 0;
30181                 int startY = 0;
30182                 if (offsetInWindow != null) {
30183                     getLocationInWindow(offsetInWindow);
30184                     startX = offsetInWindow[0];
30185                     startY = offsetInWindow[1];
30186                 }
30187 
30188                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
30189                         dxUnconsumed, dyUnconsumed);
30190 
30191                 if (offsetInWindow != null) {
30192                     getLocationInWindow(offsetInWindow);
30193                     offsetInWindow[0] -= startX;
30194                     offsetInWindow[1] -= startY;
30195                 }
30196                 return true;
30197             } else if (offsetInWindow != null) {
30198                 // No motion, no dispatch. Keep offsetInWindow up to date.
30199                 offsetInWindow[0] = 0;
30200                 offsetInWindow[1] = 0;
30201             }
30202         }
30203         return false;
30204     }
30205 
30206     /**
30207      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
30208      *
30209      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
30210      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
30211      * scrolling operation to consume some or all of the scroll operation before the child view
30212      * consumes it.</p>
30213      *
30214      * @param dx Horizontal scroll distance in pixels
30215      * @param dy Vertical scroll distance in pixels
30216      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
30217      *                 and consumed[1] the consumed dy.
30218      * @param offsetInWindow Optional. If not null, on return this will contain the offset
30219      *                       in local view coordinates of this view from before this operation
30220      *                       to after it completes. View implementations may use this to adjust
30221      *                       expected input coordinate tracking.
30222      * @return true if the parent consumed some or all of the scroll delta
30223      * @see #dispatchNestedScroll(int, int, int, int, int[])
30224      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)30225     public boolean dispatchNestedPreScroll(int dx, int dy,
30226             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
30227         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
30228             if (dx != 0 || dy != 0) {
30229                 int startX = 0;
30230                 int startY = 0;
30231                 if (offsetInWindow != null) {
30232                     getLocationInWindow(offsetInWindow);
30233                     startX = offsetInWindow[0];
30234                     startY = offsetInWindow[1];
30235                 }
30236 
30237                 if (consumed == null) {
30238                     if (mTempNestedScrollConsumed == null) {
30239                         mTempNestedScrollConsumed = new int[2];
30240                     }
30241                     consumed = mTempNestedScrollConsumed;
30242                 }
30243                 consumed[0] = 0;
30244                 consumed[1] = 0;
30245                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
30246 
30247                 if (offsetInWindow != null) {
30248                     getLocationInWindow(offsetInWindow);
30249                     offsetInWindow[0] -= startX;
30250                     offsetInWindow[1] -= startY;
30251                 }
30252                 return consumed[0] != 0 || consumed[1] != 0;
30253             } else if (offsetInWindow != null) {
30254                 offsetInWindow[0] = 0;
30255                 offsetInWindow[1] = 0;
30256             }
30257         }
30258         return false;
30259     }
30260 
30261     /**
30262      * Dispatch a fling to a nested scrolling parent.
30263      *
30264      * <p>This method should be used to indicate that a nested scrolling child has detected
30265      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
30266      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
30267      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
30268      * along a scrollable axis.</p>
30269      *
30270      * <p>If a nested scrolling child view would normally fling but it is at the edge of
30271      * its own content, it can use this method to delegate the fling to its nested scrolling
30272      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
30273      *
30274      * @param velocityX Horizontal fling velocity in pixels per second
30275      * @param velocityY Vertical fling velocity in pixels per second
30276      * @param consumed true if the child consumed the fling, false otherwise
30277      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
30278      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)30279     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
30280         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
30281             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
30282         }
30283         return false;
30284     }
30285 
30286     /**
30287      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
30288      *
30289      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
30290      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
30291      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
30292      * before the child view consumes it. If this method returns <code>true</code>, a nested
30293      * parent view consumed the fling and this view should not scroll as a result.</p>
30294      *
30295      * <p>For a better user experience, only one view in a nested scrolling chain should consume
30296      * the fling at a time. If a parent view consumed the fling this method will return false.
30297      * Custom view implementations should account for this in two ways:</p>
30298      *
30299      * <ul>
30300      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
30301      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
30302      *     position regardless.</li>
30303      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
30304      *     even to settle back to a valid idle position.</li>
30305      * </ul>
30306      *
30307      * <p>Views should also not offer fling velocities to nested parent views along an axis
30308      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
30309      * should not offer a horizontal fling velocity to its parents since scrolling along that
30310      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
30311      *
30312      * @param velocityX Horizontal fling velocity in pixels per second
30313      * @param velocityY Vertical fling velocity in pixels per second
30314      * @return true if a nested scrolling parent consumed the fling
30315      */
dispatchNestedPreFling(float velocityX, float velocityY)30316     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
30317         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
30318             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
30319         }
30320         return false;
30321     }
30322 
30323     /**
30324      * Gets a scale factor that determines the distance the view should scroll
30325      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
30326      * @return The vertical scroll scale factor.
30327      * @hide
30328      */
30329     @UnsupportedAppUsage
getVerticalScrollFactor()30330     protected float getVerticalScrollFactor() {
30331         if (mVerticalScrollFactor == 0) {
30332             TypedValue outValue = new TypedValue();
30333             if (!mContext.getTheme().resolveAttribute(
30334                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
30335                 throw new IllegalStateException(
30336                         "Expected theme to define listPreferredItemHeight.");
30337             }
30338             mVerticalScrollFactor = outValue.getDimension(
30339                     mContext.getResources().getDisplayMetrics());
30340         }
30341         return mVerticalScrollFactor;
30342     }
30343 
30344     /**
30345      * Gets a scale factor that determines the distance the view should scroll
30346      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
30347      * @return The horizontal scroll scale factor.
30348      * @hide
30349      */
30350     @UnsupportedAppUsage
getHorizontalScrollFactor()30351     protected float getHorizontalScrollFactor() {
30352         // TODO: Should use something else.
30353         return getVerticalScrollFactor();
30354     }
30355 
30356     /**
30357      * Return the value specifying the text direction or policy that was set with
30358      * {@link #setTextDirection(int)}.
30359      *
30360      * @return the defined text direction. It can be one of:
30361      *
30362      * {@link #TEXT_DIRECTION_INHERIT},
30363      * {@link #TEXT_DIRECTION_FIRST_STRONG},
30364      * {@link #TEXT_DIRECTION_ANY_RTL},
30365      * {@link #TEXT_DIRECTION_LTR},
30366      * {@link #TEXT_DIRECTION_RTL},
30367      * {@link #TEXT_DIRECTION_LOCALE},
30368      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
30369      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
30370      *
30371      * @attr ref android.R.styleable#View_textDirection
30372      *
30373      * @hide
30374      */
30375     @ViewDebug.ExportedProperty(category = "text", mapping = {
30376             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
30377             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
30378             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
30379             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
30380             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
30381             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
30382             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
30383             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
30384     })
30385     @InspectableProperty(hasAttributeId = false, enumMapping = {
30386             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
30387             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
30388             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
30389             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
30390             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
30391             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
30392             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
30393             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
30394     })
30395     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextDirection()30396     public int getRawTextDirection() {
30397         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
30398     }
30399 
30400     /**
30401      * Set the text direction.
30402      *
30403      * @param textDirection the direction to set. Should be one of:
30404      *
30405      * {@link #TEXT_DIRECTION_INHERIT},
30406      * {@link #TEXT_DIRECTION_FIRST_STRONG},
30407      * {@link #TEXT_DIRECTION_ANY_RTL},
30408      * {@link #TEXT_DIRECTION_LTR},
30409      * {@link #TEXT_DIRECTION_RTL},
30410      * {@link #TEXT_DIRECTION_LOCALE}
30411      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
30412      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
30413      *
30414      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
30415      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
30416      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
30417      *
30418      * @attr ref android.R.styleable#View_textDirection
30419      */
setTextDirection(int textDirection)30420     public void setTextDirection(int textDirection) {
30421         if (getRawTextDirection() != textDirection) {
30422             // Reset the current text direction and the resolved one
30423             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
30424             resetResolvedTextDirection();
30425             // Set the new text direction
30426             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
30427             // Do resolution
30428             resolveTextDirection();
30429             // Notify change
30430             onRtlPropertiesChanged(getLayoutDirection());
30431             // Refresh
30432             requestLayout();
30433             invalidate(true);
30434         }
30435     }
30436 
30437     /**
30438      * Return the resolved text direction.
30439      *
30440      * @return the resolved text direction. Returns one of:
30441      *
30442      * {@link #TEXT_DIRECTION_FIRST_STRONG},
30443      * {@link #TEXT_DIRECTION_ANY_RTL},
30444      * {@link #TEXT_DIRECTION_LTR},
30445      * {@link #TEXT_DIRECTION_RTL},
30446      * {@link #TEXT_DIRECTION_LOCALE},
30447      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
30448      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
30449      *
30450      * @attr ref android.R.styleable#View_textDirection
30451      */
30452     @ViewDebug.ExportedProperty(category = "text", mapping = {
30453             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
30454             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
30455             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
30456             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
30457             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
30458             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
30459             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
30460             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
30461     })
30462     @InspectableProperty(hasAttributeId = false, enumMapping = {
30463             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
30464             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
30465             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
30466             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
30467             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
30468             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
30469             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
30470     })
getTextDirection()30471     public int getTextDirection() {
30472         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
30473     }
30474 
30475     /**
30476      * Resolve the text direction.
30477      *
30478      * @return true if resolution has been done, false otherwise.
30479      *
30480      * @hide
30481      */
resolveTextDirection()30482     public boolean resolveTextDirection() {
30483         // Reset any previous text direction resolution
30484         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
30485 
30486         if (hasRtlSupport()) {
30487             // Set resolved text direction flag depending on text direction flag
30488             final int textDirection = getRawTextDirection();
30489             switch(textDirection) {
30490                 case TEXT_DIRECTION_INHERIT:
30491                     if (!canResolveTextDirection()) {
30492                         // We cannot do the resolution if there is no parent, so use the default one
30493                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30494                         // Resolution will need to happen again later
30495                         return false;
30496                     }
30497 
30498                     // Parent has not yet resolved, so we still return the default
30499                     try {
30500                         if (!mParent.isTextDirectionResolved()) {
30501                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30502                             // Resolution will need to happen again later
30503                             return false;
30504                         }
30505                     } catch (AbstractMethodError e) {
30506                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30507                                 " does not fully implement ViewParent", e);
30508                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
30509                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30510                         return true;
30511                     }
30512 
30513                     // Set current resolved direction to the same value as the parent's one
30514                     int parentResolvedDirection;
30515                     try {
30516                         parentResolvedDirection = mParent.getTextDirection();
30517                     } catch (AbstractMethodError e) {
30518                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30519                                 " does not fully implement ViewParent", e);
30520                         parentResolvedDirection = TEXT_DIRECTION_LTR;
30521                     }
30522                     switch (parentResolvedDirection) {
30523                         case TEXT_DIRECTION_FIRST_STRONG:
30524                         case TEXT_DIRECTION_ANY_RTL:
30525                         case TEXT_DIRECTION_LTR:
30526                         case TEXT_DIRECTION_RTL:
30527                         case TEXT_DIRECTION_LOCALE:
30528                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
30529                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
30530                             mPrivateFlags2 |=
30531                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
30532                             break;
30533                         default:
30534                             // Default resolved direction is "first strong" heuristic
30535                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30536                     }
30537                     break;
30538                 case TEXT_DIRECTION_FIRST_STRONG:
30539                 case TEXT_DIRECTION_ANY_RTL:
30540                 case TEXT_DIRECTION_LTR:
30541                 case TEXT_DIRECTION_RTL:
30542                 case TEXT_DIRECTION_LOCALE:
30543                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
30544                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
30545                     // Resolved direction is the same as text direction
30546                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
30547                     break;
30548                 default:
30549                     // Default resolved direction is "first strong" heuristic
30550                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30551             }
30552         } else {
30553             // Default resolved direction is "first strong" heuristic
30554             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30555         }
30556 
30557         // Set to resolved
30558         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
30559         return true;
30560     }
30561 
30562     /**
30563      * Check if text direction resolution can be done.
30564      *
30565      * @return true if text direction resolution can be done otherwise return false.
30566      */
canResolveTextDirection()30567     public boolean canResolveTextDirection() {
30568         switch (getRawTextDirection()) {
30569             case TEXT_DIRECTION_INHERIT:
30570                 if (mParent != null) {
30571                     try {
30572                         return mParent.canResolveTextDirection();
30573                     } catch (AbstractMethodError e) {
30574                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30575                                 " does not fully implement ViewParent", e);
30576                     }
30577                 }
30578                 return false;
30579 
30580             default:
30581                 return true;
30582         }
30583     }
30584 
30585     /**
30586      * Reset resolved text direction. Text direction will be resolved during a call to
30587      * {@link #onMeasure(int, int)}.
30588      *
30589      * @hide
30590      */
30591     @TestApi
resetResolvedTextDirection()30592     public void resetResolvedTextDirection() {
30593         // Reset any previous text direction resolution
30594         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
30595         // Set to default value
30596         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
30597     }
30598 
30599     /**
30600      * @return true if text direction is inherited.
30601      *
30602      * @hide
30603      */
isTextDirectionInherited()30604     public boolean isTextDirectionInherited() {
30605         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
30606     }
30607 
30608     /**
30609      * @return true if text direction is resolved.
30610      */
isTextDirectionResolved()30611     public boolean isTextDirectionResolved() {
30612         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
30613     }
30614 
30615     /**
30616      * Return the value specifying the text alignment or policy that was set with
30617      * {@link #setTextAlignment(int)}.
30618      *
30619      * @return the defined text alignment. It can be one of:
30620      *
30621      * {@link #TEXT_ALIGNMENT_INHERIT},
30622      * {@link #TEXT_ALIGNMENT_GRAVITY},
30623      * {@link #TEXT_ALIGNMENT_CENTER},
30624      * {@link #TEXT_ALIGNMENT_TEXT_START},
30625      * {@link #TEXT_ALIGNMENT_TEXT_END},
30626      * {@link #TEXT_ALIGNMENT_VIEW_START},
30627      * {@link #TEXT_ALIGNMENT_VIEW_END}
30628      *
30629      * @attr ref android.R.styleable#View_textAlignment
30630      *
30631      * @hide
30632      */
30633     @ViewDebug.ExportedProperty(category = "text", mapping = {
30634             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
30635             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
30636             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
30637             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
30638             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
30639             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
30640             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
30641     })
30642     @InspectableProperty(hasAttributeId = false, enumMapping = {
30643             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
30644             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
30645             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
30646             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
30647             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
30648             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
30649             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
30650     })
30651     @TextAlignment
30652     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextAlignment()30653     public int getRawTextAlignment() {
30654         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
30655     }
30656 
30657     /**
30658      * Set the text alignment.
30659      *
30660      * @param textAlignment The text alignment to set. Should be one of
30661      *
30662      * {@link #TEXT_ALIGNMENT_INHERIT},
30663      * {@link #TEXT_ALIGNMENT_GRAVITY},
30664      * {@link #TEXT_ALIGNMENT_CENTER},
30665      * {@link #TEXT_ALIGNMENT_TEXT_START},
30666      * {@link #TEXT_ALIGNMENT_TEXT_END},
30667      * {@link #TEXT_ALIGNMENT_VIEW_START},
30668      * {@link #TEXT_ALIGNMENT_VIEW_END}
30669      *
30670      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
30671      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
30672      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
30673      *
30674      * @attr ref android.R.styleable#View_textAlignment
30675      */
setTextAlignment(@extAlignment int textAlignment)30676     public void setTextAlignment(@TextAlignment int textAlignment) {
30677         if (textAlignment != getRawTextAlignment()) {
30678             // Reset the current and resolved text alignment
30679             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
30680             resetResolvedTextAlignment();
30681             // Set the new text alignment
30682             mPrivateFlags2 |=
30683                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
30684             // Do resolution
30685             resolveTextAlignment();
30686             // Notify change
30687             onRtlPropertiesChanged(getLayoutDirection());
30688             // Refresh
30689             requestLayout();
30690             invalidate(true);
30691         }
30692     }
30693 
30694     /**
30695      * Return the resolved text alignment.
30696      *
30697      * @return the resolved text alignment. Returns one of:
30698      *
30699      * {@link #TEXT_ALIGNMENT_GRAVITY},
30700      * {@link #TEXT_ALIGNMENT_CENTER},
30701      * {@link #TEXT_ALIGNMENT_TEXT_START},
30702      * {@link #TEXT_ALIGNMENT_TEXT_END},
30703      * {@link #TEXT_ALIGNMENT_VIEW_START},
30704      * {@link #TEXT_ALIGNMENT_VIEW_END}
30705      *
30706      * @attr ref android.R.styleable#View_textAlignment
30707      */
30708     @ViewDebug.ExportedProperty(category = "text", mapping = {
30709             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
30710             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
30711             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
30712             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
30713             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
30714             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
30715             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
30716     })
30717     @InspectableProperty(enumMapping = {
30718             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
30719             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
30720             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
30721             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
30722             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
30723             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
30724     })
30725     @TextAlignment
getTextAlignment()30726     public int getTextAlignment() {
30727         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
30728                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
30729     }
30730 
30731     /**
30732      * Resolve the text alignment.
30733      *
30734      * @return true if resolution has been done, false otherwise.
30735      *
30736      * @hide
30737      */
resolveTextAlignment()30738     public boolean resolveTextAlignment() {
30739         // Reset any previous text alignment resolution
30740         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
30741 
30742         if (hasRtlSupport()) {
30743             // Set resolved text alignment flag depending on text alignment flag
30744             final int textAlignment = getRawTextAlignment();
30745             switch (textAlignment) {
30746                 case TEXT_ALIGNMENT_INHERIT:
30747                     // Check if we can resolve the text alignment
30748                     if (!canResolveTextAlignment()) {
30749                         // We cannot do the resolution if there is no parent so use the default
30750                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30751                         // Resolution will need to happen again later
30752                         return false;
30753                     }
30754 
30755                     // Parent has not yet resolved, so we still return the default
30756                     try {
30757                         if (!mParent.isTextAlignmentResolved()) {
30758                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30759                             // Resolution will need to happen again later
30760                             return false;
30761                         }
30762                     } catch (AbstractMethodError e) {
30763                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30764                                 " does not fully implement ViewParent", e);
30765                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
30766                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30767                         return true;
30768                     }
30769 
30770                     int parentResolvedTextAlignment;
30771                     try {
30772                         parentResolvedTextAlignment = mParent.getTextAlignment();
30773                     } catch (AbstractMethodError e) {
30774                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30775                                 " does not fully implement ViewParent", e);
30776                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
30777                     }
30778                     switch (parentResolvedTextAlignment) {
30779                         case TEXT_ALIGNMENT_GRAVITY:
30780                         case TEXT_ALIGNMENT_TEXT_START:
30781                         case TEXT_ALIGNMENT_TEXT_END:
30782                         case TEXT_ALIGNMENT_CENTER:
30783                         case TEXT_ALIGNMENT_VIEW_START:
30784                         case TEXT_ALIGNMENT_VIEW_END:
30785                             // Resolved text alignment is the same as the parent resolved
30786                             // text alignment
30787                             mPrivateFlags2 |=
30788                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
30789                             break;
30790                         default:
30791                             // Use default resolved text alignment
30792                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30793                     }
30794                     break;
30795                 case TEXT_ALIGNMENT_GRAVITY:
30796                 case TEXT_ALIGNMENT_TEXT_START:
30797                 case TEXT_ALIGNMENT_TEXT_END:
30798                 case TEXT_ALIGNMENT_CENTER:
30799                 case TEXT_ALIGNMENT_VIEW_START:
30800                 case TEXT_ALIGNMENT_VIEW_END:
30801                     // Resolved text alignment is the same as text alignment
30802                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
30803                     break;
30804                 default:
30805                     // Use default resolved text alignment
30806                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30807             }
30808         } else {
30809             // Use default resolved text alignment
30810             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30811         }
30812 
30813         // Set the resolved
30814         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
30815         return true;
30816     }
30817 
30818     /**
30819      * Check if text alignment resolution can be done.
30820      *
30821      * @return true if text alignment resolution can be done otherwise return false.
30822      */
canResolveTextAlignment()30823     public boolean canResolveTextAlignment() {
30824         switch (getRawTextAlignment()) {
30825             case TEXT_DIRECTION_INHERIT:
30826                 if (mParent != null) {
30827                     try {
30828                         return mParent.canResolveTextAlignment();
30829                     } catch (AbstractMethodError e) {
30830                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
30831                                 " does not fully implement ViewParent", e);
30832                     }
30833                 }
30834                 return false;
30835 
30836             default:
30837                 return true;
30838         }
30839     }
30840 
30841     /**
30842      * Reset resolved text alignment. Text alignment will be resolved during a call to
30843      * {@link #onMeasure(int, int)}.
30844      *
30845      * @hide
30846      */
30847     @TestApi
resetResolvedTextAlignment()30848     public void resetResolvedTextAlignment() {
30849         // Reset any previous text alignment resolution
30850         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
30851         // Set to default
30852         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
30853     }
30854 
30855     /**
30856      * @return true if text alignment is inherited.
30857      *
30858      * @hide
30859      */
isTextAlignmentInherited()30860     public boolean isTextAlignmentInherited() {
30861         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
30862     }
30863 
30864     /**
30865      * @return true if text alignment is resolved.
30866      */
isTextAlignmentResolved()30867     public boolean isTextAlignmentResolved() {
30868         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
30869     }
30870 
30871     /**
30872      * Generate a value suitable for use in {@link #setId(int)}.
30873      * This value will not collide with ID values generated at build time by aapt for R.id.
30874      *
30875      * @return a generated ID value
30876      */
generateViewId()30877     public static int generateViewId() {
30878         for (;;) {
30879             final int result = sNextGeneratedId.get();
30880             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
30881             int newValue = result + 1;
30882             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
30883             if (sNextGeneratedId.compareAndSet(result, newValue)) {
30884                 return result;
30885             }
30886         }
30887     }
30888 
30889     // Note that if the function returns true, it indicates aapt did not generate this id.
30890     // However false value does not indicate that aapt did generated this id.
isViewIdGenerated(int id)30891     private static boolean isViewIdGenerated(int id) {
30892         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
30893     }
30894 
30895     /**
30896      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
30897      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
30898      *                           a normal View or a ViewGroup with
30899      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
30900      * @hide
30901      */
captureTransitioningViews(List<View> transitioningViews)30902     public void captureTransitioningViews(List<View> transitioningViews) {
30903         if (getVisibility() == View.VISIBLE) {
30904             transitioningViews.add(this);
30905         }
30906     }
30907 
30908     /**
30909      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
30910      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
30911      * @hide
30912      */
findNamedViews(Map<String, View> namedElements)30913     public void findNamedViews(Map<String, View> namedElements) {
30914         if (getVisibility() == VISIBLE || mGhostView != null) {
30915             String transitionName = getTransitionName();
30916             if (transitionName != null) {
30917                 namedElements.put(transitionName, this);
30918             }
30919         }
30920     }
30921 
30922     /**
30923      * Resolve the pointer icon that should be used for specified pointer in the motion event.
30924      *
30925      * The default implementation will resolve the pointer icon to one set using
30926      * {@link #setPointerIcon(PointerIcon)} for mouse devices. Subclasses may override this to
30927      * customize the icon for the given pointer.
30928      *
30929      * For example, to always show the PointerIcon.TYPE_HANDWRITING icon for a stylus pointer,
30930      * the event can be resolved in the following way:
30931      * <code><pre>
30932      * &#64;Override
30933      * public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
30934      *     final int toolType = event.getToolType(pointerIndex);
30935      *     if (!event.isFromSource(InputDevice.SOURCE_MOUSE)
30936      *             && event.isFromSource(InputDevice.SOURCE_STYLUS)
30937      *             && (toolType == MotionEvent.TOOL_TYPE_STYLUS
30938      *                     || toolType == MotionEvent.TOOL_TYPE_ERASER)) {
30939      *         // Show this pointer icon only if this pointer is a stylus.
30940      *         return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_HANDWRITING);
30941      *     }
30942      *     // Use the default logic for determining the pointer icon for other non-stylus pointers,
30943      *     // like for the mouse cursor.
30944      *     return super.onResolvePointerIcon(event, pointerIndex);
30945      * }
30946      * </pre></code>
30947      *
30948      * @param event The {@link MotionEvent} that requires a pointer icon to be resolved for one of
30949      *              pointers.
30950      * @param pointerIndex The index of the pointer in {@code event} for which to retrieve the
30951      *     {@link PointerIcon}. This will be between 0 and {@link MotionEvent#getPointerCount()}.
30952      * @return the pointer icon to use for specified pointer, or {@code null} if a pointer icon
30953      *     is not specified and the default icon should be used.
30954      * @see PointerIcon
30955      * @see InputManager#isStylusPointerIconEnabled()
30956      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)30957     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
30958         final float x = event.getX(pointerIndex);
30959         final float y = event.getY(pointerIndex);
30960         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
30961             // Use the default pointer icon.
30962             return null;
30963         }
30964 
30965         // Note: A drawing tablet will have both SOURCE_MOUSE and SOURCE_STYLUS, but it would use
30966         // TOOL_TYPE_STYLUS. For now, treat drawing tablets the same way as a mouse or touchpad.
30967         if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
30968             return mMousePointerIcon;
30969         }
30970 
30971         return null;
30972     }
30973 
30974     /**
30975      * Set the pointer icon to be used for a mouse pointer in the current view.
30976      *
30977      * Passing {@code null} will restore the pointer icon to its default value.
30978      * Note that setting the pointer icon using this method will only set it for events coming from
30979      * a mouse device (i.e. with source {@link InputDevice#SOURCE_MOUSE}). To resolve
30980      * the pointer icon for other device types like styluses, override
30981      * {@link #onResolvePointerIcon(MotionEvent, int)}.
30982      *
30983      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
30984      * @see #onResolvePointerIcon(MotionEvent, int)
30985      * @see PointerIcon
30986      */
setPointerIcon(PointerIcon pointerIcon)30987     public void setPointerIcon(PointerIcon pointerIcon) {
30988         mMousePointerIcon = pointerIcon;
30989         final ViewRootImpl viewRootImpl = getViewRootImpl();
30990         if (viewRootImpl == null) {
30991             return;
30992         }
30993         viewRootImpl.refreshPointerIcon();
30994     }
30995 
30996     /**
30997      * Gets the mouse pointer icon for the current view.
30998      *
30999      * @see #setPointerIcon(PointerIcon)
31000      */
31001     @InspectableProperty
getPointerIcon()31002     public PointerIcon getPointerIcon() {
31003         return mMousePointerIcon;
31004     }
31005 
31006     /**
31007      * Checks pointer capture status.
31008      *
31009      * @return true if the view has pointer capture.
31010      * @see #requestPointerCapture()
31011      * @see #hasPointerCapture()
31012      */
hasPointerCapture()31013     public boolean hasPointerCapture() {
31014         final ViewRootImpl viewRootImpl = getViewRootImpl();
31015         if (viewRootImpl == null) {
31016             return false;
31017         }
31018         return viewRootImpl.hasPointerCapture();
31019     }
31020 
31021     /**
31022      * Requests pointer capture mode.
31023      * <p>
31024      * When the window has pointer capture, the mouse pointer icon will disappear and will not
31025      * change its position. Enabling pointer capture will change the behavior of input devices in
31026      * the following ways:
31027      * <ul>
31028      *     <li>Events from a mouse will be delivered with the source
31029      *     {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
31030      *     available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
31031      *
31032      *     <li>Events from a touchpad or trackpad will be delivered with the source
31033      *     {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
31034      *     on the touchpad will be available through {@link MotionEvent#getX(int)} and
31035      *     {@link MotionEvent#getY(int)}, and their relative movements are stored in
31036      *     {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li>
31037      *
31038      *     <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
31039      * </ul>
31040      * <p>
31041      * When pointer capture changes, connected mouse and trackpad devices may be reconfigured,
31042      * and their properties (such as their sources or motion ranges) may change. Use an
31043      * {@link android.hardware.input.InputManager.InputDeviceListener} to be notified when a device
31044      * changes (which may happen after enabling or disabling pointer capture), and use
31045      * {@link InputDevice#getDevice(int)} to get the updated {@link InputDevice}.
31046      * <p>
31047      * Events captured through pointer capture will be dispatched to
31048      * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
31049      * {@link OnCapturedPointerListener} is set, and otherwise to
31050      * {@link #onCapturedPointerEvent(MotionEvent)}.
31051      * <p>
31052      * If the window already has pointer capture, this call does nothing.
31053      * <p>
31054      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
31055      * automatically when the window loses focus.
31056      *
31057      * @see #releasePointerCapture()
31058      * @see #hasPointerCapture()
31059      * @see #onPointerCaptureChange(boolean)
31060      */
requestPointerCapture()31061     public void requestPointerCapture() {
31062         final ViewRootImpl viewRootImpl = getViewRootImpl();
31063         if (viewRootImpl != null) {
31064             viewRootImpl.requestPointerCapture(true);
31065         }
31066     }
31067 
31068 
31069     /**
31070      * Releases the pointer capture.
31071      * <p>
31072      * If the window does not have pointer capture, this call will do nothing.
31073      * @see #requestPointerCapture()
31074      * @see #hasPointerCapture()
31075      * @see #onPointerCaptureChange(boolean)
31076      */
releasePointerCapture()31077     public void releasePointerCapture() {
31078         final ViewRootImpl viewRootImpl = getViewRootImpl();
31079         if (viewRootImpl != null) {
31080             viewRootImpl.requestPointerCapture(false);
31081         }
31082     }
31083 
31084     /**
31085      * Called when the window has just acquired or lost pointer capture.
31086      *
31087      * @param hasCapture True if the view now has pointerCapture, false otherwise.
31088      */
31089     @CallSuper
onPointerCaptureChange(boolean hasCapture)31090     public void onPointerCaptureChange(boolean hasCapture) {
31091     }
31092 
31093     /**
31094      * @see #onPointerCaptureChange
31095      */
dispatchPointerCaptureChanged(boolean hasCapture)31096     public void dispatchPointerCaptureChanged(boolean hasCapture) {
31097         onPointerCaptureChange(hasCapture);
31098     }
31099 
31100     /**
31101      * Implement this method to handle captured pointer events
31102      *
31103      * @param event The captured pointer event.
31104      * @return True if the event was handled, false otherwise.
31105      * @see #requestPointerCapture()
31106      */
onCapturedPointerEvent(MotionEvent event)31107     public boolean onCapturedPointerEvent(MotionEvent event) {
31108         return false;
31109     }
31110 
31111     /**
31112      * Interface definition for a callback to be invoked when a captured pointer event
31113      * is being dispatched this view. The callback will be invoked before the event is
31114      * given to the view.
31115      */
31116     public interface OnCapturedPointerListener {
31117         /**
31118          * Called when a captured pointer event is dispatched to a view.
31119          * @param view The view this event has been dispatched to.
31120          * @param event The captured event.
31121          * @return True if the listener has consumed the event, false otherwise.
31122          */
onCapturedPointer(View view, MotionEvent event)31123         boolean onCapturedPointer(View view, MotionEvent event);
31124     }
31125 
31126     /**
31127      * Set a listener to receive callbacks when the pointer capture state of a view changes.
31128      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
31129      */
setOnCapturedPointerListener(OnCapturedPointerListener l)31130     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
31131         getListenerInfo().mOnCapturedPointerListener = l;
31132     }
31133 
31134     // Properties
31135     //
31136     /**
31137      * A Property wrapper around the <code>alpha</code> functionality handled by the
31138      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
31139      */
31140     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
31141         @Override
31142         public void setValue(View object, float value) {
31143             object.setAlpha(value);
31144         }
31145 
31146         @Override
31147         public Float get(View object) {
31148             return object.getAlpha();
31149         }
31150     };
31151 
31152     /**
31153      * A Property wrapper around the <code>translationX</code> functionality handled by the
31154      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
31155      */
31156     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
31157         @Override
31158         public void setValue(View object, float value) {
31159             object.setTranslationX(value);
31160         }
31161 
31162                 @Override
31163         public Float get(View object) {
31164             return object.getTranslationX();
31165         }
31166     };
31167 
31168     /**
31169      * A Property wrapper around the <code>translationY</code> functionality handled by the
31170      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
31171      */
31172     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
31173         @Override
31174         public void setValue(View object, float value) {
31175             object.setTranslationY(value);
31176         }
31177 
31178         @Override
31179         public Float get(View object) {
31180             return object.getTranslationY();
31181         }
31182     };
31183 
31184     /**
31185      * A Property wrapper around the <code>translationZ</code> functionality handled by the
31186      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
31187      */
31188     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
31189         @Override
31190         public void setValue(View object, float value) {
31191             object.setTranslationZ(value);
31192         }
31193 
31194         @Override
31195         public Float get(View object) {
31196             return object.getTranslationZ();
31197         }
31198     };
31199 
31200     /**
31201      * A Property wrapper around the <code>x</code> functionality handled by the
31202      * {@link View#setX(float)} and {@link View#getX()} methods.
31203      */
31204     public static final Property<View, Float> X = new FloatProperty<View>("x") {
31205         @Override
31206         public void setValue(View object, float value) {
31207             object.setX(value);
31208         }
31209 
31210         @Override
31211         public Float get(View object) {
31212             return object.getX();
31213         }
31214     };
31215 
31216     /**
31217      * A Property wrapper around the <code>y</code> functionality handled by the
31218      * {@link View#setY(float)} and {@link View#getY()} methods.
31219      */
31220     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
31221         @Override
31222         public void setValue(View object, float value) {
31223             object.setY(value);
31224         }
31225 
31226         @Override
31227         public Float get(View object) {
31228             return object.getY();
31229         }
31230     };
31231 
31232     /**
31233      * A Property wrapper around the <code>z</code> functionality handled by the
31234      * {@link View#setZ(float)} and {@link View#getZ()} methods.
31235      */
31236     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
31237         @Override
31238         public void setValue(View object, float value) {
31239             object.setZ(value);
31240         }
31241 
31242         @Override
31243         public Float get(View object) {
31244             return object.getZ();
31245         }
31246     };
31247 
31248     /**
31249      * A Property wrapper around the <code>rotation</code> functionality handled by the
31250      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
31251      */
31252     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
31253         @Override
31254         public void setValue(View object, float value) {
31255             object.setRotation(value);
31256         }
31257 
31258         @Override
31259         public Float get(View object) {
31260             return object.getRotation();
31261         }
31262     };
31263 
31264     /**
31265      * A Property wrapper around the <code>rotationX</code> functionality handled by the
31266      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
31267      */
31268     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
31269         @Override
31270         public void setValue(View object, float value) {
31271             object.setRotationX(value);
31272         }
31273 
31274         @Override
31275         public Float get(View object) {
31276             return object.getRotationX();
31277         }
31278     };
31279 
31280     /**
31281      * A Property wrapper around the <code>rotationY</code> functionality handled by the
31282      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
31283      */
31284     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
31285         @Override
31286         public void setValue(View object, float value) {
31287             object.setRotationY(value);
31288         }
31289 
31290         @Override
31291         public Float get(View object) {
31292             return object.getRotationY();
31293         }
31294     };
31295 
31296     /**
31297      * A Property wrapper around the <code>scaleX</code> functionality handled by the
31298      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
31299      */
31300     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
31301         @Override
31302         public void setValue(View object, float value) {
31303             object.setScaleX(value);
31304         }
31305 
31306         @Override
31307         public Float get(View object) {
31308             return object.getScaleX();
31309         }
31310     };
31311 
31312     /**
31313      * A Property wrapper around the <code>scaleY</code> functionality handled by the
31314      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
31315      */
31316     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
31317         @Override
31318         public void setValue(View object, float value) {
31319             object.setScaleY(value);
31320         }
31321 
31322         @Override
31323         public Float get(View object) {
31324             return object.getScaleY();
31325         }
31326     };
31327 
31328     /**
31329      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
31330      * Each MeasureSpec represents a requirement for either the width or the height.
31331      * A MeasureSpec is comprised of a size and a mode. There are three possible
31332      * modes:
31333      * <dl>
31334      * <dt>UNSPECIFIED</dt>
31335      * <dd>
31336      * The parent has not imposed any constraint on the child. It can be whatever size
31337      * it wants.
31338      * </dd>
31339      *
31340      * <dt>EXACTLY</dt>
31341      * <dd>
31342      * The parent has determined an exact size for the child. The child is going to be
31343      * given those bounds regardless of how big it wants to be.
31344      * </dd>
31345      *
31346      * <dt>AT_MOST</dt>
31347      * <dd>
31348      * The child can be as large as it wants up to the specified size.
31349      * </dd>
31350      * </dl>
31351      *
31352      * MeasureSpecs are implemented as ints to reduce object allocation. This class
31353      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
31354      */
31355     public static class MeasureSpec {
31356         private static final int MODE_SHIFT = 30;
31357         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
31358 
31359         /** @hide */
31360         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
31361         @Retention(RetentionPolicy.SOURCE)
31362         public @interface MeasureSpecMode {}
31363 
31364         /**
31365          * Measure specification mode: The parent has not imposed any constraint
31366          * on the child. It can be whatever size it wants.
31367          */
31368         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
31369 
31370         /**
31371          * Measure specification mode: The parent has determined an exact size
31372          * for the child. The child is going to be given those bounds regardless
31373          * of how big it wants to be.
31374          */
31375         public static final int EXACTLY     = 1 << MODE_SHIFT;
31376 
31377         /**
31378          * Measure specification mode: The child can be as large as it wants up
31379          * to the specified size.
31380          */
31381         public static final int AT_MOST     = 2 << MODE_SHIFT;
31382 
31383         /**
31384          * Creates a measure specification based on the supplied size and mode.
31385          *
31386          * The mode must always be one of the following:
31387          * <ul>
31388          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
31389          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
31390          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
31391          * </ul>
31392          *
31393          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
31394          * implementation was such that the order of arguments did not matter
31395          * and overflow in either value could impact the resulting MeasureSpec.
31396          * {@link android.widget.RelativeLayout} was affected by this bug.
31397          * Apps targeting API levels greater than 17 will get the fixed, more strict
31398          * behavior.</p>
31399          *
31400          * @param size the size of the measure specification
31401          * @param mode the mode of the measure specification
31402          * @return the measure specification based on size and mode
31403          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)31404         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
31405                                           @MeasureSpecMode int mode) {
31406             return (size & ~MODE_MASK) | (mode & MODE_MASK);
31407         }
31408 
31409         /**
31410          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
31411          * will automatically get a size of 0. Older apps expect this.
31412          *
31413          * @hide internal use only for compatibility with system widgets and older apps
31414          */
31415         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)31416         public static int makeSafeMeasureSpec(int size, int mode) {
31417             return makeMeasureSpec(size, mode);
31418         }
31419 
31420         /**
31421          * Extracts the mode from the supplied measure specification.
31422          *
31423          * @param measureSpec the measure specification to extract the mode from
31424          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
31425          *         {@link android.view.View.MeasureSpec#AT_MOST} or
31426          *         {@link android.view.View.MeasureSpec#EXACTLY}
31427          */
31428         @MeasureSpecMode
getMode(int measureSpec)31429         public static int getMode(int measureSpec) {
31430             //noinspection ResourceType
31431             return (measureSpec & MODE_MASK);
31432         }
31433 
31434         /**
31435          * Extracts the size from the supplied measure specification.
31436          *
31437          * @param measureSpec the measure specification to extract the size from
31438          * @return the size in pixels defined in the supplied measure specification
31439          */
getSize(int measureSpec)31440         public static int getSize(int measureSpec) {
31441             return (measureSpec & ~MODE_MASK);
31442         }
31443 
adjust(int measureSpec, int delta)31444         static int adjust(int measureSpec, int delta) {
31445             final int mode = getMode(measureSpec);
31446             int size = getSize(measureSpec);
31447             if (mode == UNSPECIFIED) {
31448                 // No need to adjust size for UNSPECIFIED mode.
31449                 return makeMeasureSpec(size, UNSPECIFIED);
31450             }
31451             size += delta;
31452             if (size < 0) {
31453                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
31454                         ") spec: " + toString(measureSpec) + " delta: " + delta);
31455                 size = 0;
31456             }
31457             return makeMeasureSpec(size, mode);
31458         }
31459 
31460         /**
31461          * Returns a String representation of the specified measure
31462          * specification.
31463          *
31464          * @param measureSpec the measure specification to convert to a String
31465          * @return a String with the following format: "MeasureSpec: MODE SIZE"
31466          */
toString(int measureSpec)31467         public static String toString(int measureSpec) {
31468             int mode = getMode(measureSpec);
31469             int size = getSize(measureSpec);
31470 
31471             StringBuilder sb = new StringBuilder("MeasureSpec: ");
31472 
31473             if (mode == UNSPECIFIED)
31474                 sb.append("UNSPECIFIED ");
31475             else if (mode == EXACTLY)
31476                 sb.append("EXACTLY ");
31477             else if (mode == AT_MOST)
31478                 sb.append("AT_MOST ");
31479             else
31480                 sb.append(mode).append(" ");
31481 
31482             sb.append(size);
31483             return sb.toString();
31484         }
31485     }
31486 
31487     private final class CheckForLongPress implements Runnable {
31488         private int mOriginalWindowAttachCount;
31489         private float mX;
31490         private float mY;
31491         private boolean mOriginalPressedState;
31492         /**
31493          * The classification of the long click being checked: one of the
31494          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
31495          */
31496         private int mClassification;
31497 
31498         @UnsupportedAppUsage
CheckForLongPress()31499         private CheckForLongPress() {
31500         }
31501 
31502         @Override
run()31503         public void run() {
31504             if ((mOriginalPressedState == isPressed()) && (mParent != null)
31505                     && mOriginalWindowAttachCount == mWindowAttachCount) {
31506                 recordGestureClassification(mClassification);
31507                 if (performLongClick(mX, mY)) {
31508                     mHasPerformedLongPress = true;
31509                 }
31510             }
31511         }
31512 
setAnchor(float x, float y)31513         public void setAnchor(float x, float y) {
31514             mX = x;
31515             mY = y;
31516         }
31517 
rememberWindowAttachCount()31518         public void rememberWindowAttachCount() {
31519             mOriginalWindowAttachCount = mWindowAttachCount;
31520         }
31521 
rememberPressedState()31522         public void rememberPressedState() {
31523             mOriginalPressedState = isPressed();
31524         }
31525 
setClassification(int classification)31526         public void setClassification(int classification) {
31527             mClassification = classification;
31528         }
31529     }
31530 
31531     private final class CheckForTap implements Runnable {
31532         public float x;
31533         public float y;
31534 
31535         @Override
run()31536         public void run() {
31537             mPrivateFlags &= ~PFLAG_PREPRESSED;
31538             setPressed(true, x, y);
31539             final long delay =
31540                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
31541             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
31542         }
31543     }
31544 
31545     private final class PerformClick implements Runnable {
31546         @Override
run()31547         public void run() {
31548             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
31549             performClickInternal();
31550         }
31551     }
31552 
31553     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)31554     private void recordGestureClassification(int classification) {
31555         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
31556             return;
31557         }
31558         // To avoid negatively impacting View performance, the latency and displacement metrics
31559         // are omitted.
31560         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
31561                 classification);
31562     }
31563 
31564     /**
31565      * This method returns a ViewPropertyAnimator object, which can be used to animate
31566      * specific properties on this View.
31567      *
31568      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
31569      */
animate()31570     public ViewPropertyAnimator animate() {
31571         if (mAnimator == null) {
31572             mAnimator = new ViewPropertyAnimator(this);
31573         }
31574         return mAnimator;
31575     }
31576 
31577     /**
31578      * Sets the name of the View to be used to identify Views in Transitions.
31579      * Names should be unique in the View hierarchy.
31580      *
31581      * @param transitionName The name of the View to uniquely identify it for Transitions.
31582      */
setTransitionName(String transitionName)31583     public final void setTransitionName(String transitionName) {
31584         mTransitionName = transitionName;
31585     }
31586 
31587     /**
31588      * Returns the name of the View to be used to identify Views in Transitions.
31589      * Names should be unique in the View hierarchy.
31590      *
31591      * <p>This returns null if the View has not been given a name.</p>
31592      *
31593      * @return The name used of the View to be used to identify Views in Transitions or null
31594      * if no name has been given.
31595      */
31596     @ViewDebug.ExportedProperty
31597     @InspectableProperty
getTransitionName()31598     public String getTransitionName() {
31599         return mTransitionName;
31600     }
31601 
31602     /**
31603      * @hide
31604      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)31605     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
31606         // Do nothing.
31607     }
31608 
31609     /**
31610      * Interface definition for a callback to be invoked when a hardware key event is
31611      * dispatched to this view. The callback will be invoked before the key event is
31612      * given to the view. This is only useful for hardware keyboards; a software input
31613      * method has no obligation to trigger this listener.
31614      */
31615     public interface OnKeyListener {
31616         /**
31617          * Called when a hardware key is dispatched to a view. This allows listeners to
31618          * get a chance to respond before the target view.
31619          * <p>Key presses in software keyboards will generally NOT trigger this method,
31620          * although some may elect to do so in some situations. Do not assume a
31621          * software input method has to be key-based; even if it is, it may use key presses
31622          * in a different way than you expect, so there is no way to reliably catch soft
31623          * input key presses.
31624          *
31625          * @param v The view the key has been dispatched to.
31626          * @param keyCode The code for the physical key that was pressed
31627          * @param event The KeyEvent object containing full information about
31628          *        the event.
31629          * @return True if the listener has consumed the event, false otherwise.
31630          */
onKey(View v, int keyCode, KeyEvent event)31631         boolean onKey(View v, int keyCode, KeyEvent event);
31632     }
31633 
31634     /**
31635      * Interface definition for a callback to be invoked when a hardware key event hasn't
31636      * been handled by the view hierarchy.
31637      */
31638     public interface OnUnhandledKeyEventListener {
31639         /**
31640          * Called when a hardware key is dispatched to a view after being unhandled during normal
31641          * {@link KeyEvent} dispatch.
31642          *
31643          * @param v The view the key has been dispatched to.
31644          * @param event The KeyEvent object containing information about the event.
31645          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
31646          */
onUnhandledKeyEvent(View v, KeyEvent event)31647         boolean onUnhandledKeyEvent(View v, KeyEvent event);
31648     }
31649 
31650     /**
31651      * Interface definition for a callback to be invoked when a touch event is
31652      * dispatched to this view. The callback will be invoked before the touch
31653      * event is given to the view.
31654      */
31655     public interface OnTouchListener {
31656         /**
31657          * Called when a touch event is dispatched to a view. This allows listeners to
31658          * get a chance to respond before the target view.
31659          *
31660          * @param v The view the touch event has been dispatched to.
31661          * @param event The MotionEvent object containing full information about
31662          *        the event.
31663          * @return True if the listener has consumed the event, false otherwise.
31664          */
onTouch(View v, MotionEvent event)31665         boolean onTouch(View v, MotionEvent event);
31666     }
31667 
31668     /**
31669      * Interface definition for a callback to be invoked when a hover event is
31670      * dispatched to this view. The callback will be invoked before the hover
31671      * event is given to the view.
31672      */
31673     public interface OnHoverListener {
31674         /**
31675          * Called when a hover event is dispatched to a view. This allows listeners to
31676          * get a chance to respond before the target view.
31677          *
31678          * @param v The view the hover event has been dispatched to.
31679          * @param event The MotionEvent object containing full information about
31680          *        the event.
31681          * @return True if the listener has consumed the event, false otherwise.
31682          */
onHover(View v, MotionEvent event)31683         boolean onHover(View v, MotionEvent event);
31684     }
31685 
31686     /**
31687      * Interface definition for a callback to be invoked when a generic motion event is
31688      * dispatched to this view. The callback will be invoked before the generic motion
31689      * event is given to the view.
31690      */
31691     public interface OnGenericMotionListener {
31692         /**
31693          * Called when a generic motion event is dispatched to a view. This allows listeners to
31694          * get a chance to respond before the target view.
31695          *
31696          * @param v The view the generic motion event has been dispatched to.
31697          * @param event The MotionEvent object containing full information about
31698          *        the event.
31699          * @return True if the listener has consumed the event, false otherwise.
31700          */
onGenericMotion(View v, MotionEvent event)31701         boolean onGenericMotion(View v, MotionEvent event);
31702     }
31703 
31704     /**
31705      * Interface definition for a callback to be invoked when a view has been clicked and held.
31706      */
31707     public interface OnLongClickListener {
31708         /**
31709          * Called when a view has been clicked and held.
31710          *
31711          * @param v The view that was clicked and held.
31712          *
31713          * @return true if the callback consumed the long click, false otherwise.
31714          */
onLongClick(View v)31715         boolean onLongClick(View v);
31716 
31717         /**
31718          * Returns whether the default {@link HapticFeedbackConstants#LONG_PRESS} haptic feedback
31719          * is performed when this listener has consumed the long click. This method is called
31720          * immediately after {@link #onLongClick} has returned true.
31721          *
31722          * @param v The view that was clicked and held.
31723          * @return true to perform the default {@link HapticFeedbackConstants#LONG_PRESS} haptic
31724          * feedback, or false if the handler manages all haptics itself.
31725          */
onLongClickUseDefaultHapticFeedback(@onNull View v)31726         default boolean onLongClickUseDefaultHapticFeedback(@NonNull View v) {
31727             return true;
31728         }
31729     }
31730 
31731     /**
31732      * Interface definition for a listener that's invoked when a drag event is dispatched to this
31733      * view. The listener is invoked before the view's own
31734      * {@link #onDragEvent(DragEvent)} method. To fall back to the view's
31735      * {@code onDragEvent(DragEvent)} behavior, return {@code false} from the listener method.
31736      *
31737      * <div class="special reference">
31738      *   <h3>Developer Guides</h3>
31739      *   <p>For a guide to implementing drag and drop features, see the
31740      *   <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and drop</a> developer guide.</p>
31741      * </div>
31742      */
31743     public interface OnDragListener {
31744         /**
31745          * Called when a drag event is dispatched to a view. Enables listeners to override the
31746          * base behavior provided by {@link #onDragEvent(DragEvent)}.
31747          *
31748          * @param v The {@code View} that received the drag event.
31749          * @param event The event object for the drag event.
31750          * @return {@code true} if the drag event was handled successfully; {@code false}, if the
31751          *   drag event was not handled. <b>Note:</b> A {@code false} return value triggers the
31752          *   view's {@link #onDragEvent(DragEvent)} handler.
31753          */
onDrag(View v, DragEvent event)31754         boolean onDrag(View v, DragEvent event);
31755     }
31756 
31757     /**
31758      * Interface definition for a callback to be invoked when the focus state of
31759      * a view changed.
31760      */
31761     public interface OnFocusChangeListener {
31762         /**
31763          * Called when the focus state of a view has changed.
31764          *
31765          * @param v The view whose state has changed.
31766          * @param hasFocus The new focus state of v.
31767          */
onFocusChange(View v, boolean hasFocus)31768         void onFocusChange(View v, boolean hasFocus);
31769     }
31770 
31771     /**
31772      * Interface definition for a callback to be invoked when a view is clicked.
31773      */
31774     public interface OnClickListener {
31775         /**
31776          * Called when a view has been clicked.
31777          *
31778          * @param v The view that was clicked.
31779          */
onClick(View v)31780         void onClick(View v);
31781     }
31782 
31783     /**
31784      * Interface definition for a callback to be invoked when a view is context clicked.
31785      */
31786     public interface OnContextClickListener {
31787         /**
31788          * Called when a view is context clicked.
31789          *
31790          * @param v The view that has been context clicked.
31791          * @return true if the callback consumed the context click, false otherwise.
31792          */
onContextClick(View v)31793         boolean onContextClick(View v);
31794     }
31795 
31796     /**
31797      * Interface definition for a callback to be invoked when the context menu
31798      * for this view is being built.
31799      */
31800     public interface OnCreateContextMenuListener {
31801         /**
31802          * Called when the context menu for this view is being built. It is not
31803          * safe to hold onto the menu after this method returns.
31804          *
31805          * @param menu The context menu that is being built
31806          * @param v The view for which the context menu is being built
31807          * @param menuInfo Extra information about the item for which the
31808          *            context menu should be shown. This information will vary
31809          *            depending on the class of v.
31810          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)31811         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
31812     }
31813 
31814     /**
31815      * Interface definition for a callback to be invoked when the status bar changes
31816      * visibility.  This reports <strong>global</strong> changes to the system UI
31817      * state, not what the application is requesting.
31818      *
31819      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
31820      *
31821      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
31822      * by setting a {@link OnApplyWindowInsetsListener} on this view.
31823      */
31824     @Deprecated
31825     public interface OnSystemUiVisibilityChangeListener {
31826         /**
31827          * Called when the status bar changes visibility because of a call to
31828          * {@link View#setSystemUiVisibility(int)}.
31829          *
31830          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
31831          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
31832          * This tells you the <strong>global</strong> state of these UI visibility
31833          * flags, not what your app is currently applying.
31834          */
onSystemUiVisibilityChange(int visibility)31835         public void onSystemUiVisibilityChange(int visibility);
31836     }
31837 
31838     /**
31839      * Interface definition for a callback to be invoked when this view is attached
31840      * or detached from its window.
31841      */
31842     public interface OnAttachStateChangeListener {
31843         /**
31844          * Called when the view is attached to a window.
31845          * @param v The view that was attached
31846          */
onViewAttachedToWindow(@onNull View v)31847         public void onViewAttachedToWindow(@NonNull View v);
31848         /**
31849          * Called when the view is detached from a window.
31850          * @param v The view that was detached
31851          */
onViewDetachedFromWindow(@onNull View v)31852         public void onViewDetachedFromWindow(@NonNull View v);
31853     }
31854 
31855     /**
31856      * Listener for applying window insets on a view in a custom way.
31857      *
31858      * <p>Apps may choose to implement this interface if they want to apply custom policy
31859      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
31860      * is set, its
31861      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
31862      * method will be called instead of the View's own
31863      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
31864      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
31865      * the View's normal behavior as part of its own.</p>
31866      */
31867     public interface OnApplyWindowInsetsListener {
31868         /**
31869          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
31870          * on a View, this listener method will be called instead of the view's own
31871          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
31872          *
31873          * @param v The view applying window insets
31874          * @param insets The insets to apply
31875          * @return The insets supplied, minus any insets that were consumed
31876          */
onApplyWindowInsets(@onNull View v, @NonNull WindowInsets insets)31877         public @NonNull WindowInsets onApplyWindowInsets(@NonNull View v,
31878                 @NonNull WindowInsets insets);
31879     }
31880 
31881     private final class UnsetPressedState implements Runnable {
31882         @Override
run()31883         public void run() {
31884             setPressed(false);
31885         }
31886     }
31887 
31888     /**
31889      * When a view becomes invisible checks if autofill considers the view invisible too. This
31890      * happens after the regular removal operation to make sure the operation is finished by the
31891      * time this is called.
31892      */
31893     private static class VisibilityChangeForAutofillHandler extends Handler {
31894         private final AutofillManager mAfm;
31895         private final View mView;
31896 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)31897         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
31898                 @NonNull View view) {
31899             mAfm = afm;
31900             mView = view;
31901         }
31902 
31903         @Override
handleMessage(Message msg)31904         public void handleMessage(Message msg) {
31905             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
31906         }
31907     }
31908 
31909     /**
31910      * Base class for derived classes that want to save and restore their own
31911      * state in {@link android.view.View#onSaveInstanceState()}.
31912      */
31913     public static class BaseSavedState extends AbsSavedState {
31914         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
31915         static final int IS_AUTOFILLED = 0b10;
31916         static final int AUTOFILL_ID = 0b100;
31917 
31918         // Flags that describe what data in this state is valid
31919         int mSavedData;
31920         String mStartActivityRequestWhoSaved;
31921         boolean mIsAutofilled;
31922         boolean mHideHighlight;
31923         int mAutofillViewId;
31924 
31925         /**
31926          * Constructor used when reading from a parcel. Reads the state of the superclass.
31927          *
31928          * @param source parcel to read from
31929          */
BaseSavedState(Parcel source)31930         public BaseSavedState(Parcel source) {
31931             this(source, null);
31932         }
31933 
31934         /**
31935          * Constructor used when reading from a parcel using a given class loader.
31936          * Reads the state of the superclass.
31937          *
31938          * @param source parcel to read from
31939          * @param loader ClassLoader to use for reading
31940          */
BaseSavedState(Parcel source, ClassLoader loader)31941         public BaseSavedState(Parcel source, ClassLoader loader) {
31942             super(source, loader);
31943             mSavedData = source.readInt();
31944             mStartActivityRequestWhoSaved = source.readString();
31945             mIsAutofilled = source.readBoolean();
31946             mHideHighlight = source.readBoolean();
31947             mAutofillViewId = source.readInt();
31948         }
31949 
31950         /**
31951          * Constructor called by derived classes when creating their SavedState objects
31952          *
31953          * @param superState The state of the superclass of this view
31954          */
BaseSavedState(Parcelable superState)31955         public BaseSavedState(Parcelable superState) {
31956             super(superState);
31957         }
31958 
31959         @Override
writeToParcel(Parcel out, int flags)31960         public void writeToParcel(Parcel out, int flags) {
31961             super.writeToParcel(out, flags);
31962 
31963             out.writeInt(mSavedData);
31964             out.writeString(mStartActivityRequestWhoSaved);
31965             out.writeBoolean(mIsAutofilled);
31966             out.writeBoolean(mHideHighlight);
31967             out.writeInt(mAutofillViewId);
31968         }
31969 
31970         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
31971                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
31972             @Override
31973             public BaseSavedState createFromParcel(Parcel in) {
31974                 return new BaseSavedState(in);
31975             }
31976 
31977             @Override
31978             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
31979                 return new BaseSavedState(in, loader);
31980             }
31981 
31982             @Override
31983             public BaseSavedState[] newArray(int size) {
31984                 return new BaseSavedState[size];
31985             }
31986         };
31987     }
31988 
31989     /**
31990      * A set of information given to a view when it is attached to its parent
31991      * window.
31992      */
31993     final static class AttachInfo {
31994 
31995         interface Callbacks {
playSoundEffect(int effectId)31996             void playSoundEffect(int effectId);
31997 
performHapticFeedback(int effectId, @HapticFeedbackConstants.Flags int flags, @HapticFeedbackConstants.PrivateFlags int privFlags)31998             boolean performHapticFeedback(int effectId,
31999                     @HapticFeedbackConstants.Flags int flags,
32000                     @HapticFeedbackConstants.PrivateFlags int privFlags);
32001 
performHapticFeedbackForInputDevice(int effectId, int inputDeviceId, int inputSource, @HapticFeedbackConstants.Flags int flags, @HapticFeedbackConstants.PrivateFlags int privFlags)32002             void performHapticFeedbackForInputDevice(int effectId,
32003                     int inputDeviceId, int inputSource,
32004                     @HapticFeedbackConstants.Flags int flags,
32005                     @HapticFeedbackConstants.PrivateFlags int privFlags);
32006         }
32007 
32008         /**
32009          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
32010          * to a Handler. This class contains the target (View) to invalidate and
32011          * the coordinates of the dirty rectangle.
32012          *
32013          * For performance purposes, this class also implements a pool of up to
32014          * POOL_LIMIT objects that get reused. This reduces memory allocations
32015          * whenever possible.
32016          */
32017         static class InvalidateInfo {
32018 
32019             @UnsupportedAppUsage
InvalidateInfo()32020             InvalidateInfo() {
32021             }
32022 
32023             private static final int POOL_LIMIT = 10;
32024 
32025             private static final SynchronizedPool<InvalidateInfo> sPool =
32026                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
32027 
32028             @UnsupportedAppUsage
32029             View target;
32030 
32031             @UnsupportedAppUsage
32032             int left;
32033             @UnsupportedAppUsage
32034             int top;
32035             @UnsupportedAppUsage
32036             int right;
32037             @UnsupportedAppUsage
32038             int bottom;
32039 
obtain()32040             public static InvalidateInfo obtain() {
32041                 InvalidateInfo instance = sPool.acquire();
32042                 return (instance != null) ? instance : new InvalidateInfo();
32043             }
32044 
recycle()32045             public void recycle() {
32046                 target = null;
32047                 sPool.release(this);
32048             }
32049         }
32050 
32051         @UnsupportedAppUsage
32052         final IWindowSession mSession;
32053 
32054         @UnsupportedAppUsage
32055         final IWindow mWindow;
32056 
32057         final IBinder mWindowToken;
32058 
32059         Display mDisplay;
32060 
32061         final Callbacks mRootCallbacks;
32062 
32063         IWindowId mIWindowId;
32064         WindowId mWindowId;
32065 
32066         /**
32067          * The top view of the hierarchy.
32068          */
32069         View mRootView;
32070 
32071         IBinder mPanelParentWindowToken;
32072 
32073         boolean mHardwareAccelerated;
32074         boolean mHardwareAccelerationRequested;
32075         ThreadedRenderer mThreadedRenderer;
32076         List<RenderNode> mPendingAnimatingRenderNodes;
32077 
32078         /**
32079          * The state of the display to which the window is attached, as reported
32080          * by {@link Display#getState()}.  Note that the display state constants
32081          * declared by {@link Display} do not exactly line up with the screen state
32082          * constants declared by {@link View} (there are more display states than
32083          * screen states).
32084          */
32085         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
32086         int mDisplayState = Display.STATE_UNKNOWN;
32087 
32088         /**
32089          * Scale factor used by the compatibility mode
32090          */
32091         @UnsupportedAppUsage
32092         float mApplicationScale;
32093 
32094         /**
32095          * Indicates whether the application is in compatibility mode
32096          */
32097         @UnsupportedAppUsage
32098         boolean mScalingRequired;
32099 
32100         /**
32101          * Left position of this view's window
32102          */
32103         int mWindowLeft;
32104 
32105         /**
32106          * Top position of this view's window
32107          */
32108         int mWindowTop;
32109 
32110         /**
32111          * Indicates whether views need to use 32-bit drawing caches
32112          */
32113         boolean mUse32BitDrawingCache;
32114 
32115         /**
32116          * For windows that are full-screen but using insets to layout inside
32117          * of the screen decorations, these are the current insets for the
32118          * content of the window.
32119          */
32120         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
32121                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
32122         final Rect mContentInsets = new Rect();
32123 
32124         /**
32125          * For windows that are full-screen but using insets to layout inside
32126          * of the screen decorations, these are the current insets for the
32127          * actual visible parts of the window.
32128          */
32129         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
32130                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
32131         final Rect mVisibleInsets = new Rect();
32132 
32133         /**
32134          * For windows that are full-screen but using insets to layout inside
32135          * of the screen decorations, these are the current insets for the
32136          * stable system windows.
32137          */
32138         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
32139                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
32140         final Rect mStableInsets = new Rect();
32141 
32142         /**
32143          * Current caption insets to the display coordinate.
32144          */
32145         final Rect mCaptionInsets = new Rect();
32146 
32147         /**
32148          * In multi-window we force show the system bars. Because we don't want that the surface
32149          * size changes in this mode, we instead have a flag whether the system bars sizes should
32150          * always be consumed, so the app is treated like there are no virtual system bars at all.
32151          */
32152         boolean mAlwaysConsumeSystemBars;
32153 
32154         /**
32155          * The internal insets given by this window.  This value is
32156          * supplied by the client (through
32157          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
32158          * be given to the window manager when changed to be used in laying
32159          * out windows behind it.
32160          */
32161         @UnsupportedAppUsage
32162         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
32163                 = new ViewTreeObserver.InternalInsetsInfo();
32164 
32165         /**
32166          * Set to true when mGivenInternalInsets is non-empty.
32167          */
32168         boolean mHasNonEmptyGivenInternalInsets;
32169 
32170         /**
32171          * All views in the window's hierarchy that serve as scroll containers,
32172          * used to determine if the window can be resized or must be panned
32173          * to adjust for a soft input area.
32174          */
32175         @UnsupportedAppUsage
32176         final ArrayList<View> mScrollContainers = new ArrayList<View>();
32177 
32178         @UnsupportedAppUsage
32179         final KeyEvent.DispatcherState mKeyDispatchState
32180                 = new KeyEvent.DispatcherState();
32181 
32182         /**
32183          * Indicates whether the view's window currently has the focus.
32184          */
32185         @UnsupportedAppUsage
32186         boolean mHasWindowFocus;
32187 
32188         /**
32189          * The current visibility of the window.
32190          */
32191         int mWindowVisibility;
32192 
32193         /**
32194          * Indicates the time at which drawing started to occur.
32195          */
32196         @UnsupportedAppUsage
32197         long mDrawingTime;
32198 
32199         /**
32200          * Indicates whether the view's window is currently in touch mode.
32201          */
32202         @UnsupportedAppUsage
32203         boolean mInTouchMode;
32204 
32205         /**
32206          * Indicates whether the view has requested unbuffered input dispatching for the current
32207          * event stream.
32208          */
32209         boolean mUnbufferedDispatchRequested;
32210 
32211         /**
32212          * Indicates that ViewAncestor should trigger a global layout change
32213          * the next time it performs a traversal
32214          */
32215         @UnsupportedAppUsage
32216         boolean mRecomputeGlobalAttributes;
32217 
32218         /**
32219          * Always report new attributes at next traversal.
32220          */
32221         boolean mForceReportNewAttributes;
32222 
32223         /**
32224          * Set during a traveral if any views want to keep the screen on.
32225          */
32226         @UnsupportedAppUsage
32227         boolean mKeepScreenOn;
32228 
32229         /**
32230          * Set during a traveral if the light center needs to be updated.
32231          */
32232         boolean mNeedsUpdateLightCenter;
32233 
32234         /**
32235          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
32236          */
32237         int mSystemUiVisibility;
32238 
32239         /**
32240          * Hack to force certain system UI visibility flags to be cleared.
32241          */
32242         int mDisabledSystemUiVisibility;
32243 
32244         /**
32245          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
32246          * attached.
32247          */
32248         boolean mHasSystemUiListeners;
32249 
32250         /**
32251          * Set if the visibility of any views has changed.
32252          */
32253         @UnsupportedAppUsage
32254         boolean mViewVisibilityChanged;
32255 
32256         /**
32257          * Set to true if a view has been scrolled.
32258          */
32259         @UnsupportedAppUsage
32260         boolean mViewScrollChanged;
32261 
32262         /**
32263          * Set to true if a pointer event is currently being handled.
32264          */
32265         boolean mHandlingPointerEvent;
32266 
32267         /**
32268          * The window matrix of this view when it's on a {@link SurfaceControlViewHost} that is
32269          * embedded within a SurfaceView.
32270          */
32271         Matrix mWindowMatrixInEmbeddedHierarchy;
32272 
32273         /**
32274          * Global to the view hierarchy used as a temporary for dealing with
32275          * x/y points in the transparent region computations.
32276          */
32277         final int[] mTransparentLocation = new int[2];
32278 
32279         /**
32280          * Global to the view hierarchy used as a temporary for dealing with
32281          * x/y points in the ViewGroup.invalidateChild implementation.
32282          */
32283         final int[] mInvalidateChildLocation = new int[2];
32284 
32285         /**
32286          * Global to the view hierarchy used as a temporary for dealing with
32287          * computing absolute on-screen location.
32288          */
32289         final int[] mTmpLocation = new int[2];
32290 
32291         /**
32292          * Global to the view hierarchy used as a temporary for dealing with
32293          * x/y location when view is transformed.
32294          */
32295         final float[] mTmpTransformLocation = new float[2];
32296 
32297         /**
32298          * The view tree observer used to dispatch global events like
32299          * layout, pre-draw, touch mode change, etc.
32300          */
32301         @UnsupportedAppUsage
32302         final ViewTreeObserver mTreeObserver;
32303 
32304         /**
32305          * A Canvas used by the view hierarchy to perform bitmap caching.
32306          */
32307         Canvas mCanvas;
32308 
32309         /**
32310          * The view root impl.
32311          */
32312         final ViewRootImpl mViewRootImpl;
32313 
32314         /**
32315          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
32316          * handler can be used to pump events in the UI events queue.
32317          */
32318         @UnsupportedAppUsage
32319         final Handler mHandler;
32320 
32321         /**
32322          * Temporary for use in computing invalidate rectangles while
32323          * calling up the hierarchy.
32324          */
32325         final Rect mTmpInvalRect = new Rect();
32326 
32327         /**
32328          * Temporary for use in computing hit areas with transformed views
32329          */
32330         final RectF mTmpTransformRect = new RectF();
32331 
32332         /**
32333          * Temporary for use in computing hit areas with transformed views
32334          */
32335         final RectF mTmpTransformRect1 = new RectF();
32336 
32337         /**
32338          * Temporary list of rectanges.
32339          */
32340         final List<RectF> mTmpRectList = new ArrayList<>();
32341 
32342         /**
32343          * Temporary for use in transforming invalidation rect
32344          */
32345         final Matrix mTmpMatrix = new Matrix();
32346 
32347         /**
32348          * Temporary for use in transforming invalidation rect
32349          */
32350         final Transformation mTmpTransformation = new Transformation();
32351 
32352         /**
32353          * Temporary for use in querying outlines from OutlineProviders
32354          */
32355         final Outline mTmpOutline = new Outline();
32356 
32357         /**
32358          * Temporary list for use in collecting focusable descendents of a view.
32359          */
32360         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
32361 
32362         /**
32363          * Indicates if the next focus will be looped back to the first focusable view of the entire
32364          * hierarchy when finding in the direction of {@link #FOCUS_FORWARD} or to the last
32365          * focusable view when finding in the direction of {@link #FOCUS_BACKWARD}.
32366          */
32367         boolean mNextFocusLooped = false;
32368 
32369         /**
32370          * The id of the window for accessibility purposes.
32371          */
32372         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
32373 
32374         /**
32375          * Flags related to accessibility processing.
32376          *
32377          * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
32378          * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
32379          */
32380         int mAccessibilityFetchFlags;
32381 
32382         /**
32383          * The drawable for highlighting accessibility focus.
32384          */
32385         Drawable mAccessibilityFocusDrawable;
32386 
32387         /**
32388          * The drawable for highlighting autofilled views.
32389          *
32390          * @see #isAutofilled()
32391          */
32392         Drawable mAutofilledDrawable;
32393 
32394         /**
32395          * Show where the margins, bounds and layout bounds are for each view.
32396          */
32397         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
32398 
32399         /**
32400          * Point used to compute visible regions.
32401          */
32402         final Point mPoint = new Point();
32403 
32404         /**
32405          * Used to track which View originated a requestLayout() call, used when
32406          * requestLayout() is called during layout.
32407          */
32408         View mViewRequestingLayout;
32409 
32410         /**
32411          * Used to track the identity of the current drag operation.
32412          */
32413         IBinder mDragToken;
32414 
32415         /**
32416          * Used to track the data of the current drag operation for cleanup later.
32417          */
32418         ClipData mDragData;
32419 
32420         /**
32421          * The drag shadow surface for the current drag operation.
32422          */
32423         public Surface mDragSurface;
32424 
32425         /**
32426          * The view that currently has a tooltip displayed.
32427          */
32428         View mTooltipHost;
32429 
32430         /**
32431          * The initial structure has been reported so the view is ready to report updates.
32432          */
32433         boolean mReadyForContentCaptureUpdates;
32434 
32435         /**
32436          * Map(keyed by session) of content capture events that need to be notified after the view
32437          * hierarchy is traversed: value is either the view itself for appearead events, or its
32438          * autofill id for disappeared.
32439          */
32440         SparseArray<ArrayList<Object>> mContentCaptureEvents;
32441 
32442         /**
32443          * Cached reference to the {@link ContentCaptureManager}.
32444          */
32445         ContentCaptureManager mContentCaptureManager;
32446 
32447         /**
32448          * Listener used to fit content on window level.
32449          */
32450         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
32451 
32452         /**
32453          * The leash token of this view's parent when it's in an embedded hierarchy that is
32454          * re-parented to another window.
32455          */
32456         IBinder mLeashedParentToken;
32457 
32458         /**
32459          * The accessibility view id of this view's parent when it's in an embedded
32460          * hierarchy that is re-parented to another window.
32461          */
32462         int mLeashedParentAccessibilityViewId;
32463 
32464         /**
32465          *
32466          */
32467         ScrollCaptureInternal mScrollCaptureInternal;
32468 
32469         /**
32470          * sensitive views attached to the window
32471          */
32472         int mSensitiveViewsCount;
32473 
32474         /**
32475          * The value of viewVelocityApi(), read only once per ViewRootImpl
32476          */
32477         final boolean mViewVelocityApi = viewVelocityApi();
32478 
32479         /**
32480          * Density so that it doesn't need to be retrieved on every invalidation.
32481          */
32482         final float mDensity;
32483 
32484         /**
32485          * The number of pixels in the display (width * height).
32486          */
32487         final float mDisplayPixelCount;
32488 
32489         /**
32490          * Creates a new set of attachment information with the specified
32491          * events handler and thread.
32492          *
32493          * @param handler the events handler the view must use
32494          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)32495         AttachInfo(IWindowSession session, IWindow window, Display display,
32496                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
32497                 Context context) {
32498             mSession = session;
32499             mWindow = window;
32500             mWindowToken = window.asBinder();
32501             mDisplay = display;
32502             mViewRootImpl = viewRootImpl;
32503             mHandler = handler;
32504             mRootCallbacks = effectPlayer;
32505             mTreeObserver = new ViewTreeObserver(context);
32506             DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
32507             mDensity = displayMetrics.density;
32508             float pixelCount = (float) displayMetrics.widthPixels * displayMetrics.heightPixels;
32509             mDisplayPixelCount = pixelCount == 0f ? Float.POSITIVE_INFINITY : pixelCount;
32510         }
32511 
increaseSensitiveViewsCount()32512         void increaseSensitiveViewsCount() {
32513             if (mSensitiveViewsCount == 0) {
32514                 mViewRootImpl.addSensitiveContentAppProtection();
32515             }
32516             mSensitiveViewsCount++;
32517         }
32518 
decreaseSensitiveViewsCount()32519         void decreaseSensitiveViewsCount() {
32520             mSensitiveViewsCount--;
32521             if (mSensitiveViewsCount == 0) {
32522                 mViewRootImpl.removeSensitiveContentAppProtection();
32523             }
32524             if (mSensitiveViewsCount < 0) {
32525                 Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount);
32526                 mSensitiveViewsCount = 0;
32527             }
32528         }
32529 
32530         @Nullable
getContentCaptureManager(@onNull Context context)32531         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
32532             if (mContentCaptureManager != null) {
32533                 return mContentCaptureManager;
32534             }
32535             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
32536             return mContentCaptureManager;
32537         }
32538 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)32539         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
32540             if (mContentCaptureManager == null) {
32541                 return;
32542             }
32543 
32544             ArrayList<Object> events = ensureEvents(
32545                         mContentCaptureManager.getMainContentCaptureSession());
32546             events.add(insets);
32547         }
32548 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)32549         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
32550                 @NonNull View view, boolean appeared) {
32551             ArrayList<Object> events = ensureEvents(session);
32552             events.add(appeared ? view : view.getAutofillId());
32553         }
32554 
32555         @NonNull
ensureEvents(@onNull ContentCaptureSession session)32556         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
32557             if (mContentCaptureEvents == null) {
32558                 // Most of the time there will be just one session, so intial capacity is 1
32559                 mContentCaptureEvents = new SparseArray<>(1);
32560             }
32561             int sessionId = session.getId();
32562             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
32563             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
32564             if (events == null) {
32565                 events = new ArrayList<>();
32566                 mContentCaptureEvents.put(sessionId, events);
32567             }
32568 
32569             return events;
32570         }
32571 
32572         @Nullable
getScrollCaptureInternal()32573         ScrollCaptureInternal getScrollCaptureInternal() {
32574             if (mScrollCaptureInternal != null) {
32575                 mScrollCaptureInternal = new ScrollCaptureInternal();
32576             }
32577             return mScrollCaptureInternal;
32578         }
32579 
getRootSurfaceControl()32580         AttachedSurfaceControl getRootSurfaceControl() {
32581             return mViewRootImpl;
32582         }
32583 
dump(String prefix, PrintWriter writer)32584         public void dump(String prefix, PrintWriter writer) {
32585             String innerPrefix = prefix + "  ";
32586             writer.println(prefix + "AttachInfo:");
32587             writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
32588             writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
32589             writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
32590             writer.println(innerPrefix + "mUnbufferedDispatchRequested="
32591                     + mUnbufferedDispatchRequested);
32592         }
32593     }
32594 
32595     /**
32596      * <p>ScrollabilityCache holds various fields used by a View when scrolling
32597      * is supported. This avoids keeping too many unused fields in most
32598      * instances of View.</p>
32599      */
32600     private static class ScrollabilityCache implements Runnable {
32601 
32602         /**
32603          * Scrollbars are not visible
32604          */
32605         public static final int OFF = 0;
32606 
32607         /**
32608          * Scrollbars are visible
32609          */
32610         public static final int ON = 1;
32611 
32612         /**
32613          * Scrollbars are fading away
32614          */
32615         public static final int FADING = 2;
32616 
32617         public boolean fadeScrollBars;
32618 
32619         public int fadingEdgeLength;
32620         public int scrollBarDefaultDelayBeforeFade;
32621         public int scrollBarFadeDuration;
32622 
32623         public int scrollBarSize;
32624         public int scrollBarMinTouchTarget;
32625         @UnsupportedAppUsage
32626         public ScrollBarDrawable scrollBar;
32627         public float[] interpolatorValues;
32628         @UnsupportedAppUsage
32629         public View host;
32630 
32631         public final Paint paint;
32632         public final Matrix matrix;
32633         public Shader shader;
32634 
32635         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
32636 
32637         private static final float[] OPAQUE = { 255 };
32638         private static final float[] TRANSPARENT = { 0.0f };
32639 
32640         /**
32641          * When fading should start. This time moves into the future every time
32642          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
32643          */
32644         public long fadeStartTime;
32645 
32646 
32647         /**
32648          * The current state of the scrollbars: ON, OFF, or FADING
32649          */
32650         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
32651         public int state = OFF;
32652 
32653         private int mLastColor;
32654 
32655         public final Rect mScrollBarBounds = new Rect();
32656         public final Rect mScrollBarTouchBounds = new Rect();
32657 
32658         public static final int NOT_DRAGGING = 0;
32659         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
32660         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
32661         public int mScrollBarDraggingState = NOT_DRAGGING;
32662 
32663         public float mScrollBarDraggingPos = 0;
32664 
ScrollabilityCache(ViewConfiguration configuration, View host)32665         public ScrollabilityCache(ViewConfiguration configuration, View host) {
32666             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
32667             scrollBarSize = configuration.getScaledScrollBarSize();
32668             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
32669             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
32670             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
32671 
32672             paint = new Paint();
32673             matrix = new Matrix();
32674             // use use a height of 1, and then wack the matrix each time we
32675             // actually use it.
32676             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
32677             paint.setShader(shader);
32678             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
32679 
32680             this.host = host;
32681         }
32682 
setFadeColor(int color)32683         public void setFadeColor(int color) {
32684             if (color != mLastColor) {
32685                 mLastColor = color;
32686 
32687                 if (color != 0) {
32688                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
32689                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
32690                     paint.setShader(shader);
32691                     // Restore the default transfer mode (src_over)
32692                     paint.setXfermode(null);
32693                 } else {
32694                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
32695                     paint.setShader(shader);
32696                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
32697                 }
32698             }
32699         }
32700 
run()32701         public void run() {
32702             long now = AnimationUtils.currentAnimationTimeMillis();
32703             if (now >= fadeStartTime) {
32704 
32705                 // the animation fades the scrollbars out by changing
32706                 // the opacity (alpha) from fully opaque to fully
32707                 // transparent
32708                 int nextFrame = (int) now;
32709                 int framesCount = 0;
32710 
32711                 Interpolator interpolator = scrollBarInterpolator;
32712 
32713                 // Start opaque
32714                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
32715 
32716                 // End transparent
32717                 nextFrame += scrollBarFadeDuration;
32718                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
32719 
32720                 state = FADING;
32721 
32722                 // Kick off the fade animation
32723                 host.invalidate(true);
32724             }
32725         }
32726     }
32727 
32728     private class SendAccessibilityEventThrottle implements Runnable {
32729         public volatile boolean mIsPending;
32730         private AccessibilityEvent mAccessibilityEvent;
32731 
post(AccessibilityEvent accessibilityEvent)32732         public void post(AccessibilityEvent accessibilityEvent) {
32733             updateWithAccessibilityEvent(accessibilityEvent);
32734             if (!mIsPending) {
32735                 mIsPending = true;
32736                 postDelayed(this,
32737                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
32738             }
32739         }
32740 
32741         @Override
run()32742         public void run() {
32743             if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
32744                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
32745             }
32746             reset();
32747         }
32748 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)32749         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
32750             mAccessibilityEvent = accessibilityEvent;
32751         }
32752 
reset()32753         public void reset() {
32754             mIsPending = false;
32755             mAccessibilityEvent = null;
32756         }
32757 
32758     }
32759 
32760     /**
32761      * Resuable callback for sending
32762      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
32763      */
32764     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
32765         public int mDeltaX;
32766         public int mDeltaY;
32767 
32768         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)32769         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
32770             super.updateWithAccessibilityEvent(accessibilityEvent);
32771             mDeltaX += accessibilityEvent.getScrollDeltaX();
32772             mDeltaY += accessibilityEvent.getScrollDeltaY();
32773             accessibilityEvent.setScrollDeltaX(mDeltaX);
32774             accessibilityEvent.setScrollDeltaY(mDeltaY);
32775         }
32776 
32777         @Override
reset()32778         public void reset() {
32779             super.reset();
32780             mDeltaX = 0;
32781             mDeltaY = 0;
32782         }
32783     }
32784     /**
32785      * Remove the pending callback for sending a throttled accessibility event.
32786      */
32787     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)32788     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
32789         if (callback == null || !callback.mIsPending) return;
32790         removeCallbacks(callback);
32791         callback.reset();
32792     }
32793 
32794     /**
32795      * <p>
32796      * This class represents a delegate that can be registered in a {@link View}
32797      * to enhance accessibility support via composition rather via inheritance.
32798      * It is specifically targeted to widget developers that extend basic View
32799      * classes i.e. classes in package android.view, that would like their
32800      * applications to be backwards compatible.
32801      * </p>
32802      * <div class="special reference">
32803      * <h3>Developer Guides</h3>
32804      * <p>For more information about making applications accessible, read the
32805      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
32806      * developer guide.</p>
32807      * </div>
32808      * <p>
32809      * A scenario in which a developer would like to use an accessibility delegate
32810      * is overriding a method introduced in a later API version than the minimal API
32811      * version supported by the application. For example, the method
32812      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
32813      * in API version 4 when the accessibility APIs were first introduced. If a
32814      * developer would like their application to run on API version 4 devices (assuming
32815      * all other APIs used by the application are version 4 or lower) and take advantage
32816      * of this method, instead of overriding the method which would break the application's
32817      * backwards compatibility, they can override the corresponding method in this
32818      * delegate and register the delegate in the target View if the API version of
32819      * the system is high enough, i.e. the API version is the same as or higher than the API
32820      * version that introduced
32821      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
32822      * </p>
32823      * <p>
32824      * Here is an example implementation:
32825      * </p>
32826      * <code><pre><p>
32827      * if (Build.VERSION.SDK_INT >= 14) {
32828      *     // If the API version is equal of higher than the version in
32829      *     // which onInitializeAccessibilityNodeInfo was introduced we
32830      *     // register a delegate with a customized implementation.
32831      *     View view = findViewById(R.id.view_id);
32832      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
32833      *         public void onInitializeAccessibilityNodeInfo(View host,
32834      *                 AccessibilityNodeInfo info) {
32835      *             // Let the default implementation populate the info.
32836      *             super.onInitializeAccessibilityNodeInfo(host, info);
32837      *             // Set some other information.
32838      *             info.setEnabled(host.isEnabled());
32839      *         }
32840      *     });
32841      * }
32842      * </code></pre></p>
32843      * <p>
32844      * This delegate contains methods that correspond to the accessibility methods
32845      * in View. If a delegate has been specified the implementation in View hands
32846      * off handling to the corresponding method in this delegate. The default
32847      * implementation the delegate methods behaves exactly as the corresponding
32848      * method in View for the case of no accessibility delegate been set. Hence,
32849      * to customize the behavior of a View method, clients can override only the
32850      * corresponding delegate method without altering the behavior of the rest
32851      * accessibility related methods of the host view.
32852      * </p>
32853      * <p>
32854      * <strong>Note:</strong> On platform versions prior to
32855      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
32856      * views in the {@code android.widget.*} package are called <i>before</i>
32857      * host methods. This prevents certain properties such as class name from
32858      * being modified by overriding
32859      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
32860      * as any changes will be overwritten by the host class.
32861      * <p>
32862      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
32863      * methods are called <i>after</i> host methods, which all properties to be
32864      * modified without being overwritten by the host class.
32865      * <aside class="note">
32866      * <b>Note:</b> Use a {@link androidx.core.view.AccessibilityDelegateCompat}
32867      * wrapper instead of this class for backwards-compatibility.
32868      * </aside>
32869      *
32870      */
32871     public static class AccessibilityDelegate {
32872 
32873         /**
32874          * Sends an accessibility event of the given type. If accessibility is not
32875          * enabled this method has no effect.
32876          * <p>
32877          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
32878          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
32879          * been set.
32880          * </p>
32881          *
32882          * @param host The View hosting the delegate.
32883          * @param eventType The type of the event to send.
32884          *
32885          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
32886          */
sendAccessibilityEvent(@onNull View host, int eventType)32887         public void sendAccessibilityEvent(@NonNull View host, int eventType) {
32888             host.sendAccessibilityEventInternal(eventType);
32889         }
32890 
32891         /**
32892          * Performs the specified accessibility action on the view. For
32893          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
32894          * <p>
32895          * The default implementation behaves as
32896          * {@link View#performAccessibilityAction(int, Bundle)
32897          *  View#performAccessibilityAction(int, Bundle)} for the case of
32898          *  no accessibility delegate been set.
32899          * </p>
32900          *
32901          * @param action The action to perform.
32902          * @return Whether the action was performed.
32903          *
32904          * @see View#performAccessibilityAction(int, Bundle)
32905          *      View#performAccessibilityAction(int, Bundle)
32906          */
performAccessibilityAction(@onNull View host, int action, @Nullable Bundle args)32907         public boolean performAccessibilityAction(@NonNull View host, int action,
32908                 @Nullable Bundle args) {
32909             return host.performAccessibilityActionInternal(action, args);
32910         }
32911 
32912         /**
32913          * Sends an accessibility event. This method behaves exactly as
32914          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
32915          * empty {@link AccessibilityEvent} and does not perform a check whether
32916          * accessibility is enabled.
32917          * <p>
32918          * The default implementation behaves as
32919          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
32920          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
32921          * the case of no accessibility delegate been set.
32922          * </p>
32923          *
32924          * @param host The View hosting the delegate.
32925          * @param event The event to send.
32926          *
32927          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
32928          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
32929          */
sendAccessibilityEventUnchecked(@onNull View host, @NonNull AccessibilityEvent event)32930         public void sendAccessibilityEventUnchecked(@NonNull View host,
32931                 @NonNull AccessibilityEvent event) {
32932             host.sendAccessibilityEventUncheckedInternal(event);
32933         }
32934 
32935         /**
32936          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
32937          * to its children for adding their text content to the event.
32938          * <p>
32939          * The default implementation behaves as
32940          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
32941          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
32942          * the case of no accessibility delegate been set.
32943          * </p>
32944          *
32945          * @param host The View hosting the delegate.
32946          * @param event The event.
32947          * @return True if the event population was completed.
32948          *
32949          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
32950          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
32951          */
dispatchPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)32952         public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
32953                 @NonNull AccessibilityEvent event) {
32954             return host.dispatchPopulateAccessibilityEventInternal(event);
32955         }
32956 
32957         /**
32958          * Gives a chance to the host View to populate the accessibility event with its
32959          * text content.
32960          * <p>
32961          * The default implementation behaves as
32962          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
32963          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
32964          * the case of no accessibility delegate been set.
32965          * </p>
32966          *
32967          * @param host The View hosting the delegate.
32968          * @param event The accessibility event which to populate.
32969          *
32970          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
32971          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
32972          */
onPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)32973         public void onPopulateAccessibilityEvent(@NonNull View host,
32974                 @NonNull AccessibilityEvent event) {
32975             host.onPopulateAccessibilityEventInternal(event);
32976         }
32977 
32978         /**
32979          * Initializes an {@link AccessibilityEvent} with information about the
32980          * the host View which is the event source.
32981          * <p>
32982          * The default implementation behaves as
32983          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
32984          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
32985          * the case of no accessibility delegate been set.
32986          * </p>
32987          *
32988          * @param host The View hosting the delegate.
32989          * @param event The event to initialize.
32990          *
32991          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
32992          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
32993          */
onInitializeAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)32994         public void onInitializeAccessibilityEvent(@NonNull View host,
32995                 @NonNull AccessibilityEvent event) {
32996             host.onInitializeAccessibilityEventInternal(event);
32997         }
32998 
32999         /**
33000          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
33001          * <p>
33002          * The default implementation behaves as
33003          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
33004          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
33005          * the case of no accessibility delegate been set.
33006          * </p>
33007          *
33008          * @param host The View hosting the delegate.
33009          * @param info The instance to initialize.
33010          *
33011          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
33012          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
33013          */
onInitializeAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info)33014         public void onInitializeAccessibilityNodeInfo(@NonNull View host,
33015                 @NonNull AccessibilityNodeInfo info) {
33016             host.onInitializeAccessibilityNodeInfoInternal(info);
33017         }
33018 
33019         /**
33020          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
33021          * additional data.
33022          * <p>
33023          * This method only needs to be implemented if the View offers to provide additional data.
33024          * </p>
33025          * <p>
33026          * The default implementation behaves as
33027          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
33028          * for the case where no accessibility delegate is set.
33029          * </p>
33030          *
33031          * @param host The View hosting the delegate. Never {@code null}.
33032          * @param info The info to which to add the extra data. Never {@code null}.
33033          * @param extraDataKey A key specifying the type of extra data to add to the info. The
33034          *                     extra data should be added to the {@link Bundle} returned by
33035          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
33036          *                     {@code null}.
33037          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
33038          *                  May be {@code null} if the if the service provided no arguments.
33039          *
33040          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
33041          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)33042         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
33043                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
33044                 @Nullable Bundle arguments) {
33045             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
33046         }
33047 
33048         /**
33049          * Called when a child of the host View has requested sending an
33050          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
33051          * to augment the event.
33052          * <p>
33053          * The default implementation behaves as
33054          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
33055          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
33056          * the case of no accessibility delegate been set.
33057          * </p>
33058          *
33059          * @param host The View hosting the delegate.
33060          * @param child The child which requests sending the event.
33061          * @param event The event to be sent.
33062          * @return True if the event should be sent
33063          *
33064          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
33065          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
33066          */
onRequestSendAccessibilityEvent(@onNull ViewGroup host, @NonNull View child, @NonNull AccessibilityEvent event)33067         public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
33068                 @NonNull AccessibilityEvent event) {
33069             return host.onRequestSendAccessibilityEventInternal(child, event);
33070         }
33071 
33072         /**
33073          * Gets the provider for managing a virtual view hierarchy rooted at this View
33074          * and reported to {@link android.accessibilityservice.AccessibilityService}s
33075          * that explore the window content.
33076          * <p>
33077          * The default implementation behaves as
33078          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
33079          * the case of no accessibility delegate been set.
33080          * </p>
33081          *
33082          * @return The provider.
33083          *
33084          * @see AccessibilityNodeProvider
33085          */
getAccessibilityNodeProvider( @onNull View host)33086         public @Nullable AccessibilityNodeProvider getAccessibilityNodeProvider(
33087                 @NonNull View host) {
33088             return null;
33089         }
33090 
33091         /**
33092          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
33093          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
33094          * This method is responsible for obtaining an accessibility node info from a
33095          * pool of reusable instances and calling
33096          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
33097          * view to initialize the former.
33098          * <p>
33099          * <strong>Note:</strong> The client is responsible for recycling the obtained
33100          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
33101          * creation.
33102          * </p>
33103          * <p>
33104          * The default implementation behaves as
33105          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
33106          * the case of no accessibility delegate been set.
33107          * </p>
33108          * @return A populated {@link AccessibilityNodeInfo}.
33109          *
33110          * @see AccessibilityNodeInfo
33111          *
33112          * @hide
33113          */
33114         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
createAccessibilityNodeInfo(@onNull View host)33115         public AccessibilityNodeInfo createAccessibilityNodeInfo(@NonNull View host) {
33116             return host.createAccessibilityNodeInfoInternal();
33117         }
33118     }
33119 
33120     private static class MatchIdPredicate implements Predicate<View> {
33121         public int mId;
33122 
33123         @Override
test(View view)33124         public boolean test(View view) {
33125             return (view.mID == mId);
33126         }
33127     }
33128 
33129     private static class MatchLabelForPredicate implements Predicate<View> {
33130         private int mLabeledId;
33131 
33132         @Override
test(View view)33133         public boolean test(View view) {
33134             return (view.mLabelForId == mLabeledId);
33135         }
33136     }
33137 
33138     private static class SensitiveAutofillHintsHelper {
33139         /**
33140          * List of autofill hints deemed sensitive for screen protection during screen share.
33141          */
33142         private static final ArraySet<String> SENSITIVE_CONTENT_AUTOFILL_HINTS = new ArraySet<>();
33143         static {
33144             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME);
33145             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO);
33146             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD);
33147             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
33148             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
33149             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
33150             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY);
33151             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
33152             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
33153             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDENTIAL_MANAGER);
33154         }
33155 
33156         /**
33157          * Whether View's autofill hints contains a sensitive autofill hint.
33158          *
33159          * @see #SENSITIVE_CONTENT_AUTOFILL_HINTS
33160          */
containsSensitiveAutofillHint(@ullable String[] autofillHints)33161         static boolean containsSensitiveAutofillHint(@Nullable String[] autofillHints) {
33162             if (autofillHints == null) {
33163                 return false;
33164             }
33165 
33166             int size = autofillHints.length;
33167             for (int i = 0; i < size; i++) {
33168                 if (SENSITIVE_CONTENT_AUTOFILL_HINTS.contains(autofillHints[i])) {
33169                     return true;
33170                 }
33171             }
33172             return false;
33173         }
33174     }
33175 
33176     /**
33177      * Returns the current scroll capture hint for this view.
33178      *
33179      * @return the current scroll capture hint
33180      */
33181     @ScrollCaptureHint
getScrollCaptureHint()33182     public int getScrollCaptureHint() {
33183         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
33184                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
33185     }
33186 
33187     /**
33188      * Sets the scroll capture hint for this View. These flags affect the search for a potential
33189      * scroll capture targets.
33190      *
33191      * @param hint the scrollCaptureHint flags value to set
33192      */
setScrollCaptureHint(@crollCaptureHint int hint)33193     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
33194         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
33195         // Since include/exclude are mutually exclusive, exclude takes precedence.
33196         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
33197             hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
33198         }
33199         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
33200                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
33201     }
33202 
33203     /**
33204      * Sets the callback to receive scroll capture requests. This component is the adapter between
33205      * the scroll capture API and application UI code. If no callback is set, the system may provide
33206      * an implementation. Any value provided here will take precedence over a system version.
33207      * <p>
33208      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
33209      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
33210      * <p>
33211      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
33212      * setting a custom callback to help ensure it is selected as the target.
33213      *
33214      * @param callback the new callback to assign
33215      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)33216     public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
33217         getListenerInfo().mScrollCaptureCallback = callback;
33218     }
33219 
33220     /** {@hide} */
33221     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)33222     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
33223             @NonNull Point windowOffset) {
33224         if (mAttachInfo == null) {
33225             return null;
33226         }
33227         if (mAttachInfo.mScrollCaptureInternal == null) {
33228             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
33229         }
33230         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
33231                 windowOffset);
33232     }
33233 
33234     /**
33235      * Dispatch a scroll capture search request down the view hierarchy.
33236      *
33237      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
33238      *                         the parent
33239      * @param windowOffset     the offset of this view within the window
33240      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
33241      *                         results.accept} may be called zero or more times on the calling
33242      *                         thread before onScrollCaptureSearch returns
33243      */
dispatchScrollCaptureSearch( @onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)33244     public void dispatchScrollCaptureSearch(
33245             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
33246             @NonNull Consumer<ScrollCaptureTarget> targets) {
33247         onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
33248     }
33249 
33250     /**
33251      * Called when scroll capture is requested, to search for appropriate content to scroll. If
33252      * applicable, this view adds itself to the provided list for consideration, subject to the
33253      * flags set by {@link #setScrollCaptureHint}.
33254      *
33255      * @param localVisibleRect the local visible rect of this view
33256      * @param windowOffset     the offset of localVisibleRect within the window
33257      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
33258      *                         results.accept} may be called zero or more times on the calling
33259      *                         thread before onScrollCaptureSearch returns
33260      * @throws IllegalStateException if this view is not attached to a window
33261      */
onScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)33262     public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
33263             @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
33264         int hint = getScrollCaptureHint();
33265         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
33266             return;
33267         }
33268         boolean rectIsVisible = true;
33269 
33270         // Apply clipBounds if present.
33271         if (mClipBounds != null) {
33272             rectIsVisible = localVisibleRect.intersect(mClipBounds);
33273         }
33274         if (!rectIsVisible) {
33275             return;
33276         }
33277 
33278         // Get a callback provided by the framework, library or application.
33279         ScrollCaptureCallback callback =
33280                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
33281 
33282         // Try framework support for standard scrolling containers.
33283         if (callback == null) {
33284             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
33285         }
33286 
33287         // If found, then add it to the list.
33288         if (callback != null) {
33289             // Add to the list for consideration
33290             Point offset = new Point(windowOffset.x, windowOffset.y);
33291             Rect rect = new Rect(localVisibleRect);
33292             targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
33293         }
33294     }
33295 
33296     /**
33297      * Dump all private flags in readable format, useful for documentation and
33298      * consistency checking.
33299      */
dumpFlags()33300     private static void dumpFlags() {
33301         final HashMap<String, String> found = Maps.newHashMap();
33302         try {
33303             for (Field field : View.class.getDeclaredFields()) {
33304                 final int modifiers = field.getModifiers();
33305                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
33306                     if (field.getType().equals(int.class)) {
33307                         final int value = field.getInt(null);
33308                         dumpFlag(found, field.getName(), value);
33309                     } else if (field.getType().equals(int[].class)) {
33310                         final int[] values = (int[]) field.get(null);
33311                         for (int i = 0; i < values.length; i++) {
33312                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
33313                         }
33314                     }
33315                 }
33316             }
33317         } catch (IllegalAccessException e) {
33318             throw new RuntimeException(e);
33319         }
33320 
33321         final ArrayList<String> keys = Lists.newArrayList();
33322         keys.addAll(found.keySet());
33323         Collections.sort(keys);
33324         for (String key : keys) {
33325             Log.d(VIEW_LOG_TAG, found.get(key));
33326         }
33327     }
33328 
dumpFlag(HashMap<String, String> found, String name, int value)33329     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
33330         // Sort flags by prefix, then by bits, always keeping unique keys
33331         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
33332         final int prefix = name.indexOf('_');
33333         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
33334         final String output = bits + " " + name;
33335         found.put(key, output);
33336     }
33337 
33338     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)33339     public void encode(@NonNull ViewHierarchyEncoder stream) {
33340         stream.beginObject(this);
33341         encodeProperties(stream);
33342         stream.endObject();
33343     }
33344 
33345     /** {@hide} */
33346     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)33347     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
33348         Object resolveId = ViewDebug.resolveId(getContext(), mID);
33349         if (resolveId instanceof String) {
33350             stream.addProperty("id", (String) resolveId);
33351         } else {
33352             stream.addProperty("id", mID);
33353         }
33354 
33355         stream.addProperty("misc:transformation.alpha",
33356                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
33357         stream.addProperty("misc:transitionName", getTransitionName());
33358 
33359         // layout
33360         stream.addProperty("layout:left", mLeft);
33361         stream.addProperty("layout:right", mRight);
33362         stream.addProperty("layout:top", mTop);
33363         stream.addProperty("layout:bottom", mBottom);
33364         stream.addProperty("layout:width", getWidth());
33365         stream.addProperty("layout:height", getHeight());
33366         stream.addProperty("layout:layoutDirection", getLayoutDirection());
33367         stream.addProperty("layout:layoutRtl", isLayoutRtl());
33368         stream.addProperty("layout:hasTransientState", hasTransientState());
33369         stream.addProperty("layout:baseline", getBaseline());
33370 
33371         // layout params
33372         ViewGroup.LayoutParams layoutParams = getLayoutParams();
33373         if (layoutParams != null) {
33374             stream.addPropertyKey("layoutParams");
33375             layoutParams.encode(stream);
33376         }
33377 
33378         // scrolling
33379         stream.addProperty("scrolling:scrollX", mScrollX);
33380         stream.addProperty("scrolling:scrollY", mScrollY);
33381 
33382         // padding
33383         stream.addProperty("padding:paddingLeft", mPaddingLeft);
33384         stream.addProperty("padding:paddingRight", mPaddingRight);
33385         stream.addProperty("padding:paddingTop", mPaddingTop);
33386         stream.addProperty("padding:paddingBottom", mPaddingBottom);
33387         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
33388         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
33389         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
33390         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
33391         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
33392 
33393         // measurement
33394         stream.addProperty("measurement:minHeight", mMinHeight);
33395         stream.addProperty("measurement:minWidth", mMinWidth);
33396         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
33397         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
33398 
33399         // drawing
33400         stream.addProperty("drawing:elevation", getElevation());
33401         stream.addProperty("drawing:translationX", getTranslationX());
33402         stream.addProperty("drawing:translationY", getTranslationY());
33403         stream.addProperty("drawing:translationZ", getTranslationZ());
33404         stream.addProperty("drawing:rotation", getRotation());
33405         stream.addProperty("drawing:rotationX", getRotationX());
33406         stream.addProperty("drawing:rotationY", getRotationY());
33407         stream.addProperty("drawing:scaleX", getScaleX());
33408         stream.addProperty("drawing:scaleY", getScaleY());
33409         stream.addProperty("drawing:pivotX", getPivotX());
33410         stream.addProperty("drawing:pivotY", getPivotY());
33411         stream.addProperty("drawing:clipBounds",
33412                 mClipBounds == null ? null : mClipBounds.toString());
33413         stream.addProperty("drawing:opaque", isOpaque());
33414         stream.addProperty("drawing:alpha", getAlpha());
33415         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
33416         stream.addProperty("drawing:shadow", hasShadow());
33417         stream.addProperty("drawing:solidColor", getSolidColor());
33418         stream.addProperty("drawing:layerType", mLayerType);
33419         stream.addProperty("drawing:willNotDraw", willNotDraw());
33420         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
33421         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
33422         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
33423         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
33424         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
33425         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
33426 
33427         // focus
33428         stream.addProperty("focus:hasFocus", hasFocus());
33429         stream.addProperty("focus:isFocused", isFocused());
33430         stream.addProperty("focus:focusable", getFocusable());
33431         stream.addProperty("focus:isFocusable", isFocusable());
33432         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
33433 
33434         stream.addProperty("misc:clickable", isClickable());
33435         stream.addProperty("misc:pressed", isPressed());
33436         stream.addProperty("misc:selected", isSelected());
33437         stream.addProperty("misc:touchMode", isInTouchMode());
33438         stream.addProperty("misc:hovered", isHovered());
33439         stream.addProperty("misc:activated", isActivated());
33440 
33441         stream.addProperty("misc:visibility", getVisibility());
33442         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
33443         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
33444 
33445         stream.addProperty("misc:enabled", isEnabled());
33446         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
33447         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
33448 
33449         // theme attributes
33450         Resources.Theme theme = getContext().getTheme();
33451         if (theme != null) {
33452             stream.addPropertyKey("theme");
33453             theme.encode(stream);
33454         }
33455 
33456         // view attribute information
33457         int n = mAttributes != null ? mAttributes.length : 0;
33458         stream.addProperty("meta:__attrCount__", n/2);
33459         for (int i = 0; i < n; i += 2) {
33460             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
33461         }
33462 
33463         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
33464 
33465         // text
33466         stream.addProperty("text:textDirection", getTextDirection());
33467         stream.addProperty("text:textAlignment", getTextAlignment());
33468 
33469         // accessibility
33470         CharSequence contentDescription = getContentDescription();
33471         stream.addUserProperty("accessibility:contentDescription",
33472                 contentDescription == null ? "" : contentDescription.toString());
33473         stream.addProperty("accessibility:labelFor", getLabelFor());
33474         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
33475     }
33476 
33477     /**
33478      * Determine if this view is rendered on a round wearable device and is the main view
33479      * on the screen.
33480      */
shouldDrawRoundScrollbar()33481     boolean shouldDrawRoundScrollbar() {
33482         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
33483             return false;
33484         }
33485 
33486         final View rootView = getRootView();
33487         final WindowInsets insets = getRootWindowInsets();
33488 
33489         int height = getHeight();
33490         int width = getWidth();
33491         int displayHeight = rootView.getHeight();
33492         int displayWidth = rootView.getWidth();
33493 
33494         if (height != displayHeight || width != displayWidth) {
33495             return false;
33496         }
33497 
33498         return true;
33499     }
33500 
33501     /**
33502      * Sets the tooltip text which will be displayed in a small popup next to the view.
33503      * <p>
33504      * The tooltip will be displayed:
33505      * <ul>
33506      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
33507      * menu). </li>
33508      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
33509      * </ul>
33510      * <p>
33511      * <strong>Note:</strong> Do not override this method, as it will have no
33512      * effect on the text displayed in the tooltip.
33513      *
33514      * @param tooltipText the tooltip text, or null if no tooltip is required
33515      * @see #getTooltipText()
33516      * @attr ref android.R.styleable#View_tooltipText
33517      */
setTooltipText(@ullable CharSequence tooltipText)33518     public void setTooltipText(@Nullable CharSequence tooltipText) {
33519         if (TextUtils.isEmpty(tooltipText)) {
33520             setFlags(0, TOOLTIP);
33521             hideTooltip();
33522             mTooltipInfo = null;
33523         } else {
33524             setFlags(TOOLTIP, TOOLTIP);
33525             if (mTooltipInfo == null) {
33526                 mTooltipInfo = new TooltipInfo();
33527                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
33528                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
33529                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
33530                 mTooltipInfo.clearAnchorPos();
33531             }
33532             mTooltipInfo.mTooltipText = tooltipText;
33533         }
33534     }
33535 
33536     /**
33537      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
33538      */
33539     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)33540     public void setTooltip(@Nullable CharSequence tooltipText) {
33541         setTooltipText(tooltipText);
33542     }
33543 
33544     /**
33545      * Returns the view's tooltip text.
33546      *
33547      * <strong>Note:</strong> Do not override this method, as it will have no
33548      * effect on the text displayed in the tooltip. You must call
33549      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
33550      *
33551      * @return the tooltip text
33552      * @see #setTooltipText(CharSequence)
33553      * @attr ref android.R.styleable#View_tooltipText
33554      */
33555     @InspectableProperty
33556     @Nullable
getTooltipText()33557     public CharSequence getTooltipText() {
33558         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
33559     }
33560 
33561     /**
33562      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
33563      */
33564     @Nullable
getTooltip()33565     public CharSequence getTooltip() {
33566         return getTooltipText();
33567     }
33568 
showTooltip(int x, int y, boolean fromLongClick)33569     private boolean showTooltip(int x, int y, boolean fromLongClick) {
33570         if (mAttachInfo == null || mTooltipInfo == null) {
33571             return false;
33572         }
33573         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
33574             return false;
33575         }
33576         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
33577             return false;
33578         }
33579         hideTooltip();
33580         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
33581         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
33582         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
33583         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
33584         mAttachInfo.mTooltipHost = this;
33585         // The available accessibility actions have changed
33586         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
33587         return true;
33588     }
33589 
33590     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hideTooltip()33591     void hideTooltip() {
33592         if (mTooltipInfo == null) {
33593             return;
33594         }
33595         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
33596         if (mTooltipInfo.mTooltipPopup == null) {
33597             return;
33598         }
33599         mTooltipInfo.mTooltipPopup.hide();
33600         mTooltipInfo.mTooltipPopup = null;
33601         mTooltipInfo.mTooltipFromLongClick = false;
33602         mTooltipInfo.clearAnchorPos();
33603         if (mAttachInfo != null) {
33604             mAttachInfo.mTooltipHost = null;
33605         }
33606         // The available accessibility actions have changed
33607         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
33608     }
33609 
showLongClickTooltip(int x, int y)33610     private boolean showLongClickTooltip(int x, int y) {
33611         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
33612         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
33613         return showTooltip(x, y, true);
33614     }
33615 
showHoverTooltip()33616     private boolean showHoverTooltip() {
33617         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
33618     }
33619 
dispatchTooltipHoverEvent(MotionEvent event)33620     boolean dispatchTooltipHoverEvent(MotionEvent event) {
33621         if (mTooltipInfo == null) {
33622             return false;
33623         }
33624         switch(event.getAction()) {
33625             case MotionEvent.ACTION_HOVER_MOVE:
33626                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
33627                     break;
33628                 }
33629                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
33630                     if (mTooltipInfo.mTooltipPopup == null) {
33631                         // Schedule showing the tooltip after a timeout.
33632                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
33633                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
33634                                 ViewConfiguration.getHoverTooltipShowTimeout());
33635                     }
33636 
33637                     // Hide hover-triggered tooltip after a period of inactivity.
33638                     // Match the timeout used by NativeInputManager to hide the mouse pointer
33639                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
33640                     final int timeout;
33641                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
33642                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
33643                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
33644                     } else {
33645                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
33646                     }
33647                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
33648                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
33649                 }
33650                 return true;
33651 
33652             case MotionEvent.ACTION_HOVER_EXIT:
33653                 mTooltipInfo.clearAnchorPos();
33654                 if (!mTooltipInfo.mTooltipFromLongClick) {
33655                     hideTooltip();
33656                 }
33657                 break;
33658         }
33659         return false;
33660     }
33661 
handleTooltipKey(KeyEvent event)33662     void handleTooltipKey(KeyEvent event) {
33663         switch (event.getAction()) {
33664             case KeyEvent.ACTION_DOWN:
33665                 if (event.getRepeatCount() == 0) {
33666                     hideTooltip();
33667                 }
33668                 break;
33669 
33670             case KeyEvent.ACTION_UP:
33671                 handleTooltipUp();
33672                 break;
33673         }
33674     }
33675 
handleTooltipUp()33676     private void handleTooltipUp() {
33677         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
33678             return;
33679         }
33680         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
33681         postDelayed(mTooltipInfo.mHideTooltipRunnable,
33682                 ViewConfiguration.getLongPressTooltipHideTimeout());
33683     }
33684 
getFocusableAttribute(TypedArray attributes)33685     private int getFocusableAttribute(TypedArray attributes) {
33686         TypedValue val = new TypedValue();
33687         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
33688             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
33689                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
33690             } else {
33691                 return val.data;
33692             }
33693         } else {
33694             return FOCUSABLE_AUTO;
33695         }
33696     }
33697 
33698     /**
33699      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
33700      * is not showing.
33701      * @hide
33702      */
33703     @TestApi
getTooltipView()33704     public View getTooltipView() {
33705         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
33706             return null;
33707         }
33708         return mTooltipInfo.mTooltipPopup.getContentView();
33709     }
33710 
33711     /**
33712      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
33713      * @hide
33714      */
33715     @TestApi
isDefaultFocusHighlightEnabled()33716     public static boolean isDefaultFocusHighlightEnabled() {
33717         return sUseDefaultFocusHighlight;
33718     }
33719 
33720     /**
33721      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
33722      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
33723      * (visually on-top views first).
33724      *
33725      * @param evt the previously unhandled {@link KeyEvent}.
33726      * @return the {@link View} which consumed the event or {@code null} if not consumed.
33727      */
dispatchUnhandledKeyEvent(KeyEvent evt)33728     View dispatchUnhandledKeyEvent(KeyEvent evt) {
33729         if (onUnhandledKeyEvent(evt)) {
33730             return this;
33731         }
33732         return null;
33733     }
33734 
33735     /**
33736      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
33737      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
33738      * this will dispatch into all the listeners registered via
33739      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
33740      * order (most recently added will receive events first).
33741      *
33742      * @param event An unhandled event.
33743      * @return {@code true} if the event was handled, {@code false} otherwise.
33744      * @see #addOnUnhandledKeyEventListener
33745      */
onUnhandledKeyEvent(@onNull KeyEvent event)33746     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
33747         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
33748             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
33749                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
33750                     return true;
33751                 }
33752             }
33753         }
33754         return false;
33755     }
33756 
hasUnhandledKeyListener()33757     boolean hasUnhandledKeyListener() {
33758         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
33759                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
33760     }
33761 
33762     /**
33763      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
33764      * UI thread.
33765      *
33766      * @param listener a receiver of unhandled {@link KeyEvent}s.
33767      * @see #removeOnUnhandledKeyEventListener
33768      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)33769     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
33770         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
33771         if (listeners == null) {
33772             listeners = new ArrayList<>();
33773             getListenerInfo().mUnhandledKeyListeners = listeners;
33774         }
33775         listeners.add(listener);
33776         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
33777             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
33778         }
33779     }
33780 
33781     /**
33782      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
33783      * UI thread.
33784      *
33785      * @param listener a receiver of unhandled {@link KeyEvent}s.
33786      * @see #addOnUnhandledKeyEventListener
33787      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)33788     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
33789         if (mListenerInfo != null) {
33790             if (mListenerInfo.mUnhandledKeyListeners != null
33791                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
33792                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
33793                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
33794                     mListenerInfo.mUnhandledKeyListeners = null;
33795                     if (mParent instanceof ViewGroup) {
33796                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
33797                     }
33798                 }
33799             }
33800         }
33801     }
33802 
33803     /**
33804      * Set the view to be detached or not detached.
33805      *
33806      * @param detached Whether the view is detached.
33807      *
33808      * @hide
33809      */
setDetached(boolean detached)33810     protected void setDetached(boolean detached) {
33811         if (detached) {
33812             mPrivateFlags4 |= PFLAG4_DETACHED;
33813         } else {
33814             mPrivateFlags4 &= ~PFLAG4_DETACHED;
33815         }
33816     }
33817 
33818     /**
33819      * Sets whether this view is a credential for Credential Manager purposes.
33820      *
33821      * <p>See {@link #isCredential()}.
33822      *
33823      * @param isCredential Whether the view is a credential.
33824      *
33825      * @attr ref android.R.styleable#View_isCredential
33826      */
setIsCredential(boolean isCredential)33827     public void setIsCredential(boolean isCredential) {
33828         if (isCredential) {
33829             mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
33830         } else {
33831             mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
33832         }
33833     }
33834 
33835     /**
33836      * Gets the mode for determining whether this view is a credential.
33837      *
33838      * <p>See {@link #setIsCredential(boolean)}.
33839      *
33840      * @return false by default, or value passed to {@link #setIsCredential(boolean)}.
33841      *
33842      * @attr ref android.R.styleable#View_isCredential
33843      */
isCredential()33844     public boolean isCredential() {
33845         return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER)
33846                 == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER);
33847     }
33848 
33849     // TODO(316208691): Revive following removed API docs.
33850     // @see EditorInfo#setStylusHandwritingEnabled(boolean)
33851     /**
33852      * Set whether this view enables automatic handwriting initiation.
33853      *
33854      * For a view with an active {@link InputConnection}, if auto handwriting is enabled then
33855      * stylus movement within its view boundary will automatically trigger the handwriting mode.
33856      * Check {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} for
33857      * more details about handwriting mode.
33858      *
33859      * If the View wants to initiate handwriting mode by itself, it can set this field to
33860      * {@code false} and call
33861      * {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} when there
33862      * is stylus movement detected.
33863      *
33864      * Note that this attribute has no effect on the View's children. For example, if a
33865      * {@link ViewGroup} disables auto handwriting but its children set auto handwriting to true,
33866      * auto handwriting will still work for the children, and vice versa.
33867      *
33868      * @see #onCreateInputConnection(EditorInfo)
33869      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
33870      * @param enabled whether auto handwriting initiation is enabled for this view.
33871      * @attr ref android.R.styleable#View_autoHandwritingEnabled
33872      */
setAutoHandwritingEnabled(boolean enabled)33873     public void setAutoHandwritingEnabled(boolean enabled) {
33874         if (enabled) {
33875             mPrivateFlags4 |= PFLAG4_AUTO_HANDWRITING_ENABLED;
33876         } else {
33877             mPrivateFlags4 &= ~PFLAG4_AUTO_HANDWRITING_ENABLED;
33878         }
33879         updatePositionUpdateListener();
33880         postUpdate(this::updateHandwritingArea);
33881     }
33882 
33883     /**
33884      * Return whether the View allows automatic handwriting initiation. Returns true if automatic
33885      * handwriting initiation is enabled, and vice versa.
33886      * @see #setAutoHandwritingEnabled(boolean)
33887      */
isAutoHandwritingEnabled()33888     public boolean isAutoHandwritingEnabled() {
33889         return (mPrivateFlags4 & PFLAG4_AUTO_HANDWRITING_ENABLED)
33890                 == PFLAG4_AUTO_HANDWRITING_ENABLED;
33891     }
33892 
33893     /**
33894      * Return whether the stylus handwriting is available for this View.
33895      * @hide
33896      */
isStylusHandwritingAvailable()33897     public boolean isStylusHandwritingAvailable() {
33898         return getContext().getSystemService(InputMethodManager.class)
33899                 .isStylusHandwritingAvailable();
33900     }
33901 
setTraversalTracingEnabled(boolean enabled)33902     private void setTraversalTracingEnabled(boolean enabled) {
33903         if (enabled) {
33904             if (mTracingStrings == null) {
33905                 mTracingStrings = new ViewTraversalTracingStrings(this);
33906             }
33907             mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
33908         } else {
33909             mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
33910         }
33911     }
33912 
isTraversalTracingEnabled()33913     private boolean isTraversalTracingEnabled() {
33914         return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
33915                 == PFLAG4_TRAVERSAL_TRACING_ENABLED;
33916     }
33917 
setRelayoutTracingEnabled(boolean enabled)33918     private void setRelayoutTracingEnabled(boolean enabled) {
33919         if (enabled) {
33920             if (mTracingStrings == null) {
33921                 mTracingStrings = new ViewTraversalTracingStrings(this);
33922             }
33923             mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
33924         } else {
33925             mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
33926         }
33927     }
33928 
isRelayoutTracingEnabled()33929     private boolean isRelayoutTracingEnabled() {
33930         return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
33931                 == PFLAG4_RELAYOUT_TRACING_ENABLED;
33932     }
33933 
33934     /**
33935      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
33936      * the view.
33937      *
33938      * <p>The default implementation does nothing.</p>
33939      *
33940      * @param supportedFormats the supported translation formats. For now, the only possible value
33941      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
33942      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to
33943      * collect the information to be translated in the view. The {@code requestsCollector} only
33944      * accepts one request; an IllegalStateException is thrown if more than one
33945      * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the
33946      * {@link ViewTranslationRequest}.
33947      */
onCreateViewTranslationRequest(@onNull @ataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)33948     public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
33949             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
33950     }
33951 
33952     /**
33953      * Collects {@link ViewTranslationRequest}s which represents the content to be translated
33954      * for the virtual views in the host view. This is called if this view returned a virtual
33955      * view structure from {@link #onProvideContentCaptureStructure} and the system determined that
33956      * those virtual views were relevant for translation.
33957      *
33958      * <p>The default implementation does nothing.</p>
33959      *
33960      * @param virtualIds the virtual view ids which represents the virtual views in the host
33961      * view.
33962      * @param supportedFormats the supported translation formats. For now, the only possible value
33963      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
33964      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
33965      * multiple times to collect the information to be translated in the host view. One
33966      * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
33967      * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
33968      * Consumer after the method returns.
33969      */
33970     @SuppressLint("NullableCollection")
onCreateVirtualViewTranslationRequests(@onNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)33971     public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
33972             @NonNull @DataFormat int[] supportedFormats,
33973             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
33974         // no-op
33975     }
33976 
33977     /**
33978      * Returns a {@link ViewTranslationCallback} that is used to display the translated information
33979      * or {@code null} if this View doesn't support translation.
33980      *
33981      * @hide
33982      */
33983     @Nullable
getViewTranslationCallback()33984     public ViewTranslationCallback getViewTranslationCallback() {
33985         return mViewTranslationCallback;
33986     }
33987 
33988     /**
33989      * Sets a {@link ViewTranslationCallback} that is used to display/hide the translated
33990      * information. Developers can provide the customized implementation for show/hide translated
33991      * information.
33992      *
33993      * @param callback a {@link ViewTranslationCallback} that is used to control how to display the
33994      * translated information
33995      */
setViewTranslationCallback(@onNull ViewTranslationCallback callback)33996     public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
33997         mViewTranslationCallback = callback;
33998     }
33999 
34000     /**
34001      * Clear the {@link ViewTranslationCallback} from this view.
34002      */
clearViewTranslationCallback()34003     public void clearViewTranslationCallback() {
34004         mViewTranslationCallback = null;
34005     }
34006 
34007     /**
34008      * Returns the {@link ViewTranslationResponse} associated with this view. The response will be
34009      * set when the translation is done then {@link #onViewTranslationResponse} is called. The
34010      * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the
34011      * translated information.
34012      *
34013      * @return a {@link ViewTranslationResponse} that contains the translated information associated
34014      * with this view or {@code null} if this View doesn't have the translation.
34015      */
34016     @Nullable
getViewTranslationResponse()34017     public ViewTranslationResponse getViewTranslationResponse() {
34018         return mViewTranslationResponse;
34019     }
34020 
34021     /**
34022      * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated
34023      * by the TranslationService. The {@link ViewTranslationResponse} should be saved here so that
34024      * the {@link ViewTranslationResponse} can be used to display the translation when the system
34025      * calls {@link ViewTranslationCallback#onShowTranslation}.
34026      *
34027      * <p> The default implementation will set the ViewTranslationResponse that can be get from
34028      * {@link View#getViewTranslationResponse}. </p>
34029      *
34030      * @param response a {@link ViewTranslationResponse} that contains the translated information
34031      * which can be shown in the view.
34032      */
onViewTranslationResponse(@onNull ViewTranslationResponse response)34033     public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
34034         mViewTranslationResponse = response;
34035     }
34036 
34037     /**
34038      * Clears the ViewTranslationResponse stored by the default implementation of {@link
34039      * #onViewTranslationResponse}.
34040      *
34041      * @hide
34042      */
clearViewTranslationResponse()34043     public void clearViewTranslationResponse() {
34044         mViewTranslationResponse = null;
34045     }
34046 
34047     /**
34048      * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
34049      * translated by the TranslationService.
34050      *
34051      * <p> The default implementation does nothing.</p>
34052      *
34053      * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
34054      * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information
34055      * which can be shown in the view. The key of SparseArray is the virtual child ids.
34056      */
onVirtualViewTranslationResponses( @onNull LongSparseArray<ViewTranslationResponse> response)34057     public void onVirtualViewTranslationResponses(
34058             @NonNull LongSparseArray<ViewTranslationResponse> response) {
34059         // no-op
34060     }
34061 
34062     /**
34063      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
34064      * the hierarchy when the app requests ui translation. Typically, this method should only be
34065      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
34066      * classes should override {@link View#onCreateViewTranslationRequest} for normal view or
34067      * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children.
34068      * When requested to start the ui translation, the system will call this method to traverse the
34069      * view hierarchy to collect {@link ViewTranslationRequest}s and create a
34070      * {@link android.view.translation.Translator} to translate the requests. All the
34071      * {@link ViewTranslationRequest}s must be added when the traversal is done.
34072      *
34073      * <p> The default implementation calls {@link View#onCreateViewTranslationRequest} for normal
34074      * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
34075      * children to build {@link ViewTranslationRequest} if the view should be translated.
34076      * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
34077      * recycling of views doesn't prevent the system from attaching the response to it. Therefore,
34078      * if overriding this method, you should set or reset the transient state. </p>
34079      *
34080      * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
34081      * {@code null} if the view doesn't have virtual child that should be translated. The virtual
34082      * child ids are the same virtual ids provided by ContentCapture.
34083      * @param supportedFormats the supported translation formats. For now, the only possible value
34084      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
34085      * @param capability a {@link TranslationCapability} that holds translation capability.
34086      * information, e.g. source spec, target spec.
34087      * @param requests fill in with {@link ViewTranslationRequest}s for translation purpose.
34088      */
dispatchCreateViewTranslationRequest(@onNull Map<AutofillId, long[]> viewIds, @NonNull @DataFormat int[] supportedFormats, @NonNull TranslationCapability capability, @NonNull List<ViewTranslationRequest> requests)34089     public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
34090             @NonNull @DataFormat int[] supportedFormats,
34091             @NonNull TranslationCapability capability,
34092             @NonNull List<ViewTranslationRequest> requests) {
34093         AutofillId autofillId = getAutofillId();
34094         if (viewIds.containsKey(autofillId)) {
34095             if (viewIds.get(autofillId) == null) {
34096                 // TODO: avoiding the allocation per view
34097                 onCreateViewTranslationRequest(supportedFormats,
34098                         new ViewTranslationRequestConsumer(requests));
34099             } else {
34100                 onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
34101                         request -> {
34102                             requests.add(request);
34103                         });
34104             }
34105         }
34106     }
34107 
34108     private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
34109         private final List<ViewTranslationRequest> mRequests;
34110         private boolean mCalled;
34111 
ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests)34112         ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
34113             mRequests = requests;
34114         }
34115 
34116         @Override
accept(ViewTranslationRequest request)34117         public void accept(ViewTranslationRequest request) {
34118             if (mCalled) {
34119                 throw new IllegalStateException("The translation Consumer is not reusable.");
34120             }
34121             mCalled = true;
34122             if (request != null && request.getKeys().size() > 0) {
34123                 mRequests.add(request);
34124                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
34125                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
34126                             + getAutofillId());
34127                 }
34128                 setHasTransientState(true);
34129                 setHasTranslationTransientState(true);
34130             }
34131         }
34132     }
34133 
34134     /**
34135      * Called to generate a {@link DisplayHash} for this view.
34136      *
34137      * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
34138      *                      the values returned from
34139      *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
34140      * @param bounds The bounds for the content within the View to generate the hash for. If
34141      *               bounds are null, the entire View's bounds will be used. If empty, it will
34142      *               invoke the callback
34143      *               {@link DisplayHashResultCallback#onDisplayHashError} with error
34144      *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
34145      * @param executor The executor that the callback should be invoked on.
34146      * @param callback The callback to handle the results of generating the display hash
34147      */
generateDisplayHash(@onNull String hashAlgorithm, @Nullable Rect bounds, @NonNull Executor executor, @NonNull DisplayHashResultCallback callback)34148     public void generateDisplayHash(@NonNull String hashAlgorithm,
34149             @Nullable Rect bounds, @NonNull Executor executor,
34150             @NonNull DisplayHashResultCallback callback) {
34151         IWindowSession session = getWindowSession();
34152         if (session == null) {
34153             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
34154             return;
34155         }
34156         IWindow window = getWindow();
34157         if (window == null) {
34158             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
34159             return;
34160         }
34161 
34162         Rect visibleBounds = new Rect();
34163         getGlobalVisibleRect(visibleBounds);
34164 
34165         if (bounds != null && bounds.isEmpty()) {
34166             callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
34167             return;
34168         }
34169 
34170         if (bounds != null) {
34171             bounds.offset(visibleBounds.left, visibleBounds.top);
34172             visibleBounds.intersectUnchecked(bounds);
34173         }
34174 
34175         if (visibleBounds.isEmpty()) {
34176             callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
34177             return;
34178         }
34179 
34180         RemoteCallback remoteCallback = new RemoteCallback(result ->
34181                 executor.execute(() -> {
34182                     DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH, android.view.displayhash.DisplayHash.class);
34183                     int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
34184                             DISPLAY_HASH_ERROR_UNKNOWN);
34185                     if (displayHash != null) {
34186                         callback.onDisplayHashResult(displayHash);
34187                     } else {
34188                         callback.onDisplayHashError(errorCode);
34189                     }
34190                 }));
34191 
34192         try {
34193             session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
34194         } catch (RemoteException e) {
34195             Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
34196             callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
34197         }
34198     }
34199 
34200     /**
34201      * The AttachedSurfaceControl itself is not a View, it is just the interface to the
34202      * windowing-system object that contains the entire view hierarchy.
34203      * For the root View of a given hierarchy see {@link #getRootView}.
34204 
34205      * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
34206      * This will only return a non-null value when called between {@link #onAttachedToWindow}
34207      * and {@link #onDetachedFromWindow}.
34208      */
getRootSurfaceControl()34209     public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
34210         if (mAttachInfo != null) {
34211           return mAttachInfo.getRootSurfaceControl();
34212         }
34213         return null;
34214     }
34215 
34216     /**
34217      * Used to calculate the frame rate category of a View.
34218      *
34219      * @hide
34220      */
calculateFrameRateCategory()34221     protected int calculateFrameRateCategory() {
34222         ViewRootImpl viewRootImpl = getViewRootImpl();
34223         ViewParent parent = mParent;
34224         boolean isInputMethodWindowType =
34225                 viewRootImpl.mWindowAttributes.type == TYPE_INPUT_METHOD;
34226 
34227         // boost frame rate when the position or the size changed.
34228         if (((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
34229                 PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
34230                 || mLastFrameTop != mTop)
34231                 && viewRootImpl.shouldCheckFrameRateCategory()
34232                 && parent instanceof View
34233                 && ((View) parent).getFrameContentVelocity() <= 0
34234                 && !isInputMethodWindowType
34235                 && viewRootImpl.getFrameRateCompatibility() != FRAME_RATE_COMPATIBILITY_AT_LEAST) {
34236 
34237             return FRAME_RATE_CATEGORY_HIGH_HINT | FRAME_RATE_CATEGORY_REASON_BOOST;
34238         }
34239         int category;
34240         switch (viewRootImpl.intermittentUpdateState()) {
34241             case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT -> {
34242                 if (!sToolkitFrameRateBySizeReadOnlyFlagValue) {
34243                     category = FRAME_RATE_CATEGORY_NORMAL;
34244                 } else {
34245                     // The size based frame rate category can only be LOW or NORMAL. If the size
34246                     // based frame rate category is LOW, we shouldn't vote for NORMAL for
34247                     // intermittent.
34248                     category = Math.min(
34249                             mSizeBasedFrameRateCategoryAndReason & ~FRAME_RATE_CATEGORY_REASON_MASK,
34250                             FRAME_RATE_CATEGORY_NORMAL);
34251                 }
34252                 category |= FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
34253             }
34254             case ViewRootImpl.INTERMITTENT_STATE_NOT_INTERMITTENT ->
34255                     category = mSizeBasedFrameRateCategoryAndReason;
34256             default -> category = mLastFrameRateCategory;
34257         }
34258         return category;
34259     }
34260 
34261     /**
34262      * Used to vote the preferred frame rate and frame rate category to ViewRootImpl
34263      *
34264      * @hide
34265      */
votePreferredFrameRate()34266     protected void votePreferredFrameRate() {
34267         // use toolkitSetFrameRate flag to gate the change
34268         ViewRootImpl viewRootImpl = getViewRootImpl();
34269         if (viewRootImpl == null) {
34270             return; // can't vote if not connected
34271         }
34272         float velocity = mFrameContentVelocity;
34273         final float frameRate = mPreferredFrameRate;
34274 
34275         if (viewRootImpl.shouldCheckFrameRate(frameRate > 0f)
34276                 && (frameRate > 0 || (mAttachInfo.mViewVelocityApi && velocity > 0f))) {
34277             float velocityFrameRate = 0f;
34278             if (mAttachInfo.mViewVelocityApi && velocity > 0f) {
34279                 velocityFrameRate = convertVelocityToFrameRate(velocity);
34280             }
34281             int compatibility;
34282             float frameRateToSet;
34283             if (frameRate >= velocityFrameRate) {
34284                 compatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
34285                 frameRateToSet = frameRate;
34286             } else {
34287                 compatibility = FRAME_RATE_COMPATIBILITY_AT_LEAST;
34288                 frameRateToSet = velocityFrameRate;
34289             }
34290             viewRootImpl.votePreferredFrameRate(frameRateToSet, compatibility);
34291 
34292             if (Trace.isTagEnabled(TRACE_TAG_VIEW)) {
34293                 Trace.instant(TRACE_TAG_VIEW,
34294                         getClass().getSimpleName()
34295                             + " - votePreferredFrameRate: " + frameRateToSet);
34296             }
34297         }
34298 
34299         if (viewRootImpl.shouldCheckFrameRateCategory()) {
34300             if (sToolkitMetricsForFrameRateDecisionFlagValue) {
34301                 int width = mRight - mLeft;
34302                 int height = mBottom - mTop;
34303                 float sizePercentage = width * height / mAttachInfo.mDisplayPixelCount;
34304                 viewRootImpl.recordViewPercentage(sizePercentage);
34305             }
34306 
34307             int frameRateCategory;
34308             if (Float.isNaN(frameRate)) {
34309                 frameRateCategory = calculateFrameRateCategory();
34310             } else if (frameRate < 0) {
34311                 switch ((int) frameRate) {
34312                     case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->
34313                             frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
34314                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34315                     case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->
34316                             frameRateCategory = FRAME_RATE_CATEGORY_LOW
34317                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34318                     case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->
34319                             frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
34320                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34321                     case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->
34322                             frameRateCategory = FRAME_RATE_CATEGORY_HIGH
34323                                     | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34324                     default -> {
34325                         // invalid frame rate, use default
34326                         int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
34327                                 ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
34328                         frameRateCategory = category
34329                                 | FRAME_RATE_CATEGORY_REASON_INVALID;
34330                     }
34331                 }
34332 
34333                 if (Trace.isTagEnabled(TRACE_TAG_VIEW)) {
34334                     Trace.instant(TRACE_TAG_VIEW,
34335                             getClass().getSimpleName() + " - votePreferredFrameRate: "
34336                                 + viewRootImpl.categoryToString(
34337                                     frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK));
34338                 }
34339             } else {
34340                 // Category doesn't control it. It is directly controlled by frame rate
34341                 frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
34342                         | FRAME_RATE_CATEGORY_REASON_REQUESTED;
34343             }
34344 
34345             int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
34346             int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
34347             viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
34348             mLastFrameRateCategory = frameRateCategory;
34349         }
34350         mLastFrameLeft = mLeft;
34351         mLastFrameTop = mTop;
34352     }
34353 
convertVelocityToFrameRate(float velocityPps)34354     private float convertVelocityToFrameRate(float velocityPps) {
34355         // Internal testing has shown that this gives a premium experience:
34356         // above 300dp/s => 120fps
34357         // between 300dp/s and 125fps => 80fps
34358         // below 125dp/s => 60fps
34359         float density = mAttachInfo.mDensity;
34360         float velocityDps = velocityPps / density;
34361         float frameRate;
34362         if (velocityDps > 300f) {
34363             frameRate = MAX_FRAME_RATE; // Use maximum at fast motion
34364         } else if (velocityDps > 125f) {
34365             frameRate = 80f; // Use medium frame rate when motion is slower
34366         } else {
34367             frameRate = 60f; // Use minimum frame rate when motion is very slow
34368         }
34369         return frameRate;
34370     }
34371 
34372     /**
34373      * Set the current velocity of the View, we only track positive value.
34374      * We will use the velocity information to adjust the frame rate when applicable.
34375      * For example, we could potentially lower the frame rate when
34376      * the velocity of a fling gesture becomes slower.
34377      * Note that this is only valid till the next drawn frame.
34378      *
34379      * @param pixelsPerSecond how many pixels move per second.
34380      */
34381     @FlaggedApi(FLAG_VIEW_VELOCITY_API)
setFrameContentVelocity(float pixelsPerSecond)34382     public void setFrameContentVelocity(float pixelsPerSecond) {
34383         if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
34384             mFrameContentVelocity = Math.abs(pixelsPerSecond);
34385 
34386             if (sToolkitMetricsForFrameRateDecisionFlagValue) {
34387                 Trace.setCounter("Set frame velocity", (long) mFrameContentVelocity);
34388             }
34389         }
34390     }
34391 
34392     /**
34393      * Get the current velocity of the View.
34394      * The value should always be greater than or equal to 0.
34395      * Note that this is only valid till the next drawn frame.
34396      *
34397      * @return 0 by default, or value passed to {@link #setFrameContentVelocity(float)}.
34398      */
34399     @FlaggedApi(FLAG_VIEW_VELOCITY_API)
getFrameContentVelocity()34400     public float getFrameContentVelocity() {
34401         if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
34402             return Math.max(mFrameContentVelocity, 0f);
34403         }
34404         return 0;
34405     }
34406 
34407     /**
34408      * You can set the preferred frame rate for a View using a positive number
34409      * or by specifying the preferred frame rate category using constants, including
34410      * REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE, REQUESTED_FRAME_RATE_CATEGORY_LOW,
34411      * REQUESTED_FRAME_RATE_CATEGORY_NORMAL, REQUESTED_FRAME_RATE_CATEGORY_HIGH.
34412      * Keep in mind that the preferred frame rate affects the frame rate for the next frame,
34413      * so use this method carefully. It's important to note that the preference is valid as
34414      * long as the View is invalidated. Please also be aware that the requested frame rate
34415      * will not propagate to child views when this API is used on a ViewGroup.
34416      *
34417      * @param frameRate the preferred frame rate of the view.
34418      */
34419     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
setRequestedFrameRate(float frameRate)34420     public void setRequestedFrameRate(float frameRate) {
34421         // Skip setting the frame rate if it's currently in forced override mode.
34422         if (sToolkitViewGroupFrameRateApiFlagValue && getForcedOverrideFrameRateFlag()) {
34423             return;
34424         }
34425 
34426         if (sToolkitSetFrameRateReadOnlyFlagValue) {
34427             mPreferredFrameRate = frameRate;
34428         }
34429 
34430         if (sToolkitViewGroupFrameRateApiFlagValue) {
34431             // If frameRate is Float.NaN, it means it's set to the default value.
34432             // We only want to make the flag true, when the value is not Float.nan
34433             setSelfRequestedFrameRateFlag(!Float.isNaN(mPreferredFrameRate));
34434         }
34435     }
34436 
34437     /**
34438      * Get the current preferred frame rate of the View.
34439      * The value could be negative when preferred frame rate category is set
34440      * instead of perferred frame rate.
34441      * The frame rate category includes
34442      * REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE, REQUESTED_FRAME_RATE_CATEGORY_LOW,
34443      * REQUESTED_FRAME_RATE_CATEGORY_NORMAL, and REQUESTED_FRAME_RATE_CATEGORY_HIGH.
34444      * Note that the frame rate value is valid as long as the View is invalidated.
34445      * Please also be aware that the requested frame rate will not propagate to
34446      * child views when this API is used on a ViewGroup.
34447      *
34448      * @return REQUESTED_FRAME_RATE_CATEGORY_DEFAULT by default,
34449      * or value passed to {@link #setRequestedFrameRate(float)}.
34450      */
34451     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
getRequestedFrameRate()34452     public float getRequestedFrameRate() {
34453         if (sToolkitSetFrameRateReadOnlyFlagValue) {
34454             return mPreferredFrameRate;
34455         }
34456         return 0;
34457     }
34458 
overrideFrameRate(float frameRate, boolean forceOverride)34459     void overrideFrameRate(float frameRate, boolean forceOverride) {
34460         setForcedOverrideFrameRateFlag(forceOverride);
34461         if (forceOverride || !getSelfRequestedFrameRateFlag()) {
34462             mPreferredFrameRate = frameRate;
34463         }
34464     }
34465 
setForcedOverrideFrameRateFlag(boolean forcedOverride)34466     void setForcedOverrideFrameRateFlag(boolean forcedOverride) {
34467         if (forcedOverride) {
34468             mPrivateFlags4 |= PFLAG4_FORCED_OVERRIDE_FRAME_RATE;
34469         } else {
34470             mPrivateFlags4 &= ~PFLAG4_FORCED_OVERRIDE_FRAME_RATE;
34471         }
34472     }
34473 
getForcedOverrideFrameRateFlag()34474     boolean getForcedOverrideFrameRateFlag() {
34475         return (mPrivateFlags4 & PFLAG4_FORCED_OVERRIDE_FRAME_RATE) != 0;
34476     }
34477 
setSelfRequestedFrameRateFlag(boolean forcedOverride)34478     void setSelfRequestedFrameRateFlag(boolean forcedOverride) {
34479         if (forcedOverride) {
34480             mPrivateFlags4 |= PFLAG4_SELF_REQUESTED_FRAME_RATE;
34481         } else {
34482             mPrivateFlags4 &= ~PFLAG4_SELF_REQUESTED_FRAME_RATE;
34483         }
34484     }
34485 
getSelfRequestedFrameRateFlag()34486     boolean getSelfRequestedFrameRateFlag() {
34487         return (mPrivateFlags4 & PFLAG4_SELF_REQUESTED_FRAME_RATE) != 0;
34488     }
34489 
34490     /**
34491      * Called from apps when they want to report jank stats to the system.
34492      * @param appJankStats the stats that will be merged with the stats collected by the system.
34493      */
34494     @FlaggedApi(android.app.jank.Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
reportAppJankStats(@onNull AppJankStats appJankStats)34495     public void reportAppJankStats(@NonNull AppJankStats appJankStats) {
34496         View rootView = getRootView();
34497         if (rootView == this) return;
34498 
34499         rootView.reportAppJankStats(appJankStats);
34500     }
34501 
34502     /**
34503      * Called by widgets to get a reference to JankTracker in order to update states.
34504      * @hide
34505      */
getJankTracker()34506     public @Nullable JankTracker getJankTracker() {
34507         View rootView = getRootView();
34508         if (rootView == this) {
34509             return null;
34510         }
34511         return rootView.getJankTracker();
34512     }
34513 }
34514